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:
@@ -0,0 +1,85 @@
|
||||
# Ch418 — authentic SH3 display presentation mapping (prefit)
|
||||
|
||||
## Objective
|
||||
|
||||
Fix the large presentation mismatch between the accepted Ch417 framebuffer and
|
||||
the PCSX2 224139 frame without changing any rasterized framebuffer byte. Ch418
|
||||
is scanout-only: it maps the captured GS display source onto the board's
|
||||
640x480 HDMI/VGA active raster.
|
||||
|
||||
## Captured register evidence
|
||||
|
||||
The vendored PCSX2 `GSPrivRegSet` layout was used to decode the initial and all
|
||||
eight per-vsync register snapshots in dump 224139. The active context is
|
||||
DISPLAY2 (`PMODE.EN2=1`), stable in every snapshot:
|
||||
|
||||
- `DISPFB2 = 0x0001000000009000` (FBP rotates later), `FBW=8`, `PSM=1`,
|
||||
`DBX=0`, `DBY=32`;
|
||||
- `DISPLAY2 = 0x0037f9ff0203228c`, `DX=652`, `DY=50`, `MAGH=4`,
|
||||
`MAGV=0`, `DW=2559`, `DH=895`.
|
||||
|
||||
Therefore the display source is 512 pixels wide (`FBW*64`) and 448 interlaced
|
||||
source lines beginning at framebuffer line 32. DISPLAY2 expands each source
|
||||
pixel to five VCKs (`MAGH+1`) across 2560 display clocks. Reducing that
|
||||
captured display to the board raster gives the exact integer maps:
|
||||
|
||||
```
|
||||
source_x = floor(output_x * 4 / 5) // 0..639 -> 0..511
|
||||
source_y = 32 + floor(output_y * 14 / 15) // 0..479 -> 32..479
|
||||
```
|
||||
|
||||
## RTL change
|
||||
|
||||
`gs_lpddr_scanout_lb` now has opt-in divider-free presentation mapping:
|
||||
|
||||
- a five-state horizontal phase accumulator implements 512 -> 640;
|
||||
- a fifteen-state vertical phase accumulator implements 448 -> 480;
|
||||
- vertical prefetch starts at captured `DBY=32`;
|
||||
- buffer parity, prefetch throttling, and underflow checks use mapped source y;
|
||||
- all default parameters retain the legacy 1:1 behavior.
|
||||
|
||||
Only `GS_SH3_LPDDR_FB_640` enables the mapping in the DE25 top. The OSD remains
|
||||
in the 640x480 output domain and the LPDDR framebuffer/dump remains byte-exact
|
||||
to Ch417.
|
||||
|
||||
The mapper contains no `/` or variable multiply in synthesizable RTL. Its
|
||||
datapath is one small phase decrement and one coordinate increment per output
|
||||
pixel/line, both in the 25 MHz video domain.
|
||||
|
||||
## Prefit verification
|
||||
|
||||
- New two-axis scanout oracle: 600/600 RGB pixels exact, including horizontal
|
||||
repeats, vertical repeats, DBY offset, alternating line buffers, zero
|
||||
underflow, and zero AXI read errors.
|
||||
- Legacy PSMCT16 line-buffer regression: PASS, underflow=0, read errors=0.
|
||||
- Legacy PSMCT32 line-buffer/concurrency regression: 49,152 pixels exact,
|
||||
underflow=0, read errors=0, 325/325 probes good.
|
||||
- The actual QSF profile macros plus `USE_QSYS_TOP` elaborate cleanly under
|
||||
Icarus (unavailable vendor IP treated as black boxes); no RTL binding or
|
||||
syntax errors.
|
||||
- `git diff --check` and the preview utility's Python compile pass.
|
||||
|
||||
Expected HDMI preview:
|
||||
|
||||
`sim/data/top_psmct32_raster_demo/sh3_zsrt139f17_ch418_scanout.png`
|
||||
|
||||
Preview SHA-256:
|
||||
|
||||
`b710aa7a09db6992faacdaa5a6257d490f1d4fa0112f6c6d20fc388f4b580a63`
|
||||
|
||||
The preview moves the already-rendered lamppost and character onto the PCSX2
|
||||
landmark positions. Full-frame RGB MAE rises from 20.12 to 21.02 because the
|
||||
board is still missing large bright/background draws that the transform now
|
||||
spreads over more output pixels; that global statistic is a coverage metric at
|
||||
this stage, not an alignment metric. The mapping is justified by the captured
|
||||
registers and visible landmark alignment, not by claiming a false MAE win.
|
||||
|
||||
## Owner fit gate
|
||||
|
||||
Ready for the owner-controlled Quartus 26.1 GUI compile. Required acceptance:
|
||||
|
||||
- Analysis & Synthesis succeeds with no inferred display divider;
|
||||
- setup, hold, recovery, removal, and minimum pulse all close;
|
||||
- after deployment, the unchanged 263-epoch board run still passes and the
|
||||
framebuffer dump remains byte-identical to Ch417;
|
||||
- HDMI shows the 512x448 captured source presented across 640x480.
|
||||
Reference in New Issue
Block a user