wgpuをwasmで動かす

wgpuをwasm向けにビルドしたときのメモ。

環境

  • rustc: 1.69.0
  • wgpu: 0.16.1
  • wasm-bindgen: 0.2.86

問題点

wasm-packでビルドしたところ、以下のようなエラーが発生。

% wasm-pack build --target web --out-dir client/pkg
[INFO]: 🎯  Checking for the Wasm target...
[INFO]: 🌀  Compiling to Wasm...
...
Some errors have detailed explanations: E0412, E0432, E0433, E0599.
For more information about an error, try `rustc --explain E0412`.
error: could not compile `wgpu` due to 200 previous errors
Error: Compiling your crate to WebAssembly failed
Caused by: Compiling your crate to WebAssembly failed
Caused by: failed to execute `cargo build`: exited with exit status: 101
...

大量にエラーが出たが、どうやらWebGPUのAPIが有効になっていない様子。

解決策

WebGPUのAPIを有効にするため、以下のように.cargo/config.tomlを設定。

[build]
rustflags = ["--cfg=web_sys_unstable_apis"]

これでビルドが通ってwasmが生成されるようになった。

WebGLにフォールバックする方法

WebGPU APIを使う場合は上記の方法でOKだが、WebGPU APIが使えないブラウザで動かしたい場合はWebGLにフォールバックする必要がある。

その場合、まずはwgpuのfeatureを有効化する。

...
wgpu = {version = "0.16.1", features = ["webgl"]}
...

次に、wgpuのDevice作成時にlimitsでWebGLのデフォルト値を使うようにする。

...
    let (device, queue) = adapter
        .request_device(
            &wgpu::DeviceDescriptor {
                label: None,
                features: wgpu::Features::empty(),
                #[cfg(not(feature = "webgl"))]
                limits: wgpu::Limits::default()
                #[cfg(feature = "webgl")]
                limits: wgpu::Limits::downlevel_webgl2_defaults()
            },
            None,
        )
        .await
        .expect("No suitable GPU device found on the system!");
...

これでWebGPUがWebGLにフォールバックするようになる。 ただし、WebGLにフォールバックするとCompute Shader等のWebGLでサポートされていない機能は使えない。