diff --git a/examples/with_winit/Cargo.toml b/examples/with_winit/Cargo.toml index 3303388..24c157e 100644 --- a/examples/with_winit/Cargo.toml +++ b/examples/with_winit/Cargo.toml @@ -45,4 +45,4 @@ android_logger = "0.13.0" console_error_panic_hook = "0.1.7" console_log = "0.2" wasm-bindgen-futures = "0.4.33" -web-sys = "0.3.60" +web-sys = { version = "0.3.60", features = [ "HtmlCollection", "Text" ] } diff --git a/examples/with_winit/src/lib.rs b/examples/with_winit/src/lib.rs index e08add2..3d6422d 100644 --- a/examples/with_winit/src/lib.rs +++ b/examples/with_winit/src/lib.rs @@ -413,7 +413,7 @@ fn run( let size = window.inner_size(); let surface_future = render_cx.create_surface(&window, size.width, size.height); // We need to block here, in case a Suspended event appeared - let surface = pollster::block_on(surface_future); + let surface = pollster::block_on(surface_future).expect("Error creating surface"); render_state = { let render_state = RenderState { window, surface }; renderers.resize_with(render_cx.devices.len(), || None); @@ -453,6 +453,23 @@ enum UserEvent { HotReload, } +#[cfg(target_arch = "wasm32")] +fn display_error_message() -> Option<()> { + let window = web_sys::window()?; + let document = window.document()?; + let elements = document.get_elements_by_tag_name("body"); + let body = elements.item(0)?; + let canvas = body.first_child()?; + // TODO: style the notice at least a little, maybe link? + let text = document.create_text_node( + "WebGPU is not enabled. Make sure your browser is updated to + Chrome M113 or another browser compatible with WebGPU.", + ); + let _ = body.insert_before(&text, Some(&canvas)); + web_sys::console::log_1(&"got body".into()); + Some(()) +} + pub fn main() -> Result<()> { // TODO: initializing both env_logger and console_logger fails on wasm. // Figure out a more principled approach. @@ -496,9 +513,13 @@ pub fn main() -> Result<()> { let surface = render_cx .create_surface(&window, size.width, size.height) .await; - let render_state = RenderState { window, surface }; - // No error handling here; if the event loop has finished, we don't need to send them the surface - run(event_loop, args, scenes, render_cx, render_state); + if let Ok(surface) = surface { + let render_state = RenderState { window, surface }; + // No error handling here; if the event loop has finished, we don't need to send them the surface + run(event_loop, args, scenes, render_cx, render_state); + } else { + _ = display_error_message(); + } }); } } diff --git a/src/util.rs b/src/util.rs index 87e2d35..add0ea2 100644 --- a/src/util.rs +++ b/src/util.rs @@ -50,12 +50,20 @@ impl RenderContext { } /// Creates a new surface for the specified window and dimensions. - pub async fn create_surface(&mut self, window: &W, width: u32, height: u32) -> RenderSurface + pub async fn create_surface( + &mut self, + window: &W, + width: u32, + height: u32, + ) -> Result where W: HasRawWindowHandle + HasRawDisplayHandle, { - let surface = unsafe { self.instance.create_surface(window) }.unwrap(); - let dev_id = self.device(Some(&surface)).await.unwrap(); + let surface = unsafe { self.instance.create_surface(window) }?; + let dev_id = self + .device(Some(&surface)) + .await + .ok_or("Error creating device")?; let device_handle = &self.devices[dev_id]; let capabilities = surface.get_capabilities(&device_handle.adapter); @@ -75,12 +83,12 @@ impl RenderContext { view_formats: vec![], }; surface.configure(&self.devices[dev_id].device, &config); - RenderSurface { + Ok(RenderSurface { surface, config, dev_id, format, - } + }) } /// Resizes the surface to the new dimensions.