docs: add T8 (CRT shader fails to compile) + verified headless SwiftShader recipe

This commit is contained in:
Hermes Cron Job committed 2026-10-06 17:57:14 +00:00
1 parent da97ed7780
commit ab96608cdd
1 file changed
+72 -2
+72 -2
View File
@@ -10,8 +10,12 @@ code, not inferred from the README. Upstream: `mac-ai-playground/retro-flight-si
- `npm test` — passes, but see T4: it only counts braces. - `npm test` — passes, but see T4: it only counts braces.
- Terrain is deterministic across instances (`getHeightAt(317,-812)` identical in two - Terrain is deterministic across instances (`getHeightAt(317,-812)` identical in two
separate `Terrain` objects) — the "persistent world" claim holds. separate `Terrain` objects) — the "persistent world" claim holds.
- Rendering **not** visually verified: the audit box has no GPU and SwiftShader crashes - Rendering **verified in software** (SwiftShader, see "How to run it headless" below):
the page. Needs a run on real hardware. WebGL 2 context, 60 fps, 143 distinct colours, 63,792/64,000 non-black pixels, HUD
canvas drawing 6,905 lit pixels. No GPU is involved — this LXC has no `/dev/dri` and no
`/dev/nvidia*`, so all rendering is CPU-rasterised.
- **T8 found during that verification**: the CRT post-processing shader does not compile,
so the 3D canvas renders pure black on any machine. See T8.
--- ---
@@ -87,6 +91,35 @@ not the same thing.
**Fix:** persist the world seed + aircraft state; add a save/load menu entry. **Fix:** persist the world seed + aircraft state; add a save/load menu entry.
## T8 — The CRT shader does not compile, so the 3D canvas is black
Found by running the game under software WebGL, not by reading the code. `js/retro.js:29`:
```glsl
gl_Position = vec4(position, 0.0, 1.0);
```
In three.js `position` is a **vec3**, so this asks for `vec4(vec3, float, float)` — five
components into a four-component vector. Invalid GLSL ES on both WebGL 1 and 2:
```
THREE.WebGLProgram: Shader Error 0 - VALIDATE_STATUS false
Program Info Log: Vertex shader is not compiled.
ERROR: 0:71: 'constructor' : too many arguments
```
The whole post-processing pass therefore fails and the game canvas reads back as **one
colour, 0/64,000 non-black pixels**. Verified in isolation: `vec4(vec3, float)` compiles,
`vec4(vec3, float, float)` does not, on both WebGL 1 and WebGL 2.
**Fix (verified):** `gl_Position = vec4(position.xy, 0.0, 1.0);` — compiles clean, and the
canvas then reports 143 distinct colours, 63,792/64,000 non-black pixels, scanline banding
visible every 25 rows, and the scene hash changing frame to frame once the aircraft moves.
Applied locally during the audit to confirm it, then reverted — not committed.
Note this is the kind of bug the current test suite cannot see (see T4): braces balance
perfectly.
## T7 — Minor / housekeeping ## T7 — Minor / housekeeping
- `index.html` requests `/favicon.ico` → 404 on every load. Add one, or drop the request. - `index.html` requests `/favicon.ico` → 404 on every load. Add one, or drop the request.
@@ -98,6 +131,43 @@ not the same thing.
--- ---
## How to run it headless (no GPU, verified working)
This LXC has no GPU access — `lspci`/`lsmod` inside an LXC report the **Proxmox host's**
hardware (an RTX 3090 shows up), but the container has no `/dev/dri` and no `/dev/nvidia*`,
so nothing is usable. Software rendering is the only option and it does work.
The combination that works:
```bash
CHROME=/root/.cache/ms-playwright/chromium-1234/chrome-linux64/chrome
$CHROME --headless=new --no-sandbox --disable-gpu-sandbox \
--use-angle=swiftshader --enable-unsafe-swiftshader \
--remote-debugging-port=9223 --user-data-dir=/tmp/probe --no-first-run
# then attach with playwright-core: chromium.connectOverCDP('http://127.0.0.1:9223')
```
Gotchas, all learned the hard way:
- **Playwright's own launcher defeats this.** `chromium.launch()` injects defaults
(`--disable-gpu` among them) that silently kill the GPU process; every attempt via
`launch()` returned `webgl: NULL` or crashed the page. Launch Chrome directly and attach
over CDP instead.
- `--use-gl=swiftshader` (legacy path) crashes the page. Use `--use-angle=swiftshader`.
- `--use-angle=vulkan` + Mesa lavapipe (`VK_DRIVER_FILES=/usr/share/vulkan/icd.d/lvp_icd.json`)
brings the GPU process up (`GPU.EstablishGpuChannel` records samples) but still yields no
WebGL context. SwiftShader is the path that works.
- Headful under `xvfb-run` crashes the page. `--headless=new` is required.
- `--dump-dom` races the page script — it captures before the probe writes its result.
- WebGL clears the drawing buffer after each frame (`preserveDrawingBuffer: false`), so a
synchronous `readPixels` returns all-black. Sample inside a `requestAnimationFrame`
callback, or the measurement is meaningless.
- `readPixels` origin is bottom-left; flip rows before reporting them as screen rows.
- Screenshots via CDP fail here (`Unable to capture screenshot`), so verification is by
pixel readback and colour histograms rather than images.
---
## Suggested order ## Suggested order
T1 → T4 (tests first would be better, but T1 is the reason the project is worth keeping) T1 → T4 (tests first would be better, but T1 is the reason the project is worth keeping)