Skip to content

Running on the Web with WebGPU and WebGL

Jinlei Li edited this page Jul 28, 2023 · 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.

Running examples

Installing the Rust WebAssembly target

To build the wgpu example programs for execution in a browser, you must first install the Rust toolchains for the wasm32-unknown-unknown target. Using rustup:

rustup target add wasm32-unknown-unknown

To see the targets you have already installed:

$ rustup target list --installed
wasm32-unknown-unknown
x86_64-unknown-linux-gnu
$ 

WebGL2

wgpu examples can be run in a browser via wasm with a single command which aliases to a rust crate:

cargo xtask run-wasm --bin [example] --features webgl

For instance, to run the cube example:

user@machine wgpu$ cargo xtask run-wasm --bin cube --features webgl
    Finished release [optimized] target(s) in 0.03s
     Running `target/release/run-wasm --example cube --features webgl`
   Compiling wgpu v0.13.2 (/home/user/Projects/Crates/wgpu/wgpu)
    Finished dev [unoptimized + debuginfo] target(s) in 1.26s

Serving `cube` on http://localhost:1234

That's it! Just point your browser at the listed address.

If you want a similar setup for your project, then note that:

WebGPU

As of 2022-09-20, 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.

The same script can be used, just without the last argument:

RUSTFLAGS=--cfg=web_sys_unstable_apis cargo run-wasm --example [example]

Note: --cfg=web_sys_unstable_apis needs to be in RUSTFLAGS because webgpu is unstable and unstable APIs don't follow web_sys semver.

Manual compilation with wasm-bindgen-cli

First install the version of wasm-bindgen-cli that matches the version used by wgpu:

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

Then build the example for wasm32-unknown-unknown and run wasm-bindgen on the output:

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

# Build with the wasm target
RUSTFLAGS=--cfg=web_sys_unstable_apis cargo build --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:

<!DOCTYPE html>
<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.