Skip to content
Permalink
Browse files
Merge pull request #10255 from Pokechu22/sw-zfreeze
Software: Fix zfreeze with CullMode::All
  • Loading branch information
phire committed Apr 14, 2022
2 parents 36678dc + 59f299d commit c5c4169
Show file tree
Hide file tree
Showing 12 changed files with 169 additions and 121 deletions.
@@ -91,8 +91,6 @@ const Info<int> GFX_SHADER_PRECOMPILER_THREADS{
const Info<bool> GFX_SAVE_TEXTURE_CACHE_TO_STATE{
{System::GFX, "Settings", "SaveTextureCacheToState"}, true};

const Info<bool> GFX_SW_ZCOMPLOC{{System::GFX, "Settings", "SWZComploc"}, true};
const Info<bool> GFX_SW_ZFREEZE{{System::GFX, "Settings", "SWZFreeze"}, true};
const Info<bool> GFX_SW_DUMP_OBJECTS{{System::GFX, "Settings", "SWDumpObjects"}, false};
const Info<bool> GFX_SW_DUMP_TEV_STAGES{{System::GFX, "Settings", "SWDumpTevStages"}, false};
const Info<bool> GFX_SW_DUMP_TEV_TEX_FETCHES{{System::GFX, "Settings", "SWDumpTevTexFetches"},
@@ -73,8 +73,6 @@ extern const Info<int> GFX_SHADER_COMPILER_THREADS;
extern const Info<int> GFX_SHADER_PRECOMPILER_THREADS;
extern const Info<bool> GFX_SAVE_TEXTURE_CACHE_TO_STATE;

extern const Info<bool> GFX_SW_ZCOMPLOC;
extern const Info<bool> GFX_SW_ZFREEZE;
extern const Info<bool> GFX_SW_DUMP_OBJECTS;
extern const Info<bool> GFX_SW_DUMP_TEV_STAGES;
extern const Info<bool> GFX_SW_DUMP_TEV_TEX_FETCHES;
@@ -289,10 +289,42 @@ void ProcessTriangle(OutputVertexData* v0, OutputVertexData* v1, OutputVertexDat
{
INCSTAT(g_stats.this_frame.num_triangles_in)

bool backface;

if (!CullTest(v0, v1, v2, backface))
if (IsTriviallyRejected(v0, v1, v2))
{
INCSTAT(g_stats.this_frame.num_triangles_rejected)
// NOTE: The slope used by zfreeze shouldn't be updated if the triangle is
// trivially rejected during clipping
return;
}

bool backface = IsBackface(v0, v1, v2);

if (!backface)
{
if (bpmem.genMode.cullmode == CullMode::Back || bpmem.genMode.cullmode == CullMode::All)
{
// cull frontfacing - we still need to update the slope for zfreeze
PerspectiveDivide(v0);
PerspectiveDivide(v1);
PerspectiveDivide(v2);
Rasterizer::UpdateZSlope(v0, v1, v2);
INCSTAT(g_stats.this_frame.num_triangles_culled)
return;
}
}
else
{
if (bpmem.genMode.cullmode == CullMode::Front || bpmem.genMode.cullmode == CullMode::All)
{
// cull backfacing - we still need to update the slope for zfreeze
PerspectiveDivide(v0);
PerspectiveDivide(v2);
PerspectiveDivide(v1);
Rasterizer::UpdateZSlope(v0, v2, v1);
INCSTAT(g_stats.this_frame.num_triangles_culled)
return;
}
}

int indices[NUM_INDICES] = {0, 1, 2, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
@@ -461,19 +493,18 @@ void ProcessPoint(OutputVertexData* center)
Rasterizer::DrawTriangleFrontFace(&ur, &lr, &ul);
}

bool CullTest(const OutputVertexData* v0, const OutputVertexData* v1, const OutputVertexData* v2,
bool& backface)
bool IsTriviallyRejected(const OutputVertexData* v0, const OutputVertexData* v1,
const OutputVertexData* v2)
{
int mask = CalcClipMask(v0);
mask &= CalcClipMask(v1);
mask &= CalcClipMask(v2);

if (mask)
{
INCSTAT(g_stats.this_frame.num_triangles_rejected)
return false;
}
return mask != 0;
}

bool IsBackface(const OutputVertexData* v0, const OutputVertexData* v1, const OutputVertexData* v2)
{
float x0 = v0->projectedPosition.x;
float x1 = v1->projectedPosition.x;
float x2 = v2->projectedPosition.x;
@@ -486,29 +517,14 @@ bool CullTest(const OutputVertexData* v0, const OutputVertexData* v1, const Outp

float normalZDir = (x0 * w2 - x2 * w0) * y1 + (x2 * y0 - x0 * y2) * w1 + (y2 * w0 - y0 * w2) * x1;

backface = normalZDir <= 0.0f;
bool backface = normalZDir <= 0.0f;
// Jimmie Johnson's Anything with an Engine has a positive viewport, while other games have a
// negative viewport. The positive viewport does not require vertices to be vertically mirrored,
// but the backface test does need to be inverted for things to be drawn.
if (xfmem.viewport.ht > 0)
backface = !backface;

// TODO: Are these tests / the definition of backface above backwards?
if ((bpmem.genMode.cullmode == CullMode::Back || bpmem.genMode.cullmode == CullMode::All) &&
!backface) // cull frontfacing
{
INCSTAT(g_stats.this_frame.num_triangles_culled)
return false;
}

if ((bpmem.genMode.cullmode == CullMode::Front || bpmem.genMode.cullmode == CullMode::All) &&
backface) // cull backfacing
{
INCSTAT(g_stats.this_frame.num_triangles_culled)
return false;
}

return true;
return backface;
}

void PerspectiveDivide(OutputVertexData* vertex)
@@ -15,8 +15,10 @@ void ProcessLine(OutputVertexData* v0, OutputVertexData* v1);

void ProcessPoint(OutputVertexData* v);

bool CullTest(const OutputVertexData* v0, const OutputVertexData* v1, const OutputVertexData* v2,
bool& backface);
bool IsTriviallyRejected(const OutputVertexData* v0, const OutputVertexData* v1,
const OutputVertexData* v2);

bool IsBackface(const OutputVertexData* v0, const OutputVertexData* v1, const OutputVertexData* v2);

void PerspectiveDivide(OutputVertexData* vertex);
} // namespace Clipper

0 comments on commit c5c4169

Please sign in to comment.