mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
fix(pgxp): keep probe out of geometry counters
This commit is contained in:
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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) ---------- */
|
||||
|
||||
Reference in New Issue
Block a user