From 0c25d32445e00e76cd5987f9a33ce58bb68eaa8a Mon Sep 17 00:00:00 2001 From: "prompt.ac/@jeffrey" Date: Sat, 10 Oct 2026 13:06:13 -0700 Subject: [PATCH] =?UTF-8?q?KidLisp:=20the=20GPU=20frame=20rows=20in=20the?= =?UTF-8?q?=20benchmark=20and=20=C2=A79=20in=20the=20design?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kidlisp/PIECE-IL.md | 23 +++++++++++++++++++ .../whistlegraph-benchmark-2026-10-10.md | 9 ++++++++ 2 files changed, 32 insertions(+) diff --git a/kidlisp/PIECE-IL.md b/kidlisp/PIECE-IL.md index dbd23a7fb6..d6a97ce2bb 100644 --- a/kidlisp/PIECE-IL.md +++ b/kidlisp/PIECE-IL.md @@ -247,3 +247,26 @@ output stay in the closure compiler. Kernels take the parts that are already maps over data, which the census says is most of the arithmetic in the two big pieces: projection, star fields, the skirt's bands, the soldier's boxes. + +## 9. The frame as one buffer: drawing on the GPU + +A compiled piece that says `; @gpu` does not call the software rasterizer. +Its drawing heads record into a frame buffer (`lib/gpu-frame.mjs`): clear, +line, box, oval, tri and shape, each with its colour, one Float32Array a +frame, handed to bios in a single transferred message. bios tessellates it +to triangles with per-vertex colour and draws it with WebGPU in one pass on +its own canvas (`lib/gpu-frame-renderer.mjs`), then composites the CPU +buffer over it as a texture when the frame asks, so `write` and anything +the path does not take still show. `ink` keeps running on the CPU for its +colour parsing and the resolved colour is read back; `wipe` clears both. +The worker probes bios once; without a renderer the piece draws on the CPU +as before, same stream. + +Measured 2026-10-11, phone size / 1280×720: Fía 36 / 21 fps from 31 / 20 +on the CPU path; the shooter 25 / 24 from 22 / 22. The pictures match. The +format is the contract: a native host can consume the same buffer. + +What is left after this is evaluation and the runtime's own per-frame +work. Kernels (§8) take the data-parallel arithmetic; the whole program to +Wasm takes the rest, and a host that keeps kernel outputs on the GPU and +draws from them never pays a readback at all. diff --git a/kidlisp/reports/whistlegraph-benchmark-2026-10-10.md b/kidlisp/reports/whistlegraph-benchmark-2026-10-10.md index f9b7cd237e..50534468a6 100644 --- a/kidlisp/reports/whistlegraph-benchmark-2026-10-10.md +++ b/kidlisp/reports/whistlegraph-benchmark-2026-10-10.md @@ -21,6 +21,8 @@ into pools. | Fía | compiler v3 + the heart projection as a Wasm kernel | 26,921 | 420 | 28 | 16 | | Fía | … and no HUD colouring for the hidden label | 26,921 | 420 | 31 | 20 | | Shooter | compiler v3, no HUD colouring | 22,380 | 383 | 22 | 22 | +| Fía | … and the frame drawn by WebGPU (`; @gpu`) | 26,928 | 421 | 36 | 21 | +| Shooter | … and the frame drawn by WebGPU (`; @gpu`) | 22,387 | 384 | 25 | 24 | The compiler rows are the same sources with a `; @compile` first line (`lib/kidlisp-compile.mjs`, later the same day): the program compiled once @@ -48,6 +50,13 @@ is now skipped for a hidden label (339d671608). The star field in runtime (35 against 60 fps at phone size): a compute pass has to read its results back for a CPU rasterizer, and that costs more than the arithmetic. +The `; @gpu` rows (8754e56644, PIECE-IL.md §9): the compiled program +records its drawing into one buffer a frame (`lib/gpu-frame.mjs`) and bios +draws it with WebGPU as one vertex buffer and one draw +(`lib/gpu-frame-renderer.mjs`), the CPU buffer composited on top for text. +The frames match the CPU path's picture. What remains is evaluation and the +runtime's per-frame work around it; the rasterizer is off the clock. + ## What it says - **Size is a wash.** Prefix arithmetic costs what closures saved. A line -- 2.51.2