SoftGPU: Setup reciprocal segments from the table's formula

Nearly every segment's K is floor(2^39 / (65536 + 256 i) / 16) * 16. The
fit to probe data left a few segments loose and slightly low; segment 39
made Blade Dancer's large triangle one depth unit high where the PSP's
depth test rejects it (frame dump now exact). Segments 39, 162, 253 and 255
now use the formula, which every probe accepts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-10-02 15:09:43 -06:00
1 parent d8434424b1
commit b6dec1dfdc
2 files changed
+8 -3

No files matched your search

+6 -3
View File
@@ -152,7 +152,7 @@ static const GESetupRecipSegment geSetupRecip[256] = {
{ 7669584, -213 }, { 7642288, -212 }, { 7615184, -210 }, { 7588272, -209 },
{ 7561552, -208 }, { 7535024, -206 }, { 7508672, -205 }, { 7482512, -203 },
{ 7456528, -202 }, { 7430736, -200 }, { 7405104, -199 }, { 7379664, -198 },
{ 7354384, -196 }, { 7329280, -195 }, { 7304352, -194 }, { 7279552, -192 },
{ 7354384, -196 }, { 7329280, -195 }, { 7304352, -194 }, { 7279600, -192 },
{ 7255008, -191 }, { 7230576, -190 }, { 7206320, -188 }, { 7182208, -187 },
{ 7158272, -186 }, { 7134496, -185 }, { 7110864, -183 }, { 7087392, -182 },
{ 7064080, -181 }, { 7040928, -180 }, { 7017920, -179 }, { 6995056, -178 },
@@ -183,7 +183,7 @@ static const GESetupRecipSegment geSetupRecip[256] = {
{ 5315552, -102 }, { 5302416, -102 }, { 5289360, -101 }, { 5276368, -101 },
{ 5263440, -100 }, { 5250560, -100 }, { 5237760, -99 }, { 5225008, -99 },
{ 5212336, -98 }, { 5199712, -98 }, { 5187152, -97 }, { 5174656, -97 },
{ 5162208, -96 }, { 5149840, -96 }, { 5137504, -96 }, { 5125248, -95 },
{ 5162208, -96 }, { 5149840, -96 }, { 5137520, -96 }, { 5125248, -95 },
{ 5113056, -95 }, { 5100896, -94 }, { 5088816, -94 }, { 5076784, -93 },
{ 5064816, -93 }, { 5052896, -92 }, { 5041040, -92 }, { 5029232, -92 },
{ 5017472, -91 }, { 5005776, -91 }, { 4994144, -90 }, { 4982560, -90 },
@@ -206,9 +206,12 @@ static const GESetupRecipSegment geSetupRecip[256] = {
{ 4329600, -68 }, { 4320880, -67 }, { 4312208, -67 }, { 4303568, -67 },
{ 4294960, -67 }, { 4286384, -66 }, { 4277840, -66 }, { 4269344, -66 },
{ 4260880, -66 }, { 4252432, -65 }, { 4244032, -65 }, { 4235664, -65 },
{ 4227328, -65 }, { 4219008, -64 }, { 4210752, -64 }, { 4202496, -64 },
{ 4227328, -65 }, { 4219024, -64 }, { 4210752, -64 }, { 4202512, -64 },
};
// Nearly every K is floor(2^39 / (65536 + 256 i) / 16) * 16, the start of segment i in 1/8ths. The table was fit
// to probe data; segments it left loose (39, 161, 162, 253, 255) use that formula, which games confirmed for 39
// and 161. 105 and 106 differ from it, measured.
int64_t GESetupRecip(uint64_t absDet, int *e) {
const uint32_t hi = (uint32_t)(absDet >> 32);
const int ex = hi ? 63 - (int)clz32_nonzero(hi) : 31 - (int)clz32_nonzero((uint32_t)absDet);
+2
View File
@@ -128,6 +128,8 @@ static bool TestGESetupRecip() {
// exp54's Gouraud triangle (det 854491) needs at least 40211 here; exp39 and exp41 bound it from above.
int e = 0;
EXPECT_EQ_INT(GESetupRecip(65536 + 41275, &e), 40211);
// Blade Dancer's large triangle (det 9668772) needs at least 56859 for its depth (frame dump, index 10001).
EXPECT_EQ_INT(GESetupRecip(9668772, &e), 56859);
return true;
}