ba74bbd5aa
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>
112 lines
5.7 KiB
Markdown
112 lines
5.7 KiB
Markdown
# 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.
|