Declarative WebGPU with S-expressions WebGPU wiring you can ship and share 23-Aug-2026 About me Start here All posts Feed
This is pngine, a declarative format and runtime for WebGPU I've been working on for the past 2.5 years:
( shader-module :name code :code " " " @vertex fn vertexMain( @builtin(vertex_index) VertexIndex : u32 ) -> @builtin(position) vec4f { var pos = array<vec2f, 3>( vec2(0.0, 0.5), vec2(-0.5, -0.5), vec2(0.5, -0.5) ); return vec4f(pos[VertexIndex], 0.0, 1.0); } @fragment fn fragMain() -> @location(0) vec4f { return vec4(1.0, 0.0, 0.0, 1.0); } " " " ) ( render-pipeline :name pipeline :layout auto ( vertex :module code :entry vertexMain ) ( fragment :module code :entry fragMain ( target :format preferred-canvas-format ) ) ) ( render-pass :name trianglePass ( color-attachment :view context-current-texture :clear-value [ 0 0 0 0 ] :load-op clear :store-op store ) :pipeline pipeline ( draw :vertex-count 3 ) ) ( frame :name main :perform [ trianglePass ] )
The code above is a simple red triangle done in WebGPU using S-expressions for the plumbing that match 1:1 with the WebGPU spec.
1-2-3 pngine
Pngine has three main capabilities:
It allows you to declare and ship WebGPU plumbing (shaders and cpu/wasm init included), in a cross-platform way (not restricted to browsers, works with rust wgpu too, and players exist for android and ios).
It validates the declared WebGPU configuration using WGSL reflection and spec checks, producing errors and warnings without requiring a live WebGPU context. It also has an LSP so it happens while you type.
It can export everything to a single .html, or a .zip or a .png file, allowing you to hand someone a PNG that runs itself (the .png does not auto-execute, it just contains the bytecodes, you still need a tiny player to read it and play on your demand).
The last part is the cool one, it's where the "png" in pngine comes from because the S-expressions are compiled to a binary representation which is then interpreted by a tiny runtime. That runtime and payload can be put in an extra PNG chunk, while the PNG itself remains the preview image for what you're shipping.
... continue reading