fix(pgxp): keep probe out of geometry counters

This commit is contained in:
Shokunin
2026-10-05 03:40:41 -07:00
parent 3358f81e25
commit 5807fe8ec3
5 changed files with 134 additions and 14 deletions
+5
View File
@@ -229,6 +229,11 @@ extern uint32_t gte_geometry_correction_hits(void);
extern void gte_geometry_correction_stats(uint32_t *lookups, uint32_t *hits,
uint32_t *miss_unrecorded,
uint32_t *miss_ambiguous);
/* Same position-cache lookup without changing geometry-correction counters;
* reserved for non-rendering probes that inspect a vertex before drawing. */
extern int gte_geometry_correction_lookup_probe(uint32_t packed,
int32_t *x16,
int32_t *y16);
/* Exact NCLIP audit coverage: precise = all three SXY shadows are coherent and
* word-validated; fallback = native integer-only; disagreements counts cases
+26 -6
View File
@@ -360,25 +360,45 @@ extern "C" uint32_t gte_geometry_correction_hits(void) {
return s_geom_hits;
}
extern "C" int gte_geometry_correction_lookup(uint32_t packed,
int32_t *x16, int32_t *y16) {
static int gte_geometry_correction_lookup_impl(uint32_t packed,
int32_t *x16, int32_t *y16,
int count_stats) {
if (s_speculative_depth != 0 || !s_geom_enabled || !s_geom_cache) return 0;
int64_t slot = geom_slot(packed);
if (slot < 0) return 0;
s_geom_lookups++;
if (count_stats) s_geom_lookups++;
const GeomVertex &entry = s_geom_cache[slot];
if (entry.generation != s_geom_generation) { s_geom_miss_unrec++; return 0; }
if (entry.generation != s_geom_generation) {
if (count_stats) s_geom_miss_unrec++;
return 0;
}
/* Ambiguity gate, as in both references (beetle gFlags == 1): if two
* DIFFERENT sub-pixel positions rounded to this same pixel, we cannot tell
* which one this packet means, and guessing is what makes a vertex inherit
* a neighbour's fraction. Fall back to the faithful integer position. */
if (entry.ambiguous) { s_geom_miss_ambig++; return 0; }
if (entry.ambiguous) {
if (count_stats) s_geom_miss_ambig++;
return 0;
}
if (x16) *x16 = entry.x16;
if (y16) *y16 = entry.y16;
s_geom_hits++;
if (count_stats) s_geom_hits++;
return 1;
}
extern "C" int gte_geometry_correction_lookup(uint32_t packed,
int32_t *x16, int32_t *y16) {
return gte_geometry_correction_lookup_impl(packed, x16, y16, 1);
}
/* Read-only variant used by instrumentation probes. A probe must not change
* the geometry-correction census that describes rendered vertices. */
extern "C" int gte_geometry_correction_lookup_probe(uint32_t packed,
int32_t *x16,
int32_t *y16) {
return gte_geometry_correction_lookup_impl(packed, x16, y16, 0);
}
/* Render-pass checkpoint for the gte.cpp side of precision tracking: the
* position cache entries a pass writes are journaled and put back, and the
* speculative bracket depth is restored (a watchdog abort can leave one open).
+20 -8
View File
@@ -43,6 +43,8 @@
/* gte.cpp — position-cache fallback tier (ambiguity-gated, G1.4 exact table) */
extern "C" int gte_geometry_correction_lookup(uint32_t packed,
int32_t *x16, int32_t *y16);
extern "C" int gte_geometry_correction_lookup_probe(uint32_t packed,
int32_t *x16, int32_t *y16);
/* ------------------------------------------------------------------------- */
/* Shadow storage */
@@ -1080,10 +1082,10 @@ static inline int32_t field_rebase(int32_t v16, uint32_t half, int32_t parsed) {
return (int32_t)((int64_t)v16 + ((int64_t)as11 - as16) * 65536);
}
extern "C" int pgxp_get_precise_vertex(uint32_t addr, uint32_t packet_word,
int32_t int_x, int32_t int_y,
int32_t *x16, int32_t *y16,
uint16_t *sz) {
static int pgxp_get_precise_vertex_impl(uint32_t addr, uint32_t packet_word,
int32_t int_x, int32_t int_y,
int32_t *x16, int32_t *y16,
uint16_t *sz, int probe) {
s_stats.lookups++;
int32_t px = 0, py = 0;
@@ -1105,8 +1107,10 @@ extern "C" int pgxp_get_precise_vertex(uint32_t addr, uint32_t packet_word,
}
}
if (!have && s_position_fallback &&
gte_geometry_correction_lookup(packet_word, &px, &py)) {
const int fallback_hit = !have && s_position_fallback &&
(probe ? gte_geometry_correction_lookup_probe(packet_word, &px, &py)
: gte_geometry_correction_lookup(packet_word, &px, &py));
if (fallback_hit) {
pz = 0; /* fallback never carries depth */
have = PGXP_SRC_FALLBACK;
}
@@ -1149,13 +1153,21 @@ extern "C" int pgxp_get_precise_vertex(uint32_t addr, uint32_t packet_word,
return have;
}
extern "C" int pgxp_get_precise_vertex(uint32_t addr, uint32_t packet_word,
int32_t int_x, int32_t int_y,
int32_t *x16, int32_t *y16,
uint16_t *sz) {
return pgxp_get_precise_vertex_impl(addr, packet_word, int_x, int_y,
x16, y16, sz, 0);
}
extern "C" int pgxp_probe_precise_vertex(uint32_t addr, uint32_t packet_word,
int32_t int_x, int32_t int_y) {
const PGXPStats saved = s_stats;
int32_t x16, y16;
uint16_t sz;
const int src = pgxp_get_precise_vertex(addr, packet_word, int_x, int_y,
&x16, &y16, &sz);
const int src = pgxp_get_precise_vertex_impl(addr, packet_word, int_x, int_y,
&x16, &y16, &sz, 1);
s_stats = saved;
return src;
}
@@ -998,6 +998,51 @@ int test_precision_speculative_transaction() {
return 0;
}
int test_pgxp_probe_does_not_count_geometry_lookup() {
constexpr uint32_t packed = (80u << 16) | 160u;
constexpr int32_t x16 = (160 << 16) + 0x4000;
constexpr int32_t y16 = (80 << 16) + 0x2000;
const int fallback_was_enabled = pgxp_position_fallback();
gte_geometry_correction_set(1);
gte_test_seed_geometry(packed, x16, y16);
pgxp_set_position_fallback(1);
uint32_t lookups0 = 0, hits0 = 0, miss_unrecorded0 = 0, miss_ambiguous0 = 0;
gte_geometry_correction_stats(&lookups0, &hits0, &miss_unrecorded0,
&miss_ambiguous0);
if (pgxp_probe_precise_vertex(0xFFFFFFFFu, packed, 160, 80) !=
PGXP_SRC_FALLBACK)
return fail_value("PGXP fallback probe source", 0, 0, packed,
PGXP_SRC_FALLBACK, PGXP_SRC_NATIVE);
uint32_t lookups1 = 0, hits1 = 0, miss_unrecorded1 = 0, miss_ambiguous1 = 0;
gte_geometry_correction_stats(&lookups1, &hits1, &miss_unrecorded1,
&miss_ambiguous1);
if (lookups1 != lookups0 || hits1 != hits0 ||
miss_unrecorded1 != miss_unrecorded0 ||
miss_ambiguous1 != miss_ambiguous0)
return fail_value("PGXP probe leaves geometry counters unchanged", 0, 0,
packed, lookups0, lookups1);
int32_t got_x = 0, got_y = 0;
uint16_t got_z = 1;
if (pgxp_get_precise_vertex(0xFFFFFFFFu, packed, 160, 80,
&got_x, &got_y, &got_z) != PGXP_SRC_FALLBACK ||
got_x != x16 || got_y != y16 || got_z != 0)
return fail_value("PGXP draw uses geometry fallback", 0, 0, packed,
static_cast<uint32_t>(x16), static_cast<uint32_t>(got_x));
uint32_t lookups2 = 0, hits2 = 0, miss_unrecorded2 = 0, miss_ambiguous2 = 0;
gte_geometry_correction_stats(&lookups2, &hits2, &miss_unrecorded2,
&miss_ambiguous2);
gte_geometry_correction_set(0);
pgxp_set_position_fallback(fallback_was_enabled);
if (lookups2 != lookups1 + 1u || hits2 != hits1 + 1u ||
miss_unrecorded2 != miss_unrecorded1 ||
miss_ambiguous2 != miss_ambiguous1)
return fail_value("draw increments geometry counters", 0, 0, packed,
lookups1 + 1u, lookups2);
return 0;
}
} // namespace
/* Preserve projection precision (docs/ENHANCEMENTS.md G1.11) changes the
@@ -1124,6 +1169,7 @@ int main() {
if (int rc = test_precise_nclip_is_title_scoped()) return rc;
if (int rc = test_saturated_nclip_keeps_architectural_result()) return rc;
if (int rc = test_precision_speculative_transaction()) return rc;
if (int rc = test_pgxp_probe_does_not_count_geometry_lookup()) return rc;
if (int rc = test_preserve_projection_is_shadow_only()) return rc;
if (int rc = test_pgxp_culling()) return rc;
/* Signed host projection spans the camera plane without changing any
+37
View File
@@ -26,9 +26,22 @@ static int g_failures = 0;
static uint32_t g_fb_packed = 0;
static int32_t g_fb_x16 = 0, g_fb_y16 = 0;
static int g_fb_valid = 0;
static uint32_t g_fb_probe_lookups = 0;
static uint32_t g_fb_render_lookups = 0;
extern "C" int gte_geometry_correction_lookup(uint32_t packed,
int32_t *x16, int32_t *y16) {
++g_fb_render_lookups;
if (!g_fb_valid || packed != g_fb_packed) return 0;
if (x16) *x16 = g_fb_x16;
if (y16) *y16 = g_fb_y16;
return 1;
}
extern "C" int gte_geometry_correction_lookup_probe(uint32_t packed,
int32_t *x16,
int32_t *y16) {
++g_fb_probe_lookups;
if (!g_fb_valid || packed != g_fb_packed) return 0;
if (x16) *x16 = g_fb_x16;
if (y16) *y16 = g_fb_y16;
@@ -555,6 +568,30 @@ int main(void) {
pgxp_get_stats(&b);
CHECK(b.rect_bypass == a.rect_bypass + 1);
CHECK(b.rect_partial == a.rect_partial + 2);
const int fallback_was_enabled = pgxp_position_fallback();
pgxp_set_position_fallback(1);
g_fb_valid = 1;
g_fb_packed = PACKED;
g_fb_x16 = 160 << 16;
g_fb_y16 = 80 << 16;
const uint32_t render_lookups = g_fb_render_lookups;
const uint32_t probe_lookups = g_fb_probe_lookups;
pgxp_get_stats(&a);
CHECK(pgxp_probe_precise_vertex(0xFFFFFFFFu, PACKED, 160, 80) ==
PGXP_SRC_FALLBACK);
pgxp_get_stats(&b);
CHECK(std::memcmp(&a, &b, sizeof a) == 0);
CHECK(g_fb_render_lookups == render_lookups);
CHECK(g_fb_probe_lookups == probe_lookups + 1u);
int32_t x16, y16;
uint16_t sz;
CHECK(pgxp_get_precise_vertex(0xFFFFFFFFu, PACKED, 160, 80,
&x16, &y16, &sz) == PGXP_SRC_FALLBACK);
CHECK(g_fb_render_lookups == render_lookups + 1u);
CHECK(g_fb_probe_lookups == probe_lookups + 1u);
g_fb_valid = 0;
pgxp_set_position_fallback(fallback_was_enabled);
}
/* --- preserve projection: the RTPS-side window check (G1.11) ---------- */