Explain reading many pixels and the remaining WSL gap (#283)

admin committed 2026-09-29 22:08:03 +02:00
1 parent 02ac5dac84
commit 8a37cc494c
1 file changed
+15 -2
+15 -2
@@ -138,6 +138,15 @@ A menu's tick boxes are read through `t.menuTicked()` as `{ label, ticked }`. Th
`tests/ui/fonts.test.ts` reads the character map straight out of the font files and fails on any
character in `src/` that one of the shipped faces lacks.
**Many pixels are one read, not many.** Every `__gm.pixelAt` renders the stage into a render
texture of its own and waits for the GPU to hand the pixel back: about 2 ms here, about 7 ms
behind the WSL runner's d3d12 driver. A step that samples a grid or a strip asks
`__gm.pixels([{ x, y }, …])` (or `__gm.pixelRow(x, y, count)`) instead, which renders once around all
the points and answers each exactly as `pixelAt` would. Measured on both runners: the same colour
at all 10,680 points of six screen rows, three columns and 600 scattered points, and a row of 1280
in 4 to 18 ms instead of 2.4 to 9.9 s. Only whole pixels at a resolution of 1 share the frame;
anything else falls back to one read a point.
**What no colour check can see: whether anything was drawn at all.** `__gm.pixelAt` re-renders the
stage on demand, so it answers correctly on a screen that has been frozen for a minute — which is
exactly the failure mode of drawing on change instead of every frame (see *Architecture*). The
@@ -305,8 +314,12 @@ The **GPU is not in this repo**. It comes from `container.options` in each runne
the GPU through Mesa's d3d12 driver: `ANGLE (Microsoft Corporation, D3D12 (NVIDIA GeForce RTX
4070), OpenGL 4.2)`, WebGL 2.0, 60 frames a second. A Wayland chromium reached the GPU as well,
but let the editor's clock stall in long runs.
The suite takes about 40% longer there than here, almost all of it in the modules that read
back many pixels (drawing, tilemaps, shaders).
Every GL call there passes through ANGLE, Mesa's d3d12 driver and the Windows driver, and that
costs chromium's GPU process far more CPU than Vulkan does here: in a `perf` sample three
quarters of its time sat in the driver stack. Reading pixels back cost three times as much,
which the steps now avoid (see *Many pixels are one read* above). Frames with real work in them
(tilemaps, the graph) still take longer than here, and no chromium or Mesa switch changed that:
`mesa_glthread`, `--in-process-gpu`, software compositing and EGL were each tried and measured.
Without these options chromium falls back to software rendering, and the harness stops at the
renderer check.