WESL Logo

JavaScript Runtime Linking

Runtime linking enables custom shaders adapted to the user’s application environment:

The link() API offers options for runtime control of WESL shader transpilation.

#requestWeslDevice for Source Mapped Errors

The wesl library includes requestWeslDevice() which can be optionally used in place of WebGPU’s GPUAdapter.requestDevice() for improved error reporting.

Each WebGPU implementation analyzes WGSL to find user errors or safety violations. WESL is transpiled into WGSL, and so it’s handy to see any errors WGSL in terms of the original WESL. requestWeslDevice() returns a WeslDevice, an extended WebGPU GPUDevice. A WESLDevice captures compilation errors from WebGPU and attaches the WESL source.

A WeslDevice is as a GPUDevice and can be used everywhere a GPUDevice is used.

#Conditions

To set a condition for use in @if conditional translation, pass a conditions option to link() with boolean values for the conditions. Unset conditions are presumed falsy.

    /// main.ts
    import appWesl from "../shaders/app.wesl?link";

    link({...appWesl, conditions: { MOBILE: true }});
    /// app.wesl
    @if(MOBILE) var size = 8;

#Runtime Constants

To inject constants from JavaScript/TypeScript for WESL shader compilation, pass a constants option to link() with string or numeric values for the constants. WESL shaders can use the constants by importing from the constants virtual module.

    /// main.ts
    link({..., constants: { NumLights: 7 }});
    /// app.wesl
    var<private> lights: array<vec3f, constants::NumLights>;

#Virtual Modules

To use a function that generates WESL/WGSL shader code from JavaScript at runtime, use the virtualLibs option. Pass a record with the name of the virtual module as a key, and the generating function as a value.

    /// main.ts
    link({..., virtualLibs: { MyCustom: () => "fn custom() {}" }});
    /// app.wesl
    import MyCustom::custom;

    fn example() {
      custom();
    }

#Custom Extensions

To plug in a custom extension that extends the linker itself with a WeslJsPlugin, use the config option.

    /// main.ts
    link({..., config: { plugins: bindingStructsPlugin() }});

#Further Details

See LinkParams for further details on runtime linking options.