mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
softgpu: Prepare more state per prim call.
This commit is contained in:
parent
9ec7d65c49
commit
d5c5e9478e
8 changed files with 128 additions and 130 deletions
|
@ -127,7 +127,7 @@ static void RotateUVThrough(const VertexData &tl, const VertexData &br, VertexDa
|
|||
}
|
||||
}
|
||||
|
||||
void ProcessTriangleInternal(VertexData &v0, VertexData &v1, VertexData &v2, const VertexData &provoking, const PixelFuncID &pixelID, const SamplerID &samplerID, bool fromRectangle);
|
||||
void ProcessTriangleInternal(VertexData &v0, VertexData &v1, VertexData &v2, const VertexData &provoking, const Rasterizer::RasterizerState &state, bool fromRectangle);
|
||||
|
||||
static inline bool CheckOutsideZ(ClipCoords p, int &pos, int &neg) {
|
||||
constexpr float outsideValue = 1.000030517578125f;
|
||||
|
@ -143,7 +143,7 @@ static inline bool CheckOutsideZ(ClipCoords p, int &pos, int &neg) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void ProcessRect(const VertexData &v0, const VertexData &v1, const PixelFuncID &pixelID, const SamplerID &samplerID) {
|
||||
void ProcessRect(const VertexData &v0, const VertexData &v1, const Rasterizer::RasterizerState &state) {
|
||||
if (!gstate.isModeThrough()) {
|
||||
// We may discard the entire rect based on depth values.
|
||||
int outsidePos = 0, outsideNeg = 0;
|
||||
|
@ -191,14 +191,14 @@ void ProcessRect(const VertexData &v0, const VertexData &v1, const PixelFuncID &
|
|||
}
|
||||
|
||||
// Four triangles to do backfaces as well. Two of them will get backface culled.
|
||||
ProcessTriangleInternal(*topleft, *topright, *bottomright, buf[3], pixelID, samplerID, true);
|
||||
ProcessTriangleInternal(*bottomright, *topright, *topleft, buf[3], pixelID, samplerID, true);
|
||||
ProcessTriangleInternal(*bottomright, *bottomleft, *topleft, buf[3], pixelID, samplerID, true);
|
||||
ProcessTriangleInternal(*topleft, *bottomleft, *bottomright, buf[3], pixelID, samplerID, true);
|
||||
ProcessTriangleInternal(*topleft, *topright, *bottomright, buf[3], state, true);
|
||||
ProcessTriangleInternal(*bottomright, *topright, *topleft, buf[3], state, true);
|
||||
ProcessTriangleInternal(*bottomright, *bottomleft, *topleft, buf[3], state, true);
|
||||
ProcessTriangleInternal(*topleft, *bottomleft, *bottomright, buf[3], state, true);
|
||||
} else {
|
||||
// through mode handling
|
||||
|
||||
if (Rasterizer::RectangleFastPath(v0, v1, pixelID, samplerID)) {
|
||||
if (Rasterizer::RectangleFastPath(v0, v1, state)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -240,26 +240,26 @@ void ProcessRect(const VertexData &v0, const VertexData &v1, const PixelFuncID &
|
|||
RotateUVThrough(v0, v1, *topright, *bottomleft);
|
||||
|
||||
if (gstate.isModeClear()) {
|
||||
Rasterizer::ClearRectangle(v0, v1, pixelID, samplerID);
|
||||
Rasterizer::ClearRectangle(v0, v1, state);
|
||||
} else {
|
||||
// Four triangles to do backfaces as well. Two of them will get backface culled.
|
||||
Rasterizer::DrawTriangle(*topleft, *topright, *bottomleft, pixelID, samplerID);
|
||||
Rasterizer::DrawTriangle(*bottomleft, *topright, *topleft, pixelID, samplerID);
|
||||
Rasterizer::DrawTriangle(*topright, *bottomright, *bottomleft, pixelID, samplerID);
|
||||
Rasterizer::DrawTriangle(*bottomleft, *bottomright, *topright, pixelID, samplerID);
|
||||
Rasterizer::DrawTriangle(*topleft, *topright, *bottomleft, state);
|
||||
Rasterizer::DrawTriangle(*bottomleft, *topright, *topleft, state);
|
||||
Rasterizer::DrawTriangle(*topright, *bottomright, *bottomleft, state);
|
||||
Rasterizer::DrawTriangle(*bottomleft, *bottomright, *topright, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessPoint(VertexData &v0, const PixelFuncID &pixelID, const SamplerID &samplerID) {
|
||||
void ProcessPoint(VertexData &v0, const Rasterizer::RasterizerState &state) {
|
||||
// Points need no clipping. Will be bounds checked in the rasterizer (which seems backwards?)
|
||||
Rasterizer::DrawPoint(v0, pixelID, samplerID);
|
||||
Rasterizer::DrawPoint(v0, state);
|
||||
}
|
||||
|
||||
void ProcessLine(VertexData &v0, VertexData &v1, const PixelFuncID &pixelID, const SamplerID &samplerID) {
|
||||
void ProcessLine(VertexData &v0, VertexData &v1, const Rasterizer::RasterizerState &state) {
|
||||
if (gstate.isModeThrough()) {
|
||||
// Actually, should clip this one too so we don't need to do bounds checks in the rasterizer.
|
||||
Rasterizer::DrawLine(v0, v1, pixelID, samplerID);
|
||||
Rasterizer::DrawLine(v0, v1, state);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -286,19 +286,19 @@ void ProcessLine(VertexData &v0, VertexData &v1, const PixelFuncID &pixelID, con
|
|||
VertexData data[2] = { *Vertices[0], *Vertices[1] };
|
||||
data[0].screenpos = TransformUnit::ClipToScreen(data[0].clippos);
|
||||
data[1].screenpos = TransformUnit::ClipToScreen(data[1].clippos);
|
||||
Rasterizer::DrawLine(data[0], data[1], pixelID, samplerID);
|
||||
Rasterizer::DrawLine(data[0], data[1], state);
|
||||
}
|
||||
|
||||
void ProcessTriangleInternal(VertexData &v0, VertexData &v1, VertexData &v2, const VertexData &provoking, const PixelFuncID &pixelID, const SamplerID &samplerID, bool fromRectangle) {
|
||||
void ProcessTriangleInternal(VertexData &v0, VertexData &v1, VertexData &v2, const VertexData &provoking, const Rasterizer::RasterizerState &state, bool fromRectangle) {
|
||||
if (gstate.isModeThrough()) {
|
||||
// In case of cull reordering, make sure the right color is on the final vertex.
|
||||
if (gstate.getShadeMode() == GE_SHADE_FLAT) {
|
||||
VertexData corrected2 = v2;
|
||||
corrected2.color0 = provoking.color0;
|
||||
corrected2.color1 = provoking.color1;
|
||||
Rasterizer::DrawTriangle(v0, v1, corrected2, pixelID, samplerID);
|
||||
Rasterizer::DrawTriangle(v0, v1, corrected2, state);
|
||||
} else {
|
||||
Rasterizer::DrawTriangle(v0, v1, v2, pixelID, samplerID);
|
||||
Rasterizer::DrawTriangle(v0, v1, v2, state);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -382,13 +382,13 @@ void ProcessTriangleInternal(VertexData &v0, VertexData &v1, VertexData &v2, con
|
|||
data[2].color1 = provoking.color1;
|
||||
}
|
||||
|
||||
Rasterizer::DrawTriangle(data[0], data[1], data[2], pixelID, samplerID);
|
||||
Rasterizer::DrawTriangle(data[0], data[1], data[2], state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessTriangle(VertexData &v0, VertexData &v1, VertexData &v2, const VertexData &provoking, const PixelFuncID &pixelID, const SamplerID &samplerID) {
|
||||
ProcessTriangleInternal(v0, v1, v2, provoking, pixelID, samplerID, false);
|
||||
void ProcessTriangle(VertexData &v0, VertexData &v1, VertexData &v2, const VertexData &provoking, const Rasterizer::RasterizerState &state) {
|
||||
ProcessTriangleInternal(v0, v1, v2, provoking, state, false);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -22,11 +22,15 @@
|
|||
struct PixelFuncID;
|
||||
struct SamplerID;
|
||||
|
||||
namespace Rasterizer {
|
||||
struct RasterizerState;
|
||||
};
|
||||
|
||||
namespace Clipper {
|
||||
|
||||
void ProcessPoint(VertexData &v0, const PixelFuncID &pixelID, const SamplerID &samplerID);
|
||||
void ProcessLine(VertexData &v0, VertexData &v1, const PixelFuncID &pixelID, const SamplerID &samplerID);
|
||||
void ProcessTriangle(VertexData &v0, VertexData &v1, VertexData &v2, const VertexData &provoking, const PixelFuncID &pixelID, const SamplerID &samplerID);
|
||||
void ProcessRect(const VertexData &v0, const VertexData &v1, const PixelFuncID &pixelID, const SamplerID &samplerID);
|
||||
void ProcessPoint(VertexData &v0, const Rasterizer::RasterizerState &state);
|
||||
void ProcessLine(VertexData &v0, VertexData &v1, const Rasterizer::RasterizerState &state);
|
||||
void ProcessTriangle(VertexData &v0, VertexData &v1, VertexData &v2, const VertexData &provoking, const Rasterizer::RasterizerState &state);
|
||||
void ProcessRect(const VertexData &v0, const VertexData &v1, const Rasterizer::RasterizerState &state);
|
||||
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "GPU/Software/Rasterizer.h"
|
||||
#include "GPU/Software/Sampler.h"
|
||||
#include "GPU/Software/SoftGpu.h"
|
||||
#include "GPU/Software/TransformUnit.h"
|
||||
|
||||
#if defined(_M_SSE)
|
||||
#include <emmintrin.h>
|
||||
|
@ -477,18 +478,18 @@ Vec3<int> AlphaBlendingResult(const PixelFuncID &pixelID, const Vec4<int> &sourc
|
|||
}
|
||||
}
|
||||
|
||||
static inline Vec4IntResult SOFTRAST_CALL ApplyTexturing(float s, float t, int x, int y, Vec4IntArg prim_color, u8 *texptr[], int texbufw[], int texlevel, int frac_texlevel, bool bilinear, Sampler::Funcs sampler) {
|
||||
static inline Vec4IntResult SOFTRAST_CALL ApplyTexturing(float s, float t, int x, int y, Vec4IntArg prim_color, u8 *texptr[], int texbufw[], int texlevel, int frac_texlevel, bool bilinear, const RasterizerState &state) {
|
||||
const u8 **tptr0 = const_cast<const u8 **>(&texptr[texlevel]);
|
||||
const int *bufw0 = &texbufw[texlevel];
|
||||
|
||||
if (!bilinear) {
|
||||
return sampler.nearest(s, t, x, y, prim_color, tptr0, bufw0, texlevel, frac_texlevel);
|
||||
return state.nearest(s, t, x, y, prim_color, tptr0, bufw0, texlevel, frac_texlevel);
|
||||
}
|
||||
return sampler.linear(s, t, x, y, prim_color, tptr0, bufw0, texlevel, frac_texlevel);
|
||||
return state.linear(s, t, x, y, prim_color, tptr0, bufw0, texlevel, frac_texlevel);
|
||||
}
|
||||
|
||||
static inline Vec4IntResult SOFTRAST_CALL ApplyTexturingSingle(float s, float t, int x, int y, Vec4IntArg prim_color, u8 *texptr[], int texbufw[], int texlevel, int frac_texlevel, bool bilinear, Sampler::Funcs sampler) {
|
||||
return ApplyTexturing(s, t, ((x & 15) + 1) / 2, ((y & 15) + 1) / 2, prim_color, texptr, texbufw, texlevel, frac_texlevel, bilinear, sampler);
|
||||
static inline Vec4IntResult SOFTRAST_CALL ApplyTexturingSingle(float s, float t, int x, int y, Vec4IntArg prim_color, u8 *texptr[], int texbufw[], int texlevel, int frac_texlevel, bool bilinear, const RasterizerState &state) {
|
||||
return ApplyTexturing(s, t, ((x & 15) + 1) / 2, ((y & 15) + 1) / 2, prim_color, texptr, texbufw, texlevel, frac_texlevel, bilinear, state);
|
||||
}
|
||||
|
||||
// Produces a signed 1.27.4 value.
|
||||
|
@ -554,7 +555,7 @@ static inline void CalculateSamplingParams(const float ds, const float dt, const
|
|||
}
|
||||
}
|
||||
|
||||
static inline void ApplyTexturing(Sampler::Funcs sampler, Vec4<int> *prim_color, const Vec4<int> &mask, const Vec4<float> &s, const Vec4<float> &t, int maxTexLevel, u8 *texptr[], int texbufw[], int x, int y) {
|
||||
static inline void ApplyTexturing(const RasterizerState &state, Vec4<int> *prim_color, const Vec4<int> &mask, const Vec4<float> &s, const Vec4<float> &t, int maxTexLevel, u8 *texptr[], int texbufw[], int x, int y) {
|
||||
float ds = s[1] - s[0];
|
||||
float dt = t[2] - t[0];
|
||||
|
||||
|
@ -566,7 +567,7 @@ static inline void ApplyTexturing(Sampler::Funcs sampler, Vec4<int> *prim_color,
|
|||
PROFILE_THIS_SCOPE("sampler");
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (mask[i] >= 0)
|
||||
prim_color[i] = ApplyTexturing(s[i], t[i], ((x & 15) + 1) / 2, ((y & 15) + 1) / 2, ToVec4IntArg(prim_color[i]), texptr, texbufw, level, levelFrac, bilinear, sampler);
|
||||
prim_color[i] = ApplyTexturing(s[i], t[i], ((x & 15) + 1) / 2, ((y & 15) + 1) / 2, ToVec4IntArg(prim_color[i]), texptr, texbufw, level, levelFrac, bilinear, state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -742,25 +743,21 @@ template <bool clearMode, bool useSSE4>
|
|||
void DrawTriangleSlice(
|
||||
const VertexData& v0, const VertexData& v1, const VertexData& v2,
|
||||
int x1, int y1, int x2, int y2,
|
||||
const PixelFuncID &pixelID,
|
||||
const Rasterizer::SingleFunc &drawPixel,
|
||||
const Sampler::Funcs &sampler)
|
||||
const RasterizerState &state)
|
||||
{
|
||||
Vec4<int> bias0 = Vec4<int>::AssignToAll(IsRightSideOrFlatBottomLine(v0.screenpos.xy(), v1.screenpos.xy(), v2.screenpos.xy()) ? -1 : 0);
|
||||
Vec4<int> bias1 = Vec4<int>::AssignToAll(IsRightSideOrFlatBottomLine(v1.screenpos.xy(), v2.screenpos.xy(), v0.screenpos.xy()) ? -1 : 0);
|
||||
Vec4<int> bias2 = Vec4<int>::AssignToAll(IsRightSideOrFlatBottomLine(v2.screenpos.xy(), v0.screenpos.xy(), v1.screenpos.xy()) ? -1 : 0);
|
||||
|
||||
const PixelFuncID &pixelID = state.pixelID;
|
||||
|
||||
int texbufw[8]{};
|
||||
|
||||
int maxTexLevel = gstate.getTextureMaxLevel();
|
||||
int maxTexLevel = state.samplerID.hasAnyMips ? gstate.getTextureMaxLevel() : 0;
|
||||
u8 *texptr[8]{};
|
||||
|
||||
if (!gstate.isMipmapEnabled()) {
|
||||
maxTexLevel = 0;
|
||||
}
|
||||
|
||||
if (gstate.isTextureMapEnabled() && !clearMode) {
|
||||
GETextureFormat texfmt = gstate.getTextureFormat();
|
||||
GETextureFormat texfmt = state.samplerID.TexFmt();
|
||||
for (int i = 0; i <= maxTexLevel; i++) {
|
||||
u32 texaddr = gstate.getTextureAddress(i);
|
||||
texbufw[i] = GetTextureBufw(i, texaddr, texfmt);
|
||||
|
@ -875,7 +872,7 @@ void DrawTriangleSlice(
|
|||
GetTextureCoordinates(v0, v1, v2, w0, w1, w2, wsum_recip, s, t);
|
||||
}
|
||||
|
||||
ApplyTexturing(sampler, prim_color, mask, s, t, maxTexLevel, texptr, texbufw, curX, curY);
|
||||
ApplyTexturing(state, prim_color, mask, s, t, maxTexLevel, texptr, texbufw, curX, curY);
|
||||
}
|
||||
|
||||
if (!clearMode) {
|
||||
|
@ -917,7 +914,7 @@ void DrawTriangleSlice(
|
|||
subp.x = p.x + (i & 1);
|
||||
subp.y = p.y + (i / 2);
|
||||
|
||||
drawPixel(subp.x, subp.y, z[i], fog[i], ToVec4IntArg(prim_color[i]), pixelID);
|
||||
state.drawPixel(subp.x, subp.y, z[i], fog[i], ToVec4IntArg(prim_color[i]), pixelID);
|
||||
|
||||
#if defined(SOFTGPU_MEMORY_TAGGING_DETAILED)
|
||||
uint32_t row = gstate.getFrameBufAddress() + subp.y * gstate.FrameBufStride() * bpp;
|
||||
|
@ -948,7 +945,7 @@ void DrawTriangleSlice(
|
|||
}
|
||||
|
||||
// Draws triangle, vertices specified in counter-clockwise direction
|
||||
void DrawTriangle(const VertexData &v0, const VertexData &v1, const VertexData &v2, const PixelFuncID &pixelID, const SamplerID &samplerID) {
|
||||
void DrawTriangle(const VertexData &v0, const VertexData &v1, const VertexData &v2, const RasterizerState &state) {
|
||||
PROFILE_THIS_SCOPE("draw_tri");
|
||||
|
||||
Vec2<int> d01((int)v0.screenpos.x - (int)v1.screenpos.x, (int)v0.screenpos.y - (int)v1.screenpos.y);
|
||||
|
@ -982,20 +979,15 @@ void DrawTriangle(const VertexData &v0, const VertexData &v1, const VertexData &
|
|||
int rangeY = (maxY - minY + 31) / 32;
|
||||
int rangeX = (maxX - minX + 31) / 32;
|
||||
|
||||
Rasterizer::SingleFunc drawPixel = Rasterizer::GetSingleFunc(pixelID);
|
||||
Sampler::Funcs sampler;
|
||||
sampler.nearest = Sampler::GetNearestFunc(samplerID);
|
||||
sampler.linear = Sampler::GetLinearFunc(samplerID);
|
||||
|
||||
auto drawSlice = cpu_info.bSSE4_1 ?
|
||||
(pixelID.clearMode ? &DrawTriangleSlice<true, true> : &DrawTriangleSlice<false, true>) :
|
||||
(pixelID.clearMode ? &DrawTriangleSlice<true, false> : &DrawTriangleSlice<false, false>);
|
||||
(state.pixelID.clearMode ? &DrawTriangleSlice<true, true> : &DrawTriangleSlice<false, true>) :
|
||||
(state.pixelID.clearMode ? &DrawTriangleSlice<true, false> : &DrawTriangleSlice<false, false>);
|
||||
|
||||
const int MIN_LINES_PER_THREAD = 4;
|
||||
|
||||
const uint32_t renderTarget = gstate.getFrameBufAddress() & 0x0FFFFFFF;
|
||||
bool selfRender = (gstate.getTextureAddress(0) & 0x0FFFFFFF) == renderTarget;
|
||||
if (samplerID.hasAnyMips) {
|
||||
if (state.samplerID.hasAnyMips) {
|
||||
for (int i = 0; i <= gstate.getTextureMaxLevel(); ++i)
|
||||
selfRender = selfRender || (gstate.getTextureAddress(i) & 0x0FFFFFFF) == renderTarget;
|
||||
}
|
||||
|
@ -1004,22 +996,22 @@ void DrawTriangle(const VertexData &v0, const VertexData &v1, const VertexData &
|
|||
auto bound = [&](int a, int b) -> void {
|
||||
int x1 = minX + a * 16 * 2;
|
||||
int x2 = std::min(maxX, minX + b * 16 * 2 - 1);
|
||||
drawSlice(v0, v1, v2, x1, minY, x2, maxY, pixelID, drawPixel, sampler);
|
||||
drawSlice(v0, v1, v2, x1, minY, x2, maxY, state);
|
||||
};
|
||||
ParallelRangeLoop(&g_threadManager, bound, 0, rangeX, MIN_LINES_PER_THREAD);
|
||||
} else if (rangeY >= 12 && rangeX >= 12 && !selfRender) {
|
||||
auto bound = [&](int a, int b) -> void {
|
||||
int y1 = minY + a * 16 * 2;
|
||||
int y2 = std::min(maxY, minY + b * 16 * 2 - 1);
|
||||
drawSlice(v0, v1, v2, minX, y1, maxX, y2, pixelID, drawPixel, sampler);
|
||||
drawSlice(v0, v1, v2, minX, y1, maxX, y2, state);
|
||||
};
|
||||
ParallelRangeLoop(&g_threadManager, bound, 0, rangeY, MIN_LINES_PER_THREAD);
|
||||
} else {
|
||||
drawSlice(v0, v1, v2, minX, minY, maxX, maxY, pixelID, drawPixel, sampler);
|
||||
drawSlice(v0, v1, v2, minX, minY, maxX, maxY, state);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawPoint(const VertexData &v0, const PixelFuncID &pixelID, const SamplerID &samplerID) {
|
||||
void DrawPoint(const VertexData &v0, const RasterizerState &state) {
|
||||
ScreenCoords pos = v0.screenpos;
|
||||
Vec4<int> prim_color = v0.color0;
|
||||
Vec3<int> sec_color = v0.color1;
|
||||
|
@ -1033,8 +1025,8 @@ void DrawPoint(const VertexData &v0, const PixelFuncID &pixelID, const SamplerID
|
|||
if (pos.x < scissorTL.x || pos.y < scissorTL.y || pos.x > scissorBR.x || pos.y > scissorBR.y)
|
||||
return;
|
||||
|
||||
Sampler::Funcs sampler = Sampler::GetFuncs();
|
||||
Rasterizer::SingleFunc drawPixel = Rasterizer::GetSingleFunc(pixelID);
|
||||
auto &pixelID = state.pixelID;
|
||||
auto &samplerID = state.samplerID;
|
||||
|
||||
if (gstate.isTextureMapEnabled() && !pixelID.clearMode) {
|
||||
int texbufw[8] = {0};
|
||||
|
@ -1067,7 +1059,7 @@ void DrawPoint(const VertexData &v0, const PixelFuncID &pixelID, const SamplerID
|
|||
bool bilinear;
|
||||
CalculateSamplingParams(0.0f, 0.0f, maxTexLevel, texLevel, texLevelFrac, bilinear);
|
||||
PROFILE_THIS_SCOPE("sampler");
|
||||
prim_color = ApplyTexturingSingle(s, t, pos.x, pos.y, ToVec4IntArg(prim_color), texptr, texbufw, texLevel, texLevelFrac, bilinear, sampler);
|
||||
prim_color = ApplyTexturingSingle(s, t, pos.x, pos.y, ToVec4IntArg(prim_color), texptr, texbufw, texLevel, texLevelFrac, bilinear, state);
|
||||
}
|
||||
|
||||
if (!pixelID.clearMode)
|
||||
|
@ -1084,7 +1076,7 @@ void DrawPoint(const VertexData &v0, const PixelFuncID &pixelID, const SamplerID
|
|||
}
|
||||
|
||||
PROFILE_THIS_SCOPE("draw_px");
|
||||
drawPixel(p.x, p.y, z, fog, ToVec4IntArg(prim_color), pixelID);
|
||||
state.drawPixel(p.x, p.y, z, fog, ToVec4IntArg(prim_color), pixelID);
|
||||
|
||||
#if defined(SOFTGPU_MEMORY_TAGGING_DETAILED) || defined(SOFTGPU_MEMORY_TAGGING_BASIC)
|
||||
uint32_t bpp = pixelID.FBFormat() == GE_FORMAT_8888 ? 4 : 2;
|
||||
|
@ -1104,7 +1096,7 @@ void DrawPoint(const VertexData &v0, const PixelFuncID &pixelID, const SamplerID
|
|||
#endif
|
||||
}
|
||||
|
||||
void ClearRectangle(const VertexData &v0, const VertexData &v1, const PixelFuncID &pixelID, const SamplerID &samplerID) {
|
||||
void ClearRectangle(const VertexData &v0, const VertexData &v1, const RasterizerState &state) {
|
||||
int minX = std::min(v0.screenpos.x, v1.screenpos.x) & ~0xF;
|
||||
int minY = std::min(v0.screenpos.y, v1.screenpos.y) & ~0xF;
|
||||
int maxX = (std::max(v0.screenpos.x, v1.screenpos.x) + 0xF) & ~0xF;
|
||||
|
@ -1119,6 +1111,8 @@ void ClearRectangle(const VertexData &v0, const VertexData &v1, const PixelFuncI
|
|||
|
||||
DrawingCoords pprime = TransformUnit::ScreenToDrawing(ScreenCoords(minX, minY, 0));
|
||||
DrawingCoords pend = TransformUnit::ScreenToDrawing(ScreenCoords(maxX, maxY, 0));
|
||||
auto &pixelID = state.pixelID;
|
||||
auto &samplerID = state.samplerID;
|
||||
|
||||
constexpr int MIN_LINES_PER_THREAD = 32;
|
||||
// Min and max are in PSP fixed point screen coordinates, 16 here is for the 4 subpixel bits.
|
||||
|
@ -1287,7 +1281,7 @@ void ClearRectangle(const VertexData &v0, const VertexData &v1, const PixelFuncI
|
|||
#endif
|
||||
}
|
||||
|
||||
void DrawLine(const VertexData &v0, const VertexData &v1, const PixelFuncID &pixelID, const SamplerID &samplerID) {
|
||||
void DrawLine(const VertexData &v0, const VertexData &v1, const RasterizerState &state) {
|
||||
// TODO: Use a proper line drawing algorithm that handles fractional endpoints correctly.
|
||||
Vec3<int> a(v0.screenpos.x, v0.screenpos.y, v0.screenpos.z);
|
||||
Vec3<int> b(v1.screenpos.x, v1.screenpos.y, v0.screenpos.z);
|
||||
|
@ -1320,11 +1314,11 @@ void DrawLine(const VertexData &v0, const VertexData &v1, const PixelFuncID &pix
|
|||
|
||||
int texbufw[8] = {0};
|
||||
|
||||
int maxTexLevel = samplerID.hasAnyMips ? gstate.getTextureMaxLevel() : 0;
|
||||
int maxTexLevel = state.samplerID.hasAnyMips ? gstate.getTextureMaxLevel() : 0;
|
||||
u8 *texptr[8] = {NULL};
|
||||
|
||||
if (gstate.isTextureMapEnabled() && !pixelID.clearMode) {
|
||||
GETextureFormat texfmt = samplerID.TexFmt();
|
||||
if (gstate.isTextureMapEnabled() && !state.pixelID.clearMode) {
|
||||
GETextureFormat texfmt = state.samplerID.TexFmt();
|
||||
for (int i = 0; i <= maxTexLevel; i++) {
|
||||
u32 texaddr = gstate.getTextureAddress(i);
|
||||
texbufw[i] = GetTextureBufw(i, texaddr, texfmt);
|
||||
|
@ -1332,8 +1326,8 @@ void DrawLine(const VertexData &v0, const VertexData &v1, const PixelFuncID &pix
|
|||
}
|
||||
}
|
||||
|
||||
Sampler::Funcs sampler = Sampler::GetFuncs();
|
||||
Rasterizer::SingleFunc drawPixel = Rasterizer::GetSingleFunc(pixelID);
|
||||
auto &pixelID = state.pixelID;
|
||||
auto &samplerID = state.samplerID;
|
||||
|
||||
#if defined(SOFTGPU_MEMORY_TAGGING_DETAILED) || defined(SOFTGPU_MEMORY_TAGGING_BASIC)
|
||||
DisplayList currentList{};
|
||||
|
@ -1407,7 +1401,7 @@ void DrawLine(const VertexData &v0, const VertexData &v1, const PixelFuncID &pix
|
|||
}
|
||||
|
||||
PROFILE_THIS_SCOPE("sampler");
|
||||
prim_color = ApplyTexturingSingle(s, t, x, y, ToVec4IntArg(prim_color), texptr, texbufw, texLevel, texLevelFrac, texBilinear, sampler);
|
||||
prim_color = ApplyTexturingSingle(s, t, x, y, ToVec4IntArg(prim_color), texptr, texbufw, texLevel, texLevelFrac, texBilinear, state);
|
||||
}
|
||||
|
||||
if (!pixelID.clearMode)
|
||||
|
@ -1417,7 +1411,7 @@ void DrawLine(const VertexData &v0, const VertexData &v1, const PixelFuncID &pix
|
|||
|
||||
PROFILE_THIS_SCOPE("draw_px");
|
||||
DrawingCoords p = TransformUnit::ScreenToDrawing(pprime);
|
||||
drawPixel(p.x, p.y, z, fog, ToVec4IntArg(prim_color), pixelID);
|
||||
state.drawPixel(p.x, p.y, z, fog, ToVec4IntArg(prim_color), pixelID);
|
||||
|
||||
#if defined(SOFTGPU_MEMORY_TAGGING_DETAILED) || defined(SOFTGPU_MEMORY_TAGGING_BASIC)
|
||||
uint32_t bpp = pixelID.FBFormat() == GE_FORMAT_8888 ? 4 : 2;
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "GPU/Software/DrawPixel.h"
|
||||
#include "GPU/Software/FuncId.h"
|
||||
#include "GPU/Software/RasterizerRegCache.h"
|
||||
#include "GPU/Software/Sampler.h"
|
||||
#include "GPU/Software/TransformUnit.h" // for DrawingCoords
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
@ -30,11 +32,19 @@ struct GPUDebugBuffer;
|
|||
|
||||
namespace Rasterizer {
|
||||
|
||||
struct RasterizerState {
|
||||
PixelFuncID pixelID;
|
||||
SamplerID samplerID;
|
||||
SingleFunc drawPixel;
|
||||
Sampler::LinearFunc linear;
|
||||
Sampler::NearestFunc nearest;
|
||||
};
|
||||
|
||||
// Draws a triangle if its vertices are specified in counter-clockwise order
|
||||
void DrawTriangle(const VertexData &v0, const VertexData &v1, const VertexData &v2, const PixelFuncID &pixelID, const SamplerID &samplerID);
|
||||
void DrawPoint(const VertexData &v0, const PixelFuncID &pixelID, const SamplerID &samplerID);
|
||||
void DrawLine(const VertexData &v0, const VertexData &v1, const PixelFuncID &pixelID, const SamplerID &samplerID);
|
||||
void ClearRectangle(const VertexData &v0, const VertexData &v1, const PixelFuncID &pixelID, const SamplerID &samplerID);
|
||||
void DrawTriangle(const VertexData &v0, const VertexData &v1, const VertexData &v2, const RasterizerState &state);
|
||||
void DrawPoint(const VertexData &v0, const RasterizerState &state);
|
||||
void DrawLine(const VertexData &v0, const VertexData &v1, const RasterizerState &state);
|
||||
void ClearRectangle(const VertexData &v0, const VertexData &v1, const RasterizerState &state);
|
||||
|
||||
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer);
|
||||
bool GetCurrentTexture(GPUDebugBuffer &buffer, int level);
|
||||
|
|
|
@ -47,7 +47,7 @@ inline void DrawSinglePixel5551(u16 *pixel, const u32 color_in, const PixelFuncI
|
|||
*pixel = RGBA8888ToRGBA5551(new_color);
|
||||
}
|
||||
|
||||
static inline Vec4IntResult SOFTRAST_CALL ModulateRGBA(Vec4IntArg prim_in, Vec4IntArg texcolor_in) {
|
||||
static inline Vec4IntResult SOFTRAST_CALL ModulateRGBA(Vec4IntArg prim_in, Vec4IntArg texcolor_in, const SamplerID &samplerID) {
|
||||
Vec4<int> out;
|
||||
Vec4<int> prim_color = prim_in;
|
||||
Vec4<int> texcolor = texcolor_in;
|
||||
|
@ -57,7 +57,7 @@ static inline Vec4IntResult SOFTRAST_CALL ModulateRGBA(Vec4IntArg prim_in, Vec4I
|
|||
const __m128i p = _mm_slli_epi16(_mm_packs_epi32(prim_color.ivec, prim_color.ivec), 4);
|
||||
const __m128i pboost = _mm_add_epi16(p, _mm_set1_epi16(1 << 4));
|
||||
__m128i t = _mm_slli_epi16(_mm_packs_epi32(texcolor.ivec, texcolor.ivec), 4);
|
||||
if (gstate.isColorDoublingEnabled()) {
|
||||
if (samplerID.useColorDoubling) {
|
||||
const __m128i amask = _mm_set_epi16(-1, 0, 0, 0, -1, 0, 0, 0);
|
||||
const __m128i a = _mm_and_si128(t, amask);
|
||||
const __m128i rgb = _mm_andnot_si128(amask, t);
|
||||
|
@ -66,7 +66,7 @@ static inline Vec4IntResult SOFTRAST_CALL ModulateRGBA(Vec4IntArg prim_in, Vec4I
|
|||
const __m128i b = _mm_mulhi_epi16(pboost, t);
|
||||
out.ivec = _mm_unpacklo_epi16(b, _mm_setzero_si128());
|
||||
#else
|
||||
if (gstate.isColorDoublingEnabled()) {
|
||||
if (samplerID.useColorDoubling) {
|
||||
Vec4<int> tex = texcolor * Vec4<int>(2, 2, 2, 1);
|
||||
out = ((prim_color + Vec4<int>::AssignToAll(1)) * tex) / 256;
|
||||
} else {
|
||||
|
@ -77,19 +77,19 @@ static inline Vec4IntResult SOFTRAST_CALL ModulateRGBA(Vec4IntArg prim_in, Vec4I
|
|||
return ToVec4IntResult(out);
|
||||
}
|
||||
|
||||
void DrawSprite(const VertexData &v0, const VertexData &v1, const PixelFuncID &pixelID, const SamplerID &samplerID) {
|
||||
void DrawSprite(const VertexData &v0, const VertexData &v1, const RasterizerState &state) {
|
||||
const u8 *texptr = nullptr;
|
||||
|
||||
GETextureFormat texfmt = samplerID.TexFmt();
|
||||
GETextureFormat texfmt = state.samplerID.TexFmt();
|
||||
u32 texaddr = gstate.getTextureAddress(0);
|
||||
int texbufw = GetTextureBufw(0, texaddr, texfmt);
|
||||
if (Memory::IsValidAddress(texaddr))
|
||||
texptr = Memory::GetPointerUnchecked(texaddr);
|
||||
|
||||
ScreenCoords pprime(v0.screenpos.x, v0.screenpos.y, 0);
|
||||
Sampler::FetchFunc fetchFunc = Sampler::GetFetchFunc(samplerID);
|
||||
Sampler::NearestFunc nearestFunc = Sampler::GetNearestFunc(samplerID);
|
||||
Rasterizer::SingleFunc drawPixel = Rasterizer::GetSingleFunc(pixelID);
|
||||
Sampler::FetchFunc fetchFunc = Sampler::GetFetchFunc(state.samplerID);
|
||||
auto &pixelID = state.pixelID;
|
||||
auto &samplerID = state.samplerID;
|
||||
|
||||
DrawingCoords pos0 = TransformUnit::ScreenToDrawing(v0.screenpos);
|
||||
// Include the ending pixel based on its center, not start.
|
||||
|
@ -172,7 +172,7 @@ void DrawSprite(const VertexData &v0, const VertexData &v1, const PixelFuncID &p
|
|||
for (int x = pos0.x; x < pos1.x; x++) {
|
||||
Vec4<int> prim_color = v1.color0;
|
||||
Vec4<int> tex_color = fetchFunc(s, t, texptr, texbufw, 0);
|
||||
prim_color = Vec4<int>(ModulateRGBA(ToVec4IntArg(prim_color), ToVec4IntArg(tex_color)));
|
||||
prim_color = Vec4<int>(ModulateRGBA(ToVec4IntArg(prim_color), ToVec4IntArg(tex_color), state.samplerID));
|
||||
if (prim_color.a() > 0) {
|
||||
DrawSinglePixel5551(pixel, prim_color.ToRGBA(), pixelID);
|
||||
}
|
||||
|
@ -198,8 +198,8 @@ void DrawSprite(const VertexData &v0, const VertexData &v1, const PixelFuncID &p
|
|||
float s = sf_start;
|
||||
// Not really that fast but faster than triangle.
|
||||
for (int x = pos0.x; x < pos1.x; x++) {
|
||||
Vec4<int> prim_color = nearestFunc(s, t, xoff, yoff, ToVec4IntArg(v1.color0), &texptr, &texbufw, 0, 0);
|
||||
drawPixel(x, y, z, 255, ToVec4IntArg(prim_color), pixelID);
|
||||
Vec4<int> prim_color = state.nearest(s, t, xoff, yoff, ToVec4IntArg(v1.color0), &texptr, &texbufw, 0, 0);
|
||||
state.drawPixel(x, y, z, 255, ToVec4IntArg(prim_color), pixelID);
|
||||
s += dsf;
|
||||
}
|
||||
t += dtf;
|
||||
|
@ -243,7 +243,7 @@ void DrawSprite(const VertexData &v0, const VertexData &v1, const PixelFuncID &p
|
|||
for (int y = y1; y < y2; y++) {
|
||||
for (int x = pos0.x; x < pos1.x; x++) {
|
||||
Vec4<int> prim_color = v1.color0;
|
||||
drawPixel(x, y, z, fog, ToVec4IntArg(prim_color), pixelID);
|
||||
state.drawPixel(x, y, z, fog, ToVec4IntArg(prim_color), pixelID);
|
||||
}
|
||||
}
|
||||
}, pos0.y, pos1.y, MIN_LINES_PER_THREAD);
|
||||
|
@ -279,7 +279,7 @@ static inline bool NoClampOrWrap(const Vec2f &tc) {
|
|||
}
|
||||
|
||||
// Returns true if the normal path should be skipped.
|
||||
bool RectangleFastPath(const VertexData &v0, const VertexData &v1, const PixelFuncID &pixelID, const SamplerID &samplerID) {
|
||||
bool RectangleFastPath(const VertexData &v0, const VertexData &v1, const RasterizerState &state) {
|
||||
g_DarkStalkerStretch = DSStretch::Off;
|
||||
// Check for 1:1 texture mapping. In that case we can call DrawSprite.
|
||||
int xdiff = v1.screenpos.x - v0.screenpos.x;
|
||||
|
@ -292,10 +292,10 @@ bool RectangleFastPath(const VertexData &v0, const VertexData &v1, const PixelFu
|
|||
// Currently only works for TL/BR, which is the most common but not required.
|
||||
bool orient_check = xdiff >= 0 && ydiff >= 0;
|
||||
// We already have a fast path for clear in ClearRectangle.
|
||||
bool state_check = !pixelID.clearMode && NoClampOrWrap(v0.texturecoords) && NoClampOrWrap(v1.texturecoords);
|
||||
bool state_check = !state.pixelID.clearMode && NoClampOrWrap(v0.texturecoords) && NoClampOrWrap(v1.texturecoords);
|
||||
// TODO: No mipmap levels? Might be a font at level 1...
|
||||
if ((coord_check || !gstate.isTextureMapEnabled()) && orient_check && state_check) {
|
||||
Rasterizer::DrawSprite(v0, v1, pixelID, samplerID);
|
||||
Rasterizer::DrawSprite(v0, v1, state);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -317,7 +317,7 @@ bool RectangleFastPath(const VertexData &v0, const VertexData &v1, const PixelFu
|
|||
gstate.textureMapEnable &= ~1;
|
||||
VertexData newV1 = v1;
|
||||
newV1.color0 = Vec4<int>(0, 0, 0, 255);
|
||||
Rasterizer::DrawSprite(v0, newV1, pixelID, samplerID);
|
||||
Rasterizer::DrawSprite(v0, newV1, state);
|
||||
gstate.textureMapEnable |= 1;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
namespace Rasterizer {
|
||||
// Returns true if the normal path should be skipped.
|
||||
bool RectangleFastPath(const VertexData &v0, const VertexData &v1, const PixelFuncID &pixelID, const SamplerID &samplerID);
|
||||
bool RectangleFastPath(const VertexData &v0, const VertexData &v1, const RasterizerState &state);
|
||||
|
||||
bool DetectRectangleFromThroughModeStrip(const VertexData data[4]);
|
||||
bool DetectRectangleFromThroughModeFan(const VertexData *data, int c, int *tlIndex, int *brIndex);
|
||||
|
|
|
@ -42,19 +42,6 @@ NearestFunc GetNearestFunc(SamplerID id);
|
|||
typedef Rasterizer::Vec4IntResult (SOFTRAST_CALL *LinearFunc)(float s, float t, int x, int y, Rasterizer::Vec4IntArg prim_color, const u8 *const *tptr, const int *bufw, int level, int levelFrac);
|
||||
LinearFunc GetLinearFunc(SamplerID id);
|
||||
|
||||
struct Funcs {
|
||||
NearestFunc nearest;
|
||||
LinearFunc linear;
|
||||
};
|
||||
static inline Funcs GetFuncs() {
|
||||
Funcs f;
|
||||
SamplerID id;
|
||||
ComputeSamplerID(&id);
|
||||
f.nearest = GetNearestFunc(id);
|
||||
f.linear = GetLinearFunc(id);
|
||||
return f;
|
||||
}
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
|
|
|
@ -28,11 +28,12 @@
|
|||
#include "GPU/Common/VertexDecoderCommon.h"
|
||||
#include "GPU/Common/SplineCommon.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
#include "GPU/Software/TransformUnit.h"
|
||||
#include "GPU/Software/Clipper.h"
|
||||
#include "GPU/Software/FuncId.h"
|
||||
#include "GPU/Software/Lighting.h"
|
||||
#include "GPU/Software/Rasterizer.h"
|
||||
#include "GPU/Software/RasterizerRectangle.h"
|
||||
#include "GPU/Software/TransformUnit.h"
|
||||
|
||||
#define TRANSFORM_BUF_SIZE (65536 * 48)
|
||||
|
||||
|
@ -340,10 +341,12 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy
|
|||
// TODO: Do this in two passes - first process the vertices (before indexing/stripping),
|
||||
// then resolve the indices. This lets us avoid transforming shared vertices twice.
|
||||
|
||||
PixelFuncID pixelID;
|
||||
ComputePixelFuncID(&pixelID);
|
||||
SamplerID samplerID;
|
||||
ComputeSamplerID(&samplerID);
|
||||
Rasterizer::RasterizerState state;
|
||||
ComputePixelFuncID(&state.pixelID);
|
||||
ComputeSamplerID(&state.samplerID);
|
||||
state.drawPixel = Rasterizer::GetSingleFunc(state.pixelID);
|
||||
state.linear = Sampler::GetLinearFunc(state.samplerID);
|
||||
state.nearest = Sampler::GetNearestFunc(state.samplerID);
|
||||
|
||||
bool outside_range_flag = false;
|
||||
switch (prim_type) {
|
||||
|
@ -376,22 +379,22 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy
|
|||
case GE_PRIM_TRIANGLES:
|
||||
{
|
||||
if (!gstate.isCullEnabled() || gstate.isModeClear()) {
|
||||
Clipper::ProcessTriangle(data[0], data[1], data[2], data[2], pixelID, samplerID);
|
||||
Clipper::ProcessTriangle(data[2], data[1], data[0], data[2], pixelID, samplerID);
|
||||
Clipper::ProcessTriangle(data[0], data[1], data[2], data[2], state);
|
||||
Clipper::ProcessTriangle(data[2], data[1], data[0], data[2], state);
|
||||
} else if (!gstate.getCullMode()) {
|
||||
Clipper::ProcessTriangle(data[2], data[1], data[0], data[2], pixelID, samplerID);
|
||||
Clipper::ProcessTriangle(data[2], data[1], data[0], data[2], state);
|
||||
} else {
|
||||
Clipper::ProcessTriangle(data[0], data[1], data[2], data[2], pixelID, samplerID);
|
||||
Clipper::ProcessTriangle(data[0], data[1], data[2], data[2], state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case GE_PRIM_LINES:
|
||||
Clipper::ProcessLine(data[0], data[1], pixelID, samplerID);
|
||||
Clipper::ProcessLine(data[0], data[1], state);
|
||||
break;
|
||||
|
||||
case GE_PRIM_POINTS:
|
||||
Clipper::ProcessPoint(data[0], pixelID, samplerID);
|
||||
Clipper::ProcessPoint(data[0], state);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -431,14 +434,14 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy
|
|||
}
|
||||
|
||||
if (data_index == 4) {
|
||||
Clipper::ProcessRect(data[0], data[1], pixelID, samplerID);
|
||||
Clipper::ProcessRect(data[2], data[3], pixelID, samplerID);
|
||||
Clipper::ProcessRect(data[0], data[1], state);
|
||||
Clipper::ProcessRect(data[2], data[3], state);
|
||||
data_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (data_index >= 2) {
|
||||
Clipper::ProcessRect(data[0], data[1], pixelID, samplerID);
|
||||
Clipper::ProcessRect(data[0], data[1], state);
|
||||
data_index -= 2;
|
||||
}
|
||||
break;
|
||||
|
@ -467,7 +470,7 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy
|
|||
--skip_count;
|
||||
} else {
|
||||
// We already incremented data_index, so data_index & 1 is previous one.
|
||||
Clipper::ProcessLine(data[data_index & 1], data[(data_index & 1) ^ 1], pixelID, samplerID);
|
||||
Clipper::ProcessLine(data[data_index & 1], data[(data_index & 1) ^ 1], state);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -493,7 +496,7 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy
|
|||
|
||||
// If a strip is effectively a rectangle, draw it as such!
|
||||
if (!outside_range_flag && Rasterizer::DetectRectangleFromThroughModeStrip(data)) {
|
||||
Clipper::ProcessRect(data[0], data[3], pixelID, samplerID);
|
||||
Clipper::ProcessRect(data[0], data[3], state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -521,14 +524,14 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy
|
|||
}
|
||||
|
||||
if (!gstate.isCullEnabled() || gstate.isModeClear()) {
|
||||
Clipper::ProcessTriangle(data[0], data[1], data[2], data[provoking_index], pixelID, samplerID);
|
||||
Clipper::ProcessTriangle(data[2], data[1], data[0], data[provoking_index], pixelID, samplerID);
|
||||
Clipper::ProcessTriangle(data[0], data[1], data[2], data[provoking_index], state);
|
||||
Clipper::ProcessTriangle(data[2], data[1], data[0], data[provoking_index], state);
|
||||
} else if ((!gstate.getCullMode()) ^ ((data_index - 1) % 2)) {
|
||||
// We need to reverse the vertex order for each second primitive,
|
||||
// but we additionally need to do that for every primitive if CCW cullmode is used.
|
||||
Clipper::ProcessTriangle(data[2], data[1], data[0], data[provoking_index], pixelID, samplerID);
|
||||
Clipper::ProcessTriangle(data[2], data[1], data[0], data[provoking_index], state);
|
||||
} else {
|
||||
Clipper::ProcessTriangle(data[0], data[1], data[2], data[provoking_index], pixelID, samplerID);
|
||||
Clipper::ProcessTriangle(data[0], data[1], data[2], data[provoking_index], state);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -569,7 +572,7 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy
|
|||
|
||||
int tl = -1, br = -1;
|
||||
if (!outside_range_flag && Rasterizer::DetectRectangleFromThroughModeFan(data, vertex_count, &tl, &br)) {
|
||||
Clipper::ProcessRect(data[tl], data[br], pixelID, samplerID);
|
||||
Clipper::ProcessRect(data[tl], data[br], state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -597,14 +600,14 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy
|
|||
}
|
||||
|
||||
if (!gstate.isCullEnabled() || gstate.isModeClear()) {
|
||||
Clipper::ProcessTriangle(data[0], data[1], data[2], data[provoking_index], pixelID, samplerID);
|
||||
Clipper::ProcessTriangle(data[2], data[1], data[0], data[provoking_index], pixelID, samplerID);
|
||||
Clipper::ProcessTriangle(data[0], data[1], data[2], data[provoking_index], state);
|
||||
Clipper::ProcessTriangle(data[2], data[1], data[0], data[provoking_index], state);
|
||||
} else if ((!gstate.getCullMode()) ^ ((data_index - 1) % 2)) {
|
||||
// We need to reverse the vertex order for each second primitive,
|
||||
// but we additionally need to do that for every primitive if CCW cullmode is used.
|
||||
Clipper::ProcessTriangle(data[2], data[1], data[0], data[provoking_index], pixelID, samplerID);
|
||||
Clipper::ProcessTriangle(data[2], data[1], data[0], data[provoking_index], state);
|
||||
} else {
|
||||
Clipper::ProcessTriangle(data[0], data[1], data[2], data[provoking_index], pixelID, samplerID);
|
||||
Clipper::ProcessTriangle(data[0], data[1], data[2], data[provoking_index], state);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Add table
Reference in a new issue