Expand description
§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.
let compiler = Wesl::new("src/shaders");
// 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:
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
The quote
feature flag provides the quote_*!
macros which let one write WGSL shaders
directly in source code. This has a few advantages:
- Like
quote
, it supports local variable injection. This can be used e.g. to customize a shader module at runtime. - The module is parsed at build-time, and syntax errors will be reported at the right location in the macro invocation.
- WGSL and Rust have a similar syntax. Your Rust syntax highlighter will also highlight injected WGSL code.
use wesl::syntax::*; // this is necessary for the quote_module macro
// this i64 value is computed at runtime and injected into the shader.
let num_iterations = 8i64;
// the following variable has type `TranslationUnit`.
let wgsl = wesl::quote_module! {
@fragment
fn fs_main(@location(0) in_color: vec4<f32>) -> @location(0) vec4<f32> {
for (let i = 0; i < #num_iterations; i++) {
// ...
}
return in_color;
}
};
One can inject variables into the following places by prefixing the name with
a #
symbol:
Code location | Injected type | Indirectly supported injection type with Into |
---|---|---|
name of a global declaration | GlobalDeclaration | Declaration TypeAlias Struct Function ConstAssert |
name of a struct member | StructMember | |
name of an attribute, after @ | Attribute | BuiltinValue InterpolateAttribute WorkgroupSizeAttribute TypeConstraint CustomAttribute |
type or identifier expression | Expression | LiteralExpression ParenthesizedExpression NamedComponentExpression IndexingExpression UnaryExpression BinaryExpression FunctionCallExpression TypeOrIdentifierExpression and transitively: bool i64 (AbstractInt) f64 (AbstractFloat) i32 u32 f32 Ident |
name of an attribute preceding and empty block statement | Statement | CompoundStatement AssignmentStatement IncrementStatement DecrementStatement IfStatement SwitchStatement LoopStatement ForStatement WhileStatement BreakStatement ContinueStatement ReturnStatement DiscardStatement FunctionCallStatement ConstAssertStatement DeclarationStatement |
use wesl::syntax::*; // this is necessary for the quote_module macro
let inject_struct = Struct::new(Ident::new("mystruct".to_string()));
let inject_func = Function::new(Ident::new("myfunc".to_string()));
let inject_stmt = Statement::Void;
let inject_expr = 1f32;
let wgsl = wesl::quote_module! {
struct #inject_struct { dummy: u32 } // structs cannot be empty
fn #inject_func() {}
fn foo() {
@#inject_stmt {}
let x: f32 = #inject_expr;
}
};
§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.
// ...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 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 |
Re-exports§
pub use eval::Eval;
eval
pub use eval::EvalError;
eval
pub use eval::Exec;
eval
pub use eval::Inputs;
eval
pub use eval::exec_entrypoint;
eval
Modules§
- eval
eval
- syntax
- A syntax tree for WGSL and WESL files. The root of the tree is
TranslationUnit
.
Macros§
- include_
wesl - Include a WGSL file compiled with
Wesl::build_artifact
as a string. - query
- query_
mut - quote_
declaration - quote_
directive - quote_
expression - quote_
import - quote_
literal - quote_
module - quote_
statement - wesl_
pkg - Include a generated package.
Structs§
- Basic
Source Map - Basic implementation of
SourceMap
. - Cache
Mangler - A mangler that remembers and can unmangle.
- Compile
Options - Compilation options. Used in
compile
andWesl::set_options
. - Compile
Result - The result of
Wesl::compile
. - Diagnostic
- Error diagnostics. Display user-friendly error snippets with
Display
. - Escape
Mangler - A mangler that replaces
::
with_
and prefixes components with the number of_
they contain. e.g.foo::bar_baz item => foo__1bar_baz_item
- Eval
Result eval
- The result of
CompileResult::eval
. - Exec
Result eval
- The result of
CompileResult::exec
. - Features
- Toggle conditional compilation feature flags.
- File
Resolver - A resolver that looks for files in the filesystem.
- Hash
Mangler - A mangler that hashes the module path.
e.g.
foo::bar::baz item => item_32938483840293402930392
- Module
Path - NoMangler
- A mangler that just returns the identifier as-is (no mangling).
e.g.
foo::bar::baz item => item
- NoResolver
- A resolver that never resolves anything.
- NoSource
Map - This
SourceMap
implementation simply does nothing and returnsNone
. - Pkg
- PkgBuilder
package
- A builder that generates code for WESL packages.
- PkgModule
- The type implemented by external packages.
- PkgResolver
- A resolver that only resolves module paths that refer to modules in external packages.
- Preprocessor
- A WESL module preprocessor.
- Router
- A resolver that can dispatch imports to several sub-resolvers based on the import path prefix.
- Source
Mapper - Generate a SourceMap by keeping track of loaded files and mangled identifiers.
- Standard
Resolver - The resolver that implements the WESL standard.
- Unicode
Mangler - A mangler that uses cryptic unicode symbols that look like :, < and >
e.g.
foo::bar::baz array<f32,2> => foo::bar::baz::arrayᐸf32ˏ2ᐳ
- Virtual
Resolver - A resolver that resolves in-memory modules added with
Self::add_module
. - Wesl
- The WESL compiler high-level API.
Enums§
- Cond
Comp Error - Conditional translation error.
- Error
- Any WESL error.
- Feature
- Set the behavior for a feature flag during conditional translation.
- Generics
Error generics
- Generics error (experimental)
- Import
Error - Error produced during import resolution.
- Mangler
Kind - Mangling scheme. Used in
Wesl::set_mangler
. - Resolve
Error - Error produced by module resolution.
- Validate
Error - WESL or WGSL Validation error.
Traits§
- Mangler
- A name mangler is responsible for renaming import-qualified identifiers into valid WGSL identifiers.
- Resolver
- A Resolver implements the module resolution algorithm: it returns a module contents associated with a module path.
- Source
Map - A SourceMap is a lookup from compiled WGSL to source WESL. It translates a mangled name into a module path and declaration name.
- Syntax
Util
Functions§
- compile
- Low-level version of
Wesl::compile
. To get a source map, usecompile_sourcemap
instead. - compile_
sourcemap - Like
compile
, but provides better error diagnostics and returns the sourcemap. - emit_
rerun_ if_ changed - eval
eval
- Low-level version of
eval_str
. - eval_
str eval
- Evaluate a const-expression.
- exec
eval
- Low-level version of
CompileResult::exec
. - lower
- Performs conversions on the final syntax tree to make it more compatible with WGSL implementations like Naga, catch errors early and perform optimizations.
- validate_
wesl - Validate an intermediate WESL module.
- validate_
wgsl - Validate the final output (valid WGSL).