mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-23 15:52:42 +02:00
fast3d/D217: key CI texture cache on palette content, not just TLUT address (#49)
GE assembles weapon and character model display lists in scratch arena RAM
and reissues gDPLoadTLUT from a repeated source address with different
palette *content* between materials and frames. The CI TextureCacheKey
keyed only on {texel addr, palette_addrs[0/1], palette_index, size_bytes}
with no content check, so gfx_texture_cache_lookup() (a plain map.find)
could return a stale HIT whose GL texture was decoded against a different
palette. Proven with an env-gated probe on -level_34: the same
{addr, paladdr} pair re-imported many times per frame with materially
different rdp.palette content, all taking HITs.
Fix: FNV-1a hash of the 512-byte rdp.palette, recomputed only in
gfx_dp_load_tlut() (rare vs draws -> no per-texel or per-draw cost), added
as a trailing field of the CI cache key. Non-CI keys carry 0. Cannot
produce a worse decode than the stale HIT it replaces; worst case is a few
extra texture uploads per frame (~2 measured on -level_34).
Partial for D217: this removes a real stale-palette-HIT class (the D217
finding's own "test a palette-content hash" next-step) but does NOT resolve
the visible green PP7 grip. That has an upstream cause - the grip's count=1
model TLUT is fed different source bytes per level (Bunker 0x0001 -> black,
Facility 0x1A00 -> green) for the same tile; fast3d faithfully stores what
it is given. See scratchpad D217-report.md. Full 21-level world-CI
regression sweep still owed before merge.
Claude-Session: https://claude.ai/code/session_016TaKy6AAsVUTfjkhrX6CjG
This commit is contained in:
1 parent
50d73c519c
commit
f800275247
2 files changed
+29
-2
No files matched your search
+20
-2
@@ -156,6 +156,7 @@ static struct RDP {
|
||||
uint16_t palette[256];
|
||||
const uint8_t* palette_addrs[2];
|
||||
uint32_t palette_fmt;
|
||||
uint32_t palette_hash; /* D217: FNV-1a of palette[], refreshed in gfx_dp_load_tlut */
|
||||
struct {
|
||||
const uint8_t* addr;
|
||||
uint8_t siz;
|
||||
@@ -988,9 +989,9 @@ static void import_texture(int i, int tile, bool importReplacement) {
|
||||
TextureCacheKey key;
|
||||
if (fmt == G_IM_FMT_CI) {
|
||||
key = { orig_addr, { rdp.palette_addrs[0], rdp.palette_addrs[1] }, fmt, siz, palette_index,
|
||||
loaded_texture.size_bytes };
|
||||
loaded_texture.size_bytes, rdp.palette_hash }; // D217: key on palette content
|
||||
} else {
|
||||
key = { orig_addr, {}, fmt, siz, palette_index, loaded_texture.size_bytes };
|
||||
key = { orig_addr, {}, fmt, siz, palette_index, loaded_texture.size_bytes, 0u };
|
||||
}
|
||||
|
||||
if (gfx_texture_cache_lookup(i, key)) {
|
||||
@@ -2233,6 +2234,23 @@ static void gfx_dp_load_tlut(uint8_t tile, uint32_t uls, uint32_t ult, uint32_t
|
||||
*dst++ = PD_BE16(*src++);
|
||||
}
|
||||
|
||||
/* D217: refresh the palette-content hash that keys the CI texture cache.
|
||||
* GE reissues gDPLoadTLUT from a repeated scratch source address with
|
||||
* different content between weapon / character model materials; the CI
|
||||
* TextureCacheKey keys on the source *address*, so without a content hash a
|
||||
* later material can take a stale cache HIT decoded against an earlier
|
||||
* palette. gDPLoadTLUT is rare relative to draws, so hashing the whole
|
||||
* 512-byte table here keeps the per-texel path untouched. */
|
||||
{
|
||||
uint32_t h = 2166136261u;
|
||||
const uint8_t *pb = (const uint8_t *)rdp.palette;
|
||||
for (uint32_t k = 0; k < sizeof(rdp.palette); ++k) {
|
||||
h ^= pb[k];
|
||||
h *= 16777619u;
|
||||
}
|
||||
rdp.palette_hash = h;
|
||||
}
|
||||
|
||||
rdp.textures_changed[0] = rdp.textures_changed[1] = true;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user