Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

Welcome to the wgsl-rs operator’s manual. This book is the canonical, user-facing reference for writing GPU shaders with wgsl-rs.

FAQ

  1. How do I write shaders?
  2. How do I package my shaders?
    • They are already packaged within that same Rust module, automatically. No need to deal with shader source files. Instead, you access the module’s WGSL or linkage at runtime. Every #[wgsl_rs] annotated module contains a public WGSL_SOURCE item from which you can access an owned string of your raw WGSL source code, using Source::wgsl_source.
  3. How do I run my shaders?
  4. How do I test my shaders?
    • Using the usual Rust test tools. All Rust code written in a #[wgsl_rs] module can run on the CPU and therefore be tested - business as usual.
  5. How does wgsl-rs compare to other shader tools?

What is wgsl-rs?

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.

The Two Worlds Problem

A key insight that shapes everything about wgsl-rs is that it maintains two parallel representations of your shader:

  1. Rust World: The code must compile as valid Rust that runs on the CPU. This is design decision #1 in the devlog.
  2. WGSL World: The proc-macro transpiles to WGSL that runs on the GPU.

These are fundamentally different execution contexts with different memory models, and yet running a wgsl-rs program should produce roughly the same results in both “worlds”.

Program setup (or preamble, if you will) and the runtime behavior is expected to be different for each world, but the results should match, within reason. This is why wgsl-rs provides CPU-side implementations of every WGSL builtin in wgsl_rs::std, and why the roundtrip test harness exists — to verify that the two worlds agree.

How to Read This Book

Project Structure

The project is split into a few parts:

CratePurpose
wgsl-rsThe Module/Source type, wgsl::std, the wgsl macro re-export, extensions, and wgpu linkage.
wgsl-rs-irThe owned IR (Module, Type, Expr, Stmt, Item, etc.), render_module (IR → WGSL), and substitute_types.
wgsl-rs-macrosThe wgsl procedural macro — parsing and code generation for the supported Rust subset.
wgsl-rs-layoutWgslLayout and Layout traits for computing WGSL memory layout (§14.4.1).
wgsl-rs-layout-macros#[derive(Layout)] proc-macro.
exampleRunnable example modules demonstrating every supported feature.
xtaskDevelopment tools (wgsl-spec, ci).
roundtrip-testsTests ensuring the “two worlds” (CPU and GPU) agree.
gpu-testsGPU-side test harness.

There’s also a devlog that explains some of the decisions and tradeoffs made during the making of this library.

Funding

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.

NLnet foundation logo

NGI Zero Logo

This work will always be free and open source. If you use it (outright or for inspiration), please consider donating.

💰 Sponsor 💝