Files
retroDE_ps2/docs/ch415_fog_bilinear_prefit.md
T
thejayman77 ba74bbd5aa 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>
2026-07-20 19:56:46 -04:00

5.7 KiB

Ch415 — authentic fog fold and indexed perspective bilinear filtering

Objective

Move the 224139 board image toward the PCSX2 reference through real captured GS state rather than further draw-count expansion. Every selected draw has PRIM.FGE=1, every vertex arrives through XYZF2, FOGCOL=0, and every selected texture requests linear magnification.

Changes

  • Preserve the captured vertex fog factor and fold the zero fog color into fixture vertex RGB as RGB * F >> 8. This is exact at vertices and uses the existing Gouraud interpolator across each triangle.
  • Preserve four fractional texel bits from the perspective reciprocal path.
  • Serialize indexed perspective pixels through the existing four-tap texture sampler, performing CLUT lookup before interpolation as required.
  • Hold the raster walker while the single-port texture cache fetches four taps, then release exactly once after emitting the completed pixel.
  • Add bounded START_EPOCH/END_EPOCH integration runs and explicit cold shared-asset selection so late reuse epochs can be tested independently.

Reference evidence

Against the 640x480 PCSX2 frame, the full software reconstruction improved from MAE 22.55 / RMSE 34.96 with nearest sampling to MAE 21.17 / RMSE 32.47 with bilinear sampling. The fog fold alone was smaller (MAE 22.51 / RMSE 34.88), so both are retained but filtering is the principal visual change.

RTL evidence

  • Texture sampler: PSMT8/PSMT4 CLUT-before-interpolation, clamp, repeat, nearest fallback, and edge cases all pass.
  • Perspective feeder and palette-bilinear tile integration pass.
  • Legacy raster pipeline remains passing.
  • Real fixture epoch 1: 3,949 accepted/passing fragments, zero drops, exact Z and color-memory comparisons.
  • Dense shared-texture epoch 75: 7,304 accepted/passing fragments, zero drops, exact Z and color-memory comparisons.

First-fit hardware correction

The first signoff-clean Ch415 fit (91087214...) passed all 124 board epochs, but its capture exposed regular missing-pixel stripes: only 84,294 pixels had nonzero RGB, versus 146,399 in the preceding board frame. The DONE cycle had been reopened inside the normal pipeline-advance block, so both DONE and PB_RELEASE advanced the held walker and skipped alternate samples.

The corrected RTL emits DONE outside the advance gate, keeps the walker frozen that cycle, and advances exactly once on PB_RELEASE. Focused RTL coverage rose from 2,889 to 3,949 fragments on epoch 1 and from 4,994 to 7,304 on dense epoch 75, with exact color/Z comparisons and all sampler, tile, feeder, and legacy raster regressions passing.

Second-fit timing repair

The walker-release fit succeeded but STA was unclean in two isolated families:

  • Setup -0.128 ns, two endpoints: the registered request-pop pulse entered the 15-bit read-pointer carry chain before Gray conversion and rempty.
  • Hold -4.817 ns, two endpoints: the asynchronous CLUT-commit and tile-write toggles were timed directly into their explicit first synchronizer stages.

The FIFO now precomputes hold/pop pointer and empty results independently, so the pop pulse selects only the final mux rather than driving the carry chain. The SDC now cuts only the two asynchronous source-to-stage-0 synchronizer paths, with fatal one-register target-count checks; stages 1 and 2 remain timed. Both synchronizers are explicitly identified to Quartus. The FIFO scoreboard, CLUT CDC, tile CDC, and dense 7,304-fragment integration test all pass exactly.

Third-fit setup repair

The next owner fit (ae9729fb...) proved the CDC/FIFO repair: hold closed at 0.000 ns. Setup remained unclean at -0.220 ns / -1.193 ns TNS across eight 310 MHz endpoints. The failing paths were now three concrete datapath cones:

  • EMIF 256-bit read data through the 8:1 lane mux into u_lpddr_rd|rd_data;
  • EMIF read data and address-selected blend operands into diff_r_q/diff_g_q;
  • u_zc_emit|ca_tail through the color-alignment RAM write-address cone.

The read probe now captures the complete EMIF beat in rdata_q, then selects the requested 32-bit lane in a new S_SEL stage. The color blender similarly separates beat capture, lane selection, and operand/difference preparation into R, SEL, and PREP states. The color-alignment RAM write enable, address, and data are also registered before the memory write. This removes all three reported source-to-endpoint combinational cones without adding timing exceptions.

Directed read-probe, color-blend, and Z/color-emitter tests pass. Dense real scene epoch 75 still accepts and passes 7,304 fragments with zero drops and exact comparisons: 0/307,200 Z mismatches and 0/7,304 color mismatches.

Hardware acceptance and fidelity finding

The owner-controlled GUI fit closed cleanly: setup slack +0.052 ns, hold slack 0.000 ns, zero setup/hold TNS, and clean recovery, removal, and minimum pulse checks. The deployed RBF SHA-256 is 6fd81615af95cf51e1a893e04ca34fa1bad7a69c933efcb7fca5c9c091e18a65.

All 124 board epochs passed with every texture CRC, palette, staging-record, drain, and drop gate clean. The captured framebuffer reported 114,231 nonzero words and bounds (1,11)..(512,478); its MEM SHA-256 is e31820cfad1d550bb1ea9adf217e21cb59a02be76c6318ce0b34022307bc91ec.

The hardware result did not realize the software-reference gain. Against the bilinearly resized PCSX2 frame, the preceding board capture measured MAE 21.9782 / RMSE 32.5912, while Ch415 measured MAE 23.6438 / RMSE 35.0255. Ch415 board versus its own software reconstruction measured MAE 12.2877 / RMSE 26.4442. This isolates geometry/coverage precision, rather than scheduler capacity, as the next fidelity boundary. Ch416 therefore preserves the captured XYZ 12.4 fractions and moves coverage to GS pixel centers.