Getting Started JavaScript - wgsl-tooling-wg/wesl-spec GitHub Wiki

Quick Start

Here's typical setup for a front end application using wesl and wesl-plugin/vite .

Install

npm install wesl                      # for runtime linking
npm install --save-dev wesl-plugin    # for bundler integration

Configure Vite

/// vite.config.ts
import viteWesl from "wesl-plugin/vite";
import { linkBuildExtension } from "wesl-plugin";

export default {
  plugins: [viteWesl({ extensions: [linkBuildExtension] })],
};

Link at Runtime

import { link, createWeslDevice } from "wesl";
import appWesl from "../shaders/app.wesl?link";

async function example() {
  const device = createWeslDevice(await navigator.gpu.requestAdapter()); 
  const linked = await link(appWesl);
  const shaderModule = linked.createShaderModule(device, {});
}

Other Build Environments

WESL is easy to integrate into a diverse variety of JavaScript/TypeScript build environments. See JavaScript Builds .

Default Project Organization

./wesl.toml - optional project configuration file

./shaders - default location for .wesl and .wgsl files.

wesl.toml

Customize configuration for your project by creating a wesl.toml file in the same directory as package.json. Here's an example:

/// wesl.toml
weslFiles = [ "./shaders/**/*.w[eg]sl" ]
weslRoot = "./shaders" 
dependencies = ["random_wgsl"]

wesl.toml settings below. All settings are optional. A wesl.toml is not required if the default setting are sufficient.

  • weslFiles - an array of globs locating shader files.

    default weslFiles = [ "./shaders/**/*.w[eg]sl" ]

  • weslRoot - ignored prefix for shader module paths.

    import statements inside wesl files use module paths (with :: separators). The module paths are mapped directly from shader file paths skipping past the weslRoot.

    default weslRoot = [ "./shaders" ]

  • dependencies - list of npm package names for shader dependencies

    All dependencies should also be listed in package.json. Only direct dependencies should be listed.

    default - dependencies = []

wesl.toml is used by development tools like the wesl-plugin, wesl-packager, and the forthcoming WESL language server.

Runtime Linking Options

The link() API enables runtime control of WESL shader transpilation.

Runtime linking options allow for adapting shaders to user application environments:

  • Tune shaders based on runtime checks of GPU capabilities
  • Customize shaders according on web application settings
  • Augment shaders with frameworks that dynamically generate shader fragments,
  • Extend the linker itself with wesl-js extensions

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() }});

Runtime Linking Details

See LinkParams for further details on runtime linking options.

⚠️ **GitHub.com Fallback** ⚠️