With wgsl-rs you write a subset of Rust code and it automatically generates
WGSL shaders and wgpu runtime linkage. Rust code written this way is fully
operational (it can be run on the CPU) while the transpiled WGSL is isomorphic
and should generate the same results on the GPU.
In short, with wgsl-rs, you can unit test and run your code on the CPU in
Rust, and use the generated WGSL on the GPU, while sharing the same type
definitions between the two.
Procedural macros are provided by the
wgsl-rs-macros crate.
The canonical user-facing documentation is the
Operator's Manual —
an mdbook covering installation, writing shaders, types, generics, validation,
the standard library, wgpu linkage, extensions, memory layout, and a catalog of
35+ runnable examples. The book's sources live in book/ in this
repo.
New to wgsl-rs? Start with
Installation
and Hello, Triangle,
or browse the examples catalog.
To build the book locally:
mdbook build book/Or serve it with live reload:
mdbook serve book/ --openThere is a project plan for getting to beta here.
Yes! This is the canonical hello_triangle shader — ordinary Rust that the
#[wgsl] macro transpiles to WGSL. It is also valid Rust you can compile,
unit test, and run on the CPU:
#[wgsl]
pub mod hello_triangle {
use wgsl_rs::std::*;
uniform!(group(0), binding(0), FRAME: u32);
#[vertex]
pub fn vtx_main(#[builtin(vertex_index)] vertex_index: u32) -> Vec4f {
const POS: [Vec2f; 3] = [vec2f(0.0, 0.5), vec2f(-0.5, -0.5), vec2f(0.5, -0.5)];
let position = POS[vertex_index as usize];
vec4f(position.x, position.y, 0.0, 1.0)
}
#[fragment]
pub fn frag_main() -> Vec4f {
vec4f(1.0, sin(f32(get!(FRAME)) / 128.0), 0.0, 1.0)
}
}See the runnable example (transpiled from Tour of WGSL), or the manual's Hello, Triangle chapter for a line-by-line walkthrough.
Beyond the basics, wgsl-rs supports the features real renderers need:
- Generics — write generic shader entry points in Rust and instantiate them with turbofish at runtime; monomorphization produces concrete WGSL. Const generics and generic structs and impls work too. (templates)
- Binding macros —
uniform!,storage!,workgroup!,texture!,sampler!declare bindings once, visible in both Rust and WGSL. (binding macros) - Auto validation —
#[wgsl]modules get a hidden naga validation test; for template modules the test instantiates the template with the types given tovalidate_with_instantiation_types(T1, T2, ...)before validating. Either way,cargo testcatches invalid WGSL before it reaches the GPU. (validation) - wgpu linkage — generated modules provide bind group layouts, stage
visibility and pipeline layout helpers, so wiring up
wgpurequires no boilerplate. (linkage) - Extensions — implement
WgslExtensionto hook the IR directly: custom attributes, new statement macros, post-processing passes. (extensions) - Memory layout —
WgslLayoutand#[derive(Layout)]compute WGSL-conformant layouts so CPU structs match GPU buffers exactly. (layout)
This project is funded through NGI Zero Commons, a fund established by NLnet with financial support from the European Commission's Next Generation Internet program. Learn more at the 2025 NLnet project page.
This work will always be free and open source. If you use it (outright or for inspiration), please consider donating.
The project is split into a few parts:
wgsl-rs-macros— Thewgslprocedural macro for writing WGSL modules in Rust. Handles parsing and code generation for the supported Rust subset.wgsl-rs— TheSource/Moduletypes,wgsl::std, thewgslmacro re-export, extensions, and wgpu linkage.wgsl-rs-ir— The owned IR (Module,Type,Expr,Stmt,Item),render_module, andsubstitute_types.wgsl-rs-layout/wgsl-rs-layout-macros— WGSL memory layout computation (WgslLayout/Layouttraits,#[derive(Layout)]).example— Runnable example modules demonstrating every supported feature.xtask— Development tools (wgsl-spec,ci).roundtrip-tests— Tests ensuring the "two worlds" (CPU and GPU) agree.gpu-tests— GPU-side test harness.
There's also a devlog that explains the decisions and tradeoffs made during development.
Contributions, feedback, and questions are welcome!