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>
137 lines
5.5 KiB
Markdown
137 lines
5.5 KiB
Markdown
# Ch438 — source-space 3x3 binomial scanout (pre-fit)
|
|
|
|
## Why this chapter
|
|
|
|
Ch437 proved exact horizontal and vertical linear presentation, but the complete
|
|
f52 framebuffer still contains high-frequency speckle that the PCSX2 reference
|
|
does not. Adding more draws does not address that deficit. An offline filter
|
|
sweep identified a source-space separable `[1 2 1]/4` low-pass followed by the
|
|
authentic nearest presentation map as the best small, bounded scanout change.
|
|
|
|
The renderer and LPDDR framebuffer are unchanged. Ch438 only changes pixels at
|
|
the final HDMI scanout boundary, so the accepted f52 framebuffer SHA remains the
|
|
rollback and equivalence anchor.
|
|
|
|
## RTL architecture
|
|
|
|
- `gs_lpddr_scanout_lb.sv` adds opt-in `BINOMIAL_3X3_FILTER`.
|
|
- SH3 full-frame scanout disables the Ch436/437 linear filters and enables the
|
|
binomial filter.
|
|
- A third rotating line buffer retains source rows `y-1`, `y`, and `y+1`.
|
|
- Each physical line RAM still has one unconditional registered video read, the
|
|
Quartus-safe inference form established in Ch437.
|
|
- Six 256-bit register-cache slots retain the even/odd beats for all three rows.
|
|
- Horizontal and vertical passes each compute `(a + 2*b + c + 2) >> 2`.
|
|
- Horizontal edges clamp at source columns 0 and 511. Vertical edges clamp at
|
|
source rows 32 and 479.
|
|
- The filtered source pixel is presented with the captured nearest maps:
|
|
`sx=floor(x*4/5)` and `sy=32+floor(y*14/15)`.
|
|
- The AXI prefetcher still stays one source row ahead; its physical write target
|
|
now rotates 0/1/2 rather than alternating 0/1.
|
|
|
|
Expected fit delta from the accepted Ch437 build is one 640-pixel physical RAM
|
|
bank (approximately five M20Ks in the established 256-bit implementation), two
|
|
additional 256-bit beat-cache registers, and small shift/add logic. Ch437 used
|
|
344/358 RAM blocks, so the expected result is about 349/358.
|
|
|
|
## Exact preview result
|
|
|
|
Input framebuffer:
|
|
|
|
- `captures/gs/silenthill3/extracted/sh3_zsrt139f52_ch435_board.png`
|
|
- Its underlying f52 board dump is byte-identical to the accepted Ch436/437
|
|
framebuffer (`d0047677371a0f6e4e319458926f604a8599c92baaf34d09b8e1fd452e31662b`).
|
|
|
|
Reference: `captures/gs/silenthill3/pcsx2_ref_224139.png`.
|
|
|
|
| Scanout | MAE | RMSE |
|
|
|---|---:|---:|
|
|
| Ch437 separable linear | 13.9525 | 20.6568 |
|
|
| Ch438 3x3 binomial + nearest | 13.1111 | 19.1051 |
|
|
|
|
Preview:
|
|
`captures/gs/silenthill3/extracted/recon/sh3_zsrt139f52_ch438_binomial_preview.png`
|
|
|
|
Preview SHA-256:
|
|
`5a0402c523b64e252746067488177b08f0d23ab8a4a7dc09857e914c07f269f1`
|
|
|
|
The preview is generated by `tools/preview_scanout_ch438.py`, which reproduces
|
|
the RTL's rounding after each separable pass.
|
|
|
|
## Pre-fit verification
|
|
|
|
- `make -C sim tb_gs_lpddr_scanout_lb_binomial`
|
|
- 2,400/2,400 output pixels exact
|
|
- zero underflow
|
|
- zero read errors
|
|
- `make -C sim tb_gs_lpddr_scanout_lb_hstretch`
|
|
- Ch437 compatibility: 2,400/2,400 exact
|
|
- zero underflow/read errors
|
|
- `make -C sim tb_gs_lpddr_scanout_lb`
|
|
- legacy scanout PASS under its established one-pixel-per-line simulation
|
|
alignment allowance
|
|
- zero underflow/read errors
|
|
- Targeted Verilator lint of the binomial parameterization: no errors, latches,
|
|
multidriven signals, combinational loops, or range errors.
|
|
- Repository `git diff --check`: clean.
|
|
|
|
The repository-wide `make lint` still stops at the pre-existing unsupported
|
|
default-valued `rewind_i` input in `sif_dma_ee_ram_bridge_stub.sv`; the targeted
|
|
scanout lint is clean and this unrelated baseline issue was not changed.
|
|
|
|
## Owner fit gate
|
|
|
|
Ready for a fresh Quartus 26.1 GUI compile. Accept only if:
|
|
|
|
1. fit succeeds;
|
|
2. all setup/hold/recovery/removal/pulse-width checks are clean;
|
|
3. RAM use remains at or below 358 blocks;
|
|
4. all three scanline arrays infer as RAM rather than register banks.
|
|
|
|
## First fit and timing-root correction
|
|
|
|
The first Ch438 GUI fit completed successfully and confirmed the scanout
|
|
resource projection:
|
|
|
|
- 38,904 ALMs
|
|
- 57,173 registers
|
|
- 349/358 RAM blocks
|
|
- 160 DSP blocks
|
|
|
|
All non-setup checks were clean, but EMIF setup failed at `-0.120 ns`, TNS
|
|
`-3.122`, across 64 endpoints. The actual top-ten family was unrelated to the
|
|
new filter datapath:
|
|
|
|
- launch: `u_zc_emit|u_req|raddr_q[6]`
|
|
- capture: the deep request FIFO's packed `mem_rtl_0` port-B address banks
|
|
- launch-register fanout: 744
|
|
- data path: one 2.886 ns route, zero logic levels
|
|
|
|
This is the established 93-bit x 16K request-FIFO physical-address family. The
|
|
additional scanout RAM changed placement enough to expose it again.
|
|
|
|
The correction keeps the full 16K request depth and banks only the payload into
|
|
two independently inferred RAM arrays. Each half has a separate preserved
|
|
registered read address, reducing the single 744-load launch net to two roughly
|
|
half-sized physical trees. FIFO order, pointer CDC, and registered-read latency
|
|
are unchanged. The banked form is enabled only on `u_zc_emit.u_req`; all other
|
|
`gs_async_fifo` users retain the monolithic default.
|
|
|
|
Post-cut verification:
|
|
|
|
- default async FIFO stress: 3,285 writes/reads, zero errors;
|
|
- monolithic registered-read stress: 3,285 writes/reads, zero errors;
|
|
- banked registered-read stress: 3,285 writes/reads, zero errors;
|
|
- full f52 production Verilator replay:
|
|
- 311 epochs;
|
|
- 2,339,914 fragments fed;
|
|
- 2,286,292 passed;
|
|
- zero drops, color overflow, BRESP errors, Z mismatches, or color mismatches;
|
|
- PASS;
|
|
- post-cut framebuffer SHA-256:
|
|
`d0047677371a0f6e4e319458926f604a8599c92baaf34d09b8e1fd452e31662b`,
|
|
byte-identical to the accepted Ch437 board framebuffer.
|
|
|
|
The first timing-red RBF (`7fa4724f...`) was not deployed. A fresh GUI compile
|
|
is required for the banked-address correction.
|