feat: web build via trunk with WebGPU detection + fallback
This commit is contained in:
parent
25e2207e0d
commit
9c8f384d0e
5
.cargo/config.toml
Normal file
5
.cargo/config.toml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# WebGPU bindings in web-sys are gated behind `web_sys_unstable_apis`.
|
||||||
|
# Enable that cfg when building for the web target only (harmless on desktop,
|
||||||
|
# where src/web.rs is cfg'd out anyway).
|
||||||
|
[target.'cfg(target_arch = "wasm32")']
|
||||||
|
rustflags = ["--cfg", "web_sys_unstable_apis"]
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
/target
|
/target
|
||||||
|
/dist
|
||||||
|
|||||||
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -4910,6 +4910,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy",
|
"bevy",
|
||||||
"bevy_egui",
|
"bevy_egui",
|
||||||
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -11,6 +11,7 @@ bevy_egui = "0.41"
|
|||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
web-sys = { version = "0.3", features = ["Gpu", "Navigator", "Window", "Document", "HtmlElement", "Element"] }
|
web-sys = { version = "0.3", features = ["Gpu", "Navigator", "Window", "Document", "HtmlElement", "Element"] }
|
||||||
wasm-bindgen = "0.2"
|
wasm-bindgen = "0.2"
|
||||||
|
js-sys = "0.3"
|
||||||
|
|
||||||
# Smaller wasm binary in release web builds (per Bevy examples README).
|
# Smaller wasm binary in release web builds (per Bevy examples README).
|
||||||
[profile.wasm-release]
|
[profile.wasm-release]
|
||||||
|
|||||||
8
Trunk.toml
Normal file
8
Trunk.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[build]
|
||||||
|
target = "web/index.html"
|
||||||
|
dist = "dist"
|
||||||
|
|
||||||
|
[serve]
|
||||||
|
address = "127.0.0.1"
|
||||||
|
port = 8080
|
||||||
|
open = false
|
||||||
23
src/main.rs
23
src/main.rs
@ -1,8 +1,29 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
use bevy::window::WindowPlugin;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
mod web;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// On web, abort startup if WebGPU isn't available and show a message.
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
{
|
||||||
|
if !web::webgpu_available() {
|
||||||
|
web::show_fallback_message();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins(DefaultPlugins)
|
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
||||||
|
primary_window: Some(Window {
|
||||||
|
title: "singularity-rs".into(),
|
||||||
|
// On web, make the canvas track the browser window size.
|
||||||
|
fit_canvas_to_parent: true,
|
||||||
|
..default()
|
||||||
|
}),
|
||||||
|
..default()
|
||||||
|
}))
|
||||||
.add_systems(Startup, setup)
|
.add_systems(Startup, setup)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|||||||
42
src/web.rs
Normal file
42
src/web.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
use wasm_bindgen::JsCast;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
pub fn webgpu_available() -> bool {
|
||||||
|
// `navigator.gpu` is gated in web-sys behind `web_sys_unstable_apis` and its
|
||||||
|
// getter returns `Gpu` directly (not `Option<Gpu>`), so we probe the JS
|
||||||
|
// object for the property instead. Reflect::has returns `true` when the
|
||||||
|
// browser exposes the WebGPU API.
|
||||||
|
web_sys::window()
|
||||||
|
.and_then(|w| {
|
||||||
|
let nav = w.navigator();
|
||||||
|
js_sys::Reflect::has(nav.as_ref(), &"gpu".into()).ok()
|
||||||
|
})
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
pub fn show_fallback_message() {
|
||||||
|
if let Some(window) = web_sys::window() {
|
||||||
|
if let Some(document) = window.document() {
|
||||||
|
if let Some(body) = document.body() {
|
||||||
|
let el = document
|
||||||
|
.create_element("div")
|
||||||
|
.unwrap()
|
||||||
|
.unchecked_into::<web_sys::HtmlElement>();
|
||||||
|
el.set_inner_text(
|
||||||
|
"WebGPU is not available in this browser. \
|
||||||
|
Please use a recent version of Chrome, Edge, or Firefox.",
|
||||||
|
);
|
||||||
|
el.set_attribute(
|
||||||
|
"style",
|
||||||
|
"position:fixed;inset:0;display:flex;align-items:center;\
|
||||||
|
justify-content:center;font-family:sans-serif;font-size:1.5rem;\
|
||||||
|
text-align:center;padding:2rem;background:#111;color:#eee;",
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
|
body.append_child(&el).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
web/index.html
Normal file
21
web/index.html
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>singularity-rs</title>
|
||||||
|
<style>
|
||||||
|
html, body { margin: 0; padding: 0; height: 100%; overflow: hidden; background: #000; }
|
||||||
|
canvas { width: 100vw; height: 100vh; display: block; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<link
|
||||||
|
data-trunk rel="rust"
|
||||||
|
href="../Cargo.toml"
|
||||||
|
data-bin="singularity-rs"
|
||||||
|
data-type="main"
|
||||||
|
data-cargo-features="bevy/webgpu"
|
||||||
|
data-wasm-opt="z"
|
||||||
|
/>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
x
Reference in New Issue
Block a user