diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 93afa6b..945d18d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -52,7 +52,14 @@ jobs:
# `ring` (under iroh) compiles C for wasm32, which needs clang and llvm-ar.
- name: clang
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends clang llvm
- - run: cargo check -p client --target wasm32-unknown-unknown --locked
+ # Both browser builds, without the dev features, as `web/build.sh dist both` makes them.
+ - name: check (webgl2)
+ run: cargo check -p client --target wasm32-unknown-unknown --locked --no-default-features
+ env:
+ CC_wasm32_unknown_unknown: clang
+ AR_wasm32_unknown_unknown: llvm-ar
+ - name: check (webgpu)
+ run: cargo check -p client --target wasm32-unknown-unknown --locked --no-default-features --features webgpu
env:
CC_wasm32_unknown_unknown: clang
AR_wasm32_unknown_unknown: llvm-ar
diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
index 193b3bb..3aee907 100644
--- a/.github/workflows/pages.yml
+++ b/.github/workflows/pages.yml
@@ -39,7 +39,8 @@ jobs:
# `ring` (under iroh) compiles C for wasm32, which needs clang and llvm-ar.
- name: clang
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends clang llvm
- - run: ./web/build.sh dist
+ # The WebGL2 build and the WebGPU one: the page picks by what the browser has.
+ - run: ./web/build.sh dist both
env:
LLVM: /usr
- uses: actions/upload-pages-artifact@v5
diff --git a/Cargo.lock b/Cargo.lock
index 285dc27..1f82725 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2419,6 +2419,8 @@ version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681"
dependencies = [
+ "serde",
+ "termcolor",
"unicode-width",
]
@@ -7330,6 +7332,15 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
+[[package]]
+name = "termcolor"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
+dependencies = [
+ "winapi-util",
+]
+
[[package]]
name = "thiserror"
version = "1.0.69"
@@ -8275,12 +8286,14 @@ dependencies = [
"hashbrown 0.17.1",
"js-sys",
"log",
+ "naga",
"portable-atomic",
"profiling",
"raw-window-handle",
"smallvec",
"static_assertions",
"wasm-bindgen",
+ "wasm-bindgen-futures",
"web-sys",
"wgpu-core",
"wgpu-hal",
diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml
index 05e41ae..420057b 100644
--- a/crates/client/Cargo.toml
+++ b/crates/client/Cargo.toml
@@ -14,6 +14,9 @@ tracy = ["bevy/trace_tracy"]
# Names the commands and components in Bevy's error and warning messages (instead of
# "Enable the debug feature to see the name"): `--features debug`.
debug = ["bevy/debug"]
+# The browser build draws through WebGPU instead of WebGL2 (`web/build.sh release webgpu`). Bevy
+# picks the backend as it is compiled: a browser without WebGPU gets no picture from this build.
+webgpu = ["bevy/webgpu"]
[dependencies]
bevy = { version = "0.20.0", features = [
diff --git a/macos/Info.plist b/macos/Info.plist
index 79fcda6..a09cce7 100644
--- a/macos/Info.plist
+++ b/macos/Info.plist
@@ -12,6 +12,8 @@
ctr-rs
CFBundlePackageType
APPL
+ LSApplicationCategoryType
+ public.app-category.racing-games
NSHighResolutionCapable
diff --git a/web/build.sh b/web/build.sh
index 0170e12..548fada 100755
--- a/web/build.sh
+++ b/web/build.sh
@@ -1,6 +1,9 @@
#!/bin/sh
-# Usage: web/build.sh [release|dev|dist], into target/web. Needs wasm-bindgen-cli at Cargo.lock's
-# version, wasm-opt for dist, and an LLVM clang that targets wasm (brew install llvm, or LLVM=).
+# Usage: web/build.sh [release|dev|dist] [webgl2|webgpu|both], into target/web. Needs
+# wasm-bindgen-cli at Cargo.lock's version, wasm-opt for dist, and an LLVM clang that targets wasm
+# (brew install llvm, or LLVM=). The page draws through WebGPU where the browser has it and
+# that build was made, and through WebGL2 elsewhere; with webgpu alone, a browser without WebGPU
+# shows nothing.
set -eu
cd "$(dirname "$0")/.."
@@ -27,12 +30,31 @@ else
features=
names=
fi
-cargo build -p client --target wasm32-unknown-unknown --profile "$profile" $features
-wasm-bindgen --target web --no-typescript $names --out-dir target/web/play --out-name client \
- "target/wasm32-unknown-unknown/$dir/client.wasm"
-if [ "$profile" = dist ]; then
- wasm-opt -O3 target/web/play/client_bg.wasm -o target/web/play/client_bg.wasm
-fi
+backends="${2:-webgl2}"
+case "$backends" in
+webgl2 | webgpu) ;;
+both) backends="webgl2 webgpu" ;;
+*) echo "unknown backend: $backends (webgl2, webgpu or both)" >&2; exit 1 ;;
+esac
+
+rm -rf target/web/play
+for backend in $backends; do
+ if [ "$backend" = webgpu ]; then
+ with=--features=webgpu
+ else
+ with=
+ fi
+ cargo build -p client --target wasm32-unknown-unknown --profile "$profile" $features $with
+ wasm-bindgen --target web --no-typescript $names --out-dir target/web/play \
+ --out-name "client-$backend" "target/wasm32-unknown-unknown/$dir/client.wasm"
+ if [ "$profile" = dist ]; then
+ wasm-opt -O3 "target/web/play/client-${backend}_bg.wasm" \
+ -o "target/web/play/client-${backend}_bg.wasm"
+ fi
+done
cp web/index.html target/web/
-cp web/play.html target/web/play/index.html
+# The page picks among the builds made here (`BUILT` in it).
+built=$(printf '"%s", ' $backends)
+sed "s/^const BUILT = \[\"webgl2\"\];/const BUILT = [${built%, }];/" web/play.html \
+ >target/web/play/index.html
cp -R web/fonts target/web/
diff --git a/web/play.html b/web/play.html
index cbbe1ff..c706d97 100644
--- a/web/play.html
+++ b/web/play.html
@@ -158,7 +158,7 @@
};
// Sound only starts after a key or click, so the game's audio contexts are resumed on one.
-// Must run before client.js is imported.
+// Must run before the game (`client-*.js`) is imported.
const audio = [];
window.AudioContext = new Proxy(window.AudioContext, {
construct(target, args) {
@@ -190,16 +190,31 @@
}