Snapshot: fog implementation + fidelity tooling baseline (pre bilinear-clamp fix)

Per-vertex GS fog end-to-end (gs_stub emit incl. persp_emit5, gs_prim_list_feeder
XYZ2->XYZF2 on PRIM.FGE, gs_make_sh3_scheduler_fixture.py F/FGE packing), new fog
TBs, fidelity attribution tooling. Functional baseline before removing the dead
bilinear lerp8 clamps (Codex: 161-node comb loop -> -0.042ns setup fail).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-20 19:56:46 -04:00
parent ec82764bef
commit ba74bbd5aa
476 changed files with 696247 additions and 130119 deletions
+74
View File
@@ -0,0 +1,74 @@
# Ch402 — character draws through runtime CLAMP state
Ch402 extends the accepted Ch401 56-draw scene with twelve authentic draws from
the character family, each in its own epoch. These draws use GS region clamp
mode 2 with exact full-texture bounds (`MINU/MINV=0`, `MAXU/MAXV=511`). For a
512x512 texture that state is mathematically identical to ordinary clamp, so the
fixture generator proves those bounds and normalizes only the mode bits. Any
other region-clamp bounds continue to fail closed.
The feeder format is backward-compatible. Legacy lists retain the seven-word
header. Extended lists advertise word 8 with count-word bit 34 and emit
`CLAMP_1` between `TEX0_1` and `PRIM`. A focused feeder regression proves both
formats and the new vertex base.
An initial four-epoch grouping required 2,294 to 3,410 staging words and doubled
the allocated RAM. Although functionally exact in simulation, that placement
pressure moved the previously marginal color-address FIFO family to -0.233 ns.
Ch402 therefore uses twelve single-draw character epochs, retains the accepted
2,048-word staging allocation, and raises only the software epoch-table ceiling
from 32 to 64.
## Simulation
- 68 authentic draws in 40 ordered epochs
- 649,189 fragments fed
- 332,984 fragments passed Z
- 40 fresh ordered drains
- zero request drops, color FIFO overflows, or AXI BRESP errors
- Z mismatches: 0 / 307,200
- color mismatches: 0 / 131,618
- reference coverage: 131,830 pixels
- largest staging list: 1,844 / 2,048 words
- maximum measured request FIFO high-water: 1,753 / 4,096
- simulated framebuffer MEM SHA-256:
`d3a211671a444991e8032c97d3ba16c66621de1e9d3ad1432442bdb8be585010`
- simulated framebuffer PNG SHA-256:
`ae1b8fbdf1748723eede478d4ca349245920c32836df94cdf076cc6b983047b6`
The simulated image now includes the central character silhouette and reaches
the bottom of the 640x480 frame. It remains visibly short of the PCSX2 image in
lighting, fog/compositing, and precision; Ch402 closes the missing-character
state/capacity blocker, not the remaining fidelity debt.
## Timing gate
The first owner GUI fit used a 4,096-word staging allocation. It fit at 291 RAM
blocks but failed setup at -0.233 ns / -1.287 ns TNS on the known
`u_zc_emit|ca_tail/ca_head -> ca_mem` family; hold remained clean. The failure
was a placement regression rather than a new logical path through the feeder.
The 40-epoch repartition removes the seven added RAM blocks and restores the
accepted 2,048-word allocation. The follow-up owner GUI fit recovered timing at
+0.041 ns setup / 0.000 TNS; hold remained clean. It used 37,279 / 46,800 ALMs
and restored RAM usage to 284 / 358 blocks.
## Silicon
The timing-clean RBF (SHA-256
`a7691ff9203bc1a9097da88f0a341f6c14ed96910bb2d6f3fb46349e02b0fcce`)
was hash-verified on the board and loaded through `core_loader.sh`; `fpga0`
reported `operating`.
All 40 epochs passed texture/CLUT CRC, staging count, record count, ordered
drain, and zero-drop gates with `rc=0`.
- nonzero pixels: 131,618
- bounds: `(36,10)..(599,463)`
- board/simulation MEM SHA-256:
`d3a211671a444991e8032c97d3ba16c66621de1e9d3ad1432442bdb8be585010`
- board/simulation PNG SHA-256:
`ae1b8fbdf1748723eede478d4ca349245920c32836df94cdf076cc6b983047b6`
Board and simulation are byte-exact over all 307,200 framebuffer words.
Ch402 is accepted on silicon and remains displayed through the LPDDR HDMI
scanout.