wgsl-rs beta release retro
wgsl-rs is released!๐
Wow! So much work went into this beta release. It's been the most organized project I've ever attempted, and I think that shows in the beta project board.
If you're interested in what wgsl-rs is, see the github repo https://github.com/schell/wgsl-rs,
or the previous article Introducing wgsl-rs.
Life events๐
Looking back, wgsl-rs was definitely a bite too big for me to chew as a single developer working
part time. But luckily, I lost my day job early September and found myself with all the time in
the world to work on the project ๐.
(I didn't really have all the time, but I had more than usual)
Highlights๐
In the four months since Introducing wgsl-rs, the work has primarily been about three
things:
Pivoting
wgpucodegen onto the runtime IRSystematically closing every place Rust and WGSL silently disagree
Actually shipping the
0.1.0-beta(which consisted of ensuring I covered the WGSL vocab, fixed bugs and had documentation in place)
I went digging through the devlog to find the most interesting-for-a-technical-audience developments.
The top 5 most interesting things, I think๐
The operator precedence flip (#159, Sept 20).
Problem: Rust binds
& ^ | << >>tighter than==; WGSL binds the reverse. The renderer emitted binary expressions flat, so(0 & 0) == 0in Rust became0 & 0 == 0in WGSL, which re-parses as0 & (0 == 0)โ a silent type-error miscompile (same class broke-(a + b)into-a + b).Fix: fully parenthesize every binary expression, deliberately choosing "correctness over output polish" over a precedence-aware renderer.
Vector equality is a mask (#164, Sept 15).
Problem: Rust
==yieldsbool; WGSL==yieldsvecN.Fix: Rust code could never produce the componentwise mask, so wgsl-rs added a post-monomorphization pass rewriting vector
==toall(lhs == rhs)(and!=to!(all(...))), pluscmp_eq/cmp_nefree functions as the componentwise escape hatch. The pass fails open on un-inferable types so CPU-only code keeps compiling.
The literal-suffix pass (#145, Sept 21โ26).
Problem: Rust infers
0asu32from context; WGSL defaults bare ints toi32, soselect(0, 1, data)compiled in Rust and failednagavalidation.Fix: I (and GLM 5.2) built a scope-tracking "anchoring pass" placed at the deshadow slot so it sees all four sources of literals (source, const substitution, type substitution, extension lowering). After seven review rounds with Copilot and Kimi K3 it was consolidated into a bottom-up
infer(expr) -> Optionwith an exhaustive match and no catch-all. Loop-variable typing mirrors rustc's backward inference via a "probe, not a constraint solver."
Runtime wgpu linkage from the IR (June 6, #120, plus July 11/18).
~650 lines of proc-macro-generated
wgpucodegen (walking thesyntree) were replaced by runtime IR traversal. This unlocked a rad feature: generic "template" modules can now produce realwgpupipelines after callingpath::to::module::instantiate::()at runtime. Buffer sizing follows WGSL ยง14.4.1 instead ofsize_of::, which was wrong for non-() repr(C)structs. The API split is a nice design story:wgsl_rs::Sourceis "the spec,"ir::Moduleis "the AST," and methods live in extension traits becausewgsl-rs-ircan't depend onwgsl-rswithout a cycle.
Binding stage visibility from the call graph (July 18, then #177, Sept 20).
Problem: The analyzer hardcoded
ShaderStages::all(), which silently demandedVERTEX_WRITABLE_STORAGEand broke everyread_writecompute dispatch.Fix: Two iterations: first per-entry-point identifier scanning, then full transitive call-graph reachability, so bindings used only in helper functions resolve correctly. A whole-module scan was rejected because over-broad visibility forces features on users who don't want them.
Users๐
Part of the impetus to jam on the beta release is that the project already has users! There's two users in particular that reached out to me. The first is Jak Kos (jakkos-net on github).
Hiya, super cool project, I've been having fun the last few days porting the wgsl shaders of my gamedev project over, so thank you :D ! -- jakkos-net
They identified a bunch of gaps in my initial build out like missing support for storage textures.
They've been really helpful, creating tickets for bugs
they've found while they port their game to wgsl-rs.
Thank you Jak! ๐
gpui-ce๐
The other exciting development is that the gpui-ce project is using wgsl-rs for their shader layer.
gpui-ce is a community fork of the Zed editor's gpui crate.
It offers an immediate-mode rendering API (though it's more nuanced than that) inspired by the web DOM.
It's a big impressive project with currently 1.2k stars and I'm honored that they've integrated my project.
Funnily enough, I almost missed learning about this since my email client put Miles Wirht's introductory email in the spam folder! Miles is a maintainer of the project and reached out to say hi and show me the shaders in their repo.
Thanks Miles!
Others?๐
If you're using wgsl-rs and would like a mention, please reach out!
That's a wrap ๐ฏ๐
My next focus is going to be on porting crabslab and craballoc from Rust-GPU to wgsl-rs.
After that I'll be writing an ECS that runs on the GPU and then using this whole stack to rewrite the shaders and linkage of Renderling.
Thanks for reading :)