Skip to content
lee mighdoll edited this page Apr 15, 2025 · 7 revisions

WESL currently provides these functionalities:

  • Imports allow splitting code in multiple files.
  • Packages are collections of general-purpose shader modules published to npm (JavaScript) and crates.io (Rust).
  • Conditional Translation is a mechanism to conditionally include/exclude chunks of code. Similar to #ifdef (C/C++) or #[cfg] (Rust).
  • ...More Coming Soon!

Import Statements

Import statements are placed at the top of your file. All they do is add a declaration present in another file to the scope.

import sdf::primitives::box;         // import function `box` in module `primitives` in package `sdf`.
import package::bindings::mySampler; // import declaration `mySampler` from file `bindings.wesl` located at the root of this package.
import super::util;                  // import the entire sibling module `./util.wesl`.
import package::animals::{           // you can nest imports with `{ }`.
    bird,
    mammals::{ dog, cat }
};
  • What can be imported? - You can import all top-level declarations in a file: functions, structs, variables and aliases. You can also import whole modules.
  • How to locate a file? - The first segment indicate where to look for the file:
    • If it is super, start from the folder containing the current file. You can chain supers to walk up the file tree.
    • If it is package, start at the package root (provided to the linker).
    • Any other name corresponds to an external package.

Qualified names

In addition to import statements, you can write directly the path to a declaration at the usage site.

import package::math;

fn main() {
    package::my_mod::my_submod::my_fn(); // import statement not required.
    let x = math::constants::PI;         // module `math` was imported, you can access its declarations with a qualified name.
}

Shader entrypoints and co.

We recommend putting shader entrypoints and pipeline overridable constants in the root module. This ensures that they do not get mangled.

@if attribute

The @if(condition) attribute makes the following element optionally included in the final shader, depending on the condition. The condition is made of feature flags which are set when you invoke the linker (wesl-js or wesl-rs).

@if(debug_mode && !raytracing_disabled) // attributes on top-level declarations 
var<private> debug_count_iterations: i32 = 0;

@if(is_2d)
alias point = vec2f;
@if(!is_2d) // the @else block is in discussion, meanwhile just negate the if condition.
alias point = vec3f;

struct Line {
    start_point: point, end_point: point,
    @if(colored) color: vec4f, // attributes on struct members
}

fn fibonacci(n: u32) {
    @if(use_lookup_table) { // attributes on blocks `{ }`
        const lut = array(0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144);
        return lut[n];
    }
    // ...
}

The condition is a boolean expression containing: feature names, && (and), || (or), ! (not), true and false.

You can place attributes on declarations (functions, structs, variables, etc.), statements, struct members and function parameters.

Next Steps

Visit the Reference page for the complete documentation of WESL Extensions.

Documentation has moved → wesl-lang.dev

This wiki is no longer maintained.

Clone this wiki locally