Skip to content
Tech News
← Back to articles

Declarative WebGPU with S-Expressions

read original more articles
Why This Matters

The introduction of pngine, a declarative format for WebGPU using S-expressions, marks a significant advancement in simplifying and sharing GPU programming across platforms. Its validation, cross-platform compatibility, and innovative export options empower developers and consumers to create portable, self-contained graphics assets, potentially transforming how WebGPU applications are developed and distributed.

Key Takeaways

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