Skip to content
This repository has been archived by the owner on Jun 18, 2021. It is now read-only.

Running on the Web with WebGPU and WebGL

Connor Fitzgerald edited this page May 1, 2021 · 8 revisions

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

WebGPU Support

As of 2021-01-23, 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.

WebGL Code Changes

To use WebGL, the following changes to your code must be made:

  • When creating an instance and enumerating adapters, you must use wgpu::BackendBit::all().
  • Enable the webgl feature of wgpu.

Compiling for WASM

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

# Install or update wasm-bindgen-cli
cargo install -f wasm-bindgen-cli --version 0.2.73

# 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 WebGPU

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>

Setting up WebGL

First you need to copy the following files from spirv-cross's wasm folder and into your target/generated:

Then, 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 src="./spirv_cross_wrapper_glsl.js"></script>
  <script type="module">
    import init from "./hello-triangle.js"; <!-- Change this file to the name of the example you are using -->
    window.addEventListener("load", () => {
      const module = window.sc_internal_wrapper().then(module => {
        window.sc_internal = module;
        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.