9 unstable releases (3 breaking)

Uses new Rust 2024

0.4.1 Jul 24, 2026
0.4.0 May 19, 2026
0.3.2 Dec 27, 2025
0.2.0 Jul 28, 2025
0.1.1 Feb 26, 2025

#17 in Data formats

Download history 4770/week @ 2026-04-12 4201/week @ 2026-04-19 3817/week @ 2026-04-26 5374/week @ 2026-05-03 2850/week @ 2026-05-10 4432/week @ 2026-05-17 3537/week @ 2026-05-24 2830/week @ 2026-05-31 3579/week @ 2026-06-07 2684/week @ 2026-06-14 2942/week @ 2026-06-21 2638/week @ 2026-06-28 3400/week @ 2026-07-05 3918/week @ 2026-07-12 4076/week @ 2026-07-19 4831/week @ 2026-07-26

16,739 downloads per month
Used in 23 crates (12 directly)

MIT/Apache

1MB
25K SLoC

WESL: A Community Standard for Enhanced WGSL

This is the crate for all your WESL needs.

See also the standalone CLI.

Basic Usage

See Wesl for an overview of the high-level API.

# use wesl::{Wesl, VirtualResolver};
let compiler = Wesl::new("src/shaders");
# // just adding a virtual file here so the doctest runs without a filesystem
# let mut resolver = VirtualResolver::new();
# resolver.add_module("package::main".parse().unwrap(), "fn my_fn() {}".into());
# let compiler = compiler.set_custom_resolver(resolver);

// compile a WESL file to a WGSL string
let wgsl_str = compiler
    .compile(&"package::main".parse().unwrap())
    .inspect_err(|e| eprintln!("WESL error: {e}")) // pretty errors with `display()`
    .unwrap()
    .to_string();

Usage in build.rs

In your Rust project you probably want to have your WESL code converted automatically to a WGSL string at build-time, unless your WGSL code must be assembled at runtime.

Add this crate to your build dependencies in Cargo.toml:

[build-dependencies]
wesl = "0.1"

Create the build.rs file with the following content:

# use wesl::{Wesl, FileResolver};
fn main() {
    Wesl::new("src/shaders")
        .build_artifact(&"package::main".parse().unwrap(), "my_shader");
}

Include the compiled WGSL string in your code:

let module = device.create_shader_module(ShaderModuleDescriptor {
    label: Some("my_shader"),
    source: ShaderSource::Wgsl(include_wesl!("my_shader")),
});

Write shaders inline with the quote_module macro

See the wesl-quote crate.

Evaluating const-expressions

This is an advanced and experimental feature. wesl-rs supports evaluation and execution of WESL code with the eval feature flag. Early evaluation (in particular of const-expressions) helps developers to catch bugs early by improving the validation and error reporting capabilities of WESL. Full evaluation of const-expressions can be enabled with the lower compiler option.

Additionally, the eval feature adds support for user-defined @const attributes on functions, which allows one to precompute data ahead of time, and ensure that code has no runtime dependencies.

The eval/exec implementation is tested with the WebGPU Conformance Test Suite.

# use wesl::{Wesl, VirtualResolver, eval_str};
// ...standalone expression
let wgsl_expr = eval_str("abs(3 - 5)").unwrap().to_string();
assert_eq!(wgsl_expr, "2");

// ...expression using declarations in a WESL file
let source = "const my_const = 4; @const fn my_fn(v: u32) -> u32 { return v * 10; }";
# let mut resolver = VirtualResolver::new();
# resolver.add_module("package::source".parse().unwrap(), source.into());
# let compiler = Wesl::new_barebones().set_custom_resolver(resolver);
let wgsl_expr = compiler
    .compile(&"package::source".parse().unwrap()).unwrap()
    .eval("my_fn(my_const) + 2").unwrap()
    .to_string();
assert_eq!(wgsl_expr, "42u");

Features

name description Status/Specification
generics user-defined type-generators and generic functions experimental
package create shader libraries published to crates.io experimental
eval execute shader code on the CPU and @const attribute experimental
naga-ext enable all Naga/WGPU extensions experimental
serde derive Serialize and Deserialize for syntax nodes

Dependencies

~7–9MB
~156K SLoC