Skip to content

Running on the Web with WebGPU and WebGL

Lucas Kent edited this page Oct 15, 2021 · 17 revisions

Running on the web is still work-in-progress. The WebGL2 backend is still experimental and is missing many features and WebGPU support in browsers is only available in nightly browsers.

Both webgpu and webgl2 backends run in wasm, so you need to install this specific version of wasm-bindgen-cli:

cargo install -f wasm-bindgen-cli --version 0.2.73

WebGL2

There is a script included in the WGPU repo for easily compiling and running the examples for WebGL. The script may be extended later to support running WebGPU examples, too.

To use the script simply run it from the terminal. You must have bash installed:

./run-wasm-example.sh [example]

For instance, to run the shadow example:

$ ./run-wasm-example.sh shadow
Compiling...
    Finished dev [unoptimized + debuginfo] target(s) in 0.05s
Generating bindings...
/home/zicklag/.cargo/bin/basic-http-server
Serving example with basic-http-server at http://localhost:1234

The script will look for a static file server on your machine and use the first one it finds to serve the example and print out the local address so you can connect to it in your browser.

That's it! You can copy the script, or adjust the steps for your own build system to compile your own projects for WebGL.

WebGPU

As of 2021-10-07, you need to enable experimental flags on your browser to use WebGPU -- for up to date browser implementation status, check webgpu.io. Notably, wgpu-rs is often ahead in catching up with upstream WebGPU API changes. We keep the gecko branch pointing to the code that should work on latest Firefox.

Compiling

To run examples on the wasm32-unknown-unknown target, first build the example as usual, then run wasm-bindgen:

# Checkout `gecko` branch that matches the state of Firefox
git checkout upstream/gecko

# Build with the wasm target
# Since "cross" is enabled by default but useful for this target, we disable default features
RUSTFLAGS=--cfg=web_sys_unstable_apis cargo build --no-default-features --target wasm32-unknown-unknown --example hello-triangle

# Generate bindings in a `target/generated` directory for the hello-triangle example
wasm-bindgen --out-dir target/generated --web target/wasm32-unknown-unknown/debug/examples/hello-triangle.wasm

Setting up Wasm

Create an index.html file in target/generated directory and add the following code:

<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  </head>
  <body>
    <script type="module">
      import init from "./hello-triangle.js"; // Change this file to the name of the example you are using
      init();
    </script>
  </body>
</html>

Running the Code

Now run a web server locally inside the target/generated directory to see the hello-triangle in the browser. Examples of servers are rust's simple-http-server target/generated, miniserve target/generated, or other languages ruby -run -e httpd -p 8000 target/generated. Python's debug server (python -m http.server target/generated) may have issues with MIME types causing failures.