igc_conformance.py pins the reference behaviour any port (RTL/GPU/C) must reproduce: the DUMP packet parse, a synthetic raster, the bars pipeline (texu==x+2 from the real cap7 tile programs), and the fxtest effect primitives (coverage + z pinned) -- fixtures committed under conformance/. GPU-RETARGET.md maps the DOSBox-renderer path: EMC tile as compute shader (pixel=thread), 4 milestones, conformance-gated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.3 KiB
GPU-compute retarget — the DOSBox-renderer path (2026-07-19)
Companion to FPGA-RECONSTRUCTION.md. This is the plan for shipping the decoded IGC/EMC model as a real-time renderer behind the existing DOSBox seam — the practical answer to "use this as the renderer for the pod."
Why GPU compute
The EMC array is 8,192 bit-serial PEs per 64×128 tile. On a GPU that is one thread per pixel executing the same decoded op stream — a literal 1:1 mapping, no hardware, ships as software next to the renderer we already deploy. The original array ran ~40 MHz bit-serial; any integrated GPU exceeds the whole frame's work by orders of magnitude.
Architecture
DOSBox (game, unmodified)
│ wire protocol (known) ── existing seam: render-bridge/live_bridge
▼
emu860 geometry stage ── the i860 firmware, C/JIT port for realtime
│ per-draw DMA stream + payloads (the coefficient programs)
▼
IGC translator (host) ── igc_exec.parse -> flat op records
│ SSBO: op stream + payload floats + tile list
▼
compute shader "EMC tile" ── pixel = thread; fields in registers/LDS:
│ texz/texu/texv/zbuf as uint20, r/g/b as uint8, enable as bool;
│ ops = a switch over the named table (TREE*, MEM*, CPY, sweeps, SCA*)
▼
readout pass ── ramp(texu) / rgb24 -> RGBA8 frame texture
▼
present (the existing renderer window / vr_readpixels reply)
What ports 1:1 from the golden model
- The op table (data) and parser — host-side, unchanged.
- Tile semantics — each
Tile.runbranch becomes a shader case; the pixel memory bit-fields become packed uints (no bit-serial emulation needed: field-level semantics are already proven equivalent by the conformance suite). - Readout — ramp LUT as a small texture.
Conformance gate
igc_conformance.py (C1-C4, committed fixtures) is the acceptance bar: the
shader path must reproduce C2-C4 outputs exactly (C1 is host-side parse).
Add a C5 full-frame image hash (bars + fxtest frames) once texel sampling
lands.
Realtime budget (per frame)
- 52 tiles × ~100-3000 op-steps × 8,192 px ≈ 1-10 G pixel-ops worst case — a compute-shader trifle at 60 fps on integrated graphics.
- Geometry stage: the real wall. emu860 in Python ≈ 600K steps/s; a frame is ~10-50M steps → need the C/JIT step-core (planned; the i860 ISA semantics are fully pinned by emu860 + MAME cross-validation). Interim: pre-captured streams replay at full speed for validation.
Milestones
- M1 shader tile: WGPU/GL compute kernel executing the named ops; passes C2-C4. (small)
- M2 frame loop: DMA-stream walker + tile dispatch + readout; renders the bars + fxtest fixtures. (small-medium)
- M3 texel path: TXDN stream -> texture sampling (needs the remaining spec work — the io-port fetch protocol). (medium, spec-gated)
- M4 live seam: behind live_bridge in place of / beside the GL renderer; real-time gate = the C step-core for emu860. (the big one, independent)
Open spec items feeding this (tracked in IGC-ENCODING-DERIVATION.md)
- op-0x2c edge exact semantics (winding rule) — affects M1 fidelity.
- TXDN io-port texel stream — gates M3.
- The texz coordinate-seed op + the real ramp tables — purity for M2 images.