Pass the culling unit tests.

This commit is contained in:
Henrik Rydgård committed 2026-05-23 14:40:15 +02:00
1 parent a854a2bed1
commit fa856fbf68
3 files changed
+26 -20

No files matched your search

+20 -15
View File
@@ -252,13 +252,25 @@ bool DrawEngineCommon::TestBoundingBox(const void *vdata, const void *inds, int
}
}
// Unclear why the top/left is off by a pixel.
const int left = gstate.getOffsetX() + std::max(gstate.getRegionX1(), gstate.getScissorX1()) - 1;
const int top = gstate.getOffsetY() + std::max(gstate.getRegionY1(), gstate.getScissorY1()) - 1;
const int right = gstate.getOffsetX() + std::min(gstate.getRegionX2(), gstate.getScissorX2()) + 1;
const int bottom = gstate.getOffsetY() + std::min(gstate.getRegionY2(), gstate.getScissorY2()) + 1;
// This is strange, it seems if the draw box is at all outside the 4096x4096 coordinate space, all checks pass.
// It seems very odd that the hardware would have checks for this.
if (right >= 4096 || bottom >= 4096 || left < 1.0f || top < 1.0f) {
return true;
}
// TODO: How accurate should we be?
int insideCount[6] = {0};
for (int i = 0; i < vertexCount; i++) {
// Complete the transform to see if the vertex should be ignored. Not sure if we need to go to these lengths...
const float *objpos = verts + i * 3;
float projpos[4]{};
float projpos[4];
Vec3ByMatrix44(projpos, objpos, gstate_c.worldviewproj);
if (projpos[2] >= -projpos[3]) {
@@ -268,28 +280,26 @@ bool DrawEngineCommon::TestBoundingBox(const void *vdata, const void *inds, int
insideCount[5]++;
}
float invW = 1.0f / projpos[3];
const float invW = 1.0f / projpos[3];
const float screenpos[3] = {
projpos[0] * gstate.getViewportXScale() * invW + gstate.getViewportXCenter(),
projpos[1] * gstate.getViewportYScale() * invW + gstate.getViewportYCenter(),
projpos[2] * gstate.getViewportZScale() * invW + gstate.getViewportZCenter(),
};
const float drawX = screenpos[0] - gstate.getOffsetX();
const float drawY = screenpos[1] - gstate.getOffsetY();
const float drawX = screenpos[0];
const float drawY = screenpos[1];
const int regionX2 = gstate.getRegionX2() + 1;
const int regionY2 = gstate.getRegionY2() + 1;
if (drawX >= 0.0f) {
if (drawX >= left) {
insideCount[0]++;
}
if (drawX <= regionX2) {
if (drawX <= right) {
insideCount[1]++;
}
if (drawY >= 0.0f) {
if (drawY >= top) {
insideCount[2]++;
}
if (drawY <= regionY2) {
if (drawY <= bottom) {
insideCount[3]++;
}
}
@@ -328,11 +338,6 @@ bool DrawEngineCommon::TestBoundingBoxFast(const void *vdata, int vertexCount, c
return true;
}
// Also let's just bail if offsetOutsideEdge_ is set, instead of handling the cases.
// NOTE: This is written to in UpdatePlanes so can't check it before.
if (offsetOutsideEdge_)
return true;
// Simple, most common case.
int stride = dec->VertexSize();
int offset = dec->posoff;
-5
View File
@@ -350,11 +350,6 @@ protected:
// Hardware tessellation
TessellationDataTransfer *tessDataTransfer = nullptr;
// Culling
Vec2f minOffset_{};
Vec2f maxOffset_{};
bool offsetOutsideEdge_ = false;
GPUCommon *gpuCommon_ = nullptr;
// Software depth raster
+6
View File
@@ -375,8 +375,14 @@ struct GPUgstate {
int getScissorY1() const { return (scissor1 >> 10) & 0x3FF; }
int getScissorX2() const { return scissor2 & 0x3FF; }
int getScissorY2() const { return (scissor2 >> 10) & 0x3FF; }
// When drawing, these registers do weird stuff. Must be set to 0 for normal behavior.
int getRegionRateX() const { return 0x100 + (region1 & 0x3FF); }
int getRegionRateY() const { return 0x100 + ((region1 >> 10) & 0x3FF); }
// However when testing for bbox culling, these do act like X1/X2.
int getRegionX1() const { return (region1 & 0x3FF); }
int getRegionY1() const { return (region1 >> 10) & 0x3FF; }
int getRegionX2() const { return (region2 & 0x3FF); }
int getRegionY2() const { return (region2 >> 10) & 0x3FF; }