diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index 3261244e83a..44f24d8453b 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -280,6 +280,7 @@ web-sys = { version = "0.3.53", features = [ "GpuVertexStepMode", "HtmlCanvasElement", "OffscreenCanvas", + "ImageBitmapRenderingContext", "Window", ]} js-sys = "0.3.50" diff --git a/wgpu/examples/skybox_offscreen/main.rs b/wgpu/examples/skybox_offscreen/main.rs index 7394f750ccd..c1f67ff13e9 100644 --- a/wgpu/examples/skybox_offscreen/main.rs +++ b/wgpu/examples/skybox_offscreen/main.rs @@ -6,6 +6,8 @@ mod framework { event::{self, WindowEvent}, event_loop::{ControlFlow, EventLoop}, }; + use web_sys::{ImageBitmapRenderingContext, OffscreenCanvas}; + use wasm_bindgen::JsCast; #[allow(dead_code)] pub enum ShaderStage { @@ -62,6 +64,8 @@ mod framework { adapter: wgpu::Adapter, device: wgpu::Device, queue: wgpu::Queue, + bitmap_renderer: ImageBitmapRenderingContext, + offscreen_canvas: OffscreenCanvas, } async fn setup(title: &str) -> Setup { @@ -78,16 +82,28 @@ mod framework { .unwrap_or(log::Level::Error); console_log::init_with_level(level).expect("could not initialize logger"); std::panic::set_hook(Box::new(console_error_panic_hook::hook)); + // On wasm, append the canvas to the document body + let canvas = window.canvas(); + let canvas_clone = canvas.clone(); web_sys::window() .and_then(|win| win.document()) .and_then(|doc| doc.body()) .and_then(|body| { - body.append_child(&web_sys::Element::from(window.canvas())) + body.append_child(&web_sys::Element::from(canvas_clone)) .ok() }) .expect("couldn't append canvas to document body"); + let bitmap_renderer = canvas + .get_context("bitmaprenderer") + .expect("couldn't create ImageBitmapRenderingContext (Result)") + .expect("couldn't create ImageBitmapRenderingContext (Option)") + .dyn_into::() + .expect("couldn't convert into ImageBitmapRenderingContext"); + + let offscreen_canvas = OffscreenCanvas::new(1024, 768).expect("couldn't create OffscreenCanvas"); + log::info!("Initializing the surface..."); let backend = wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all); @@ -95,7 +111,7 @@ mod framework { let instance = wgpu::Instance::new(backend); let (size, surface) = unsafe { let size = window.inner_size(); - let surface = instance.create_surface(&window); + let surface = instance.create_surface_from_offscreen_canvas(&offscreen_canvas); (size, surface) }; let adapter = @@ -152,6 +168,8 @@ mod framework { adapter, device, queue, + bitmap_renderer, + offscreen_canvas, } } @@ -165,6 +183,8 @@ mod framework { adapter, device, queue, + bitmap_renderer, + offscreen_canvas, }: Setup, ) { let spawner = Spawner::new(); @@ -241,6 +261,8 @@ mod framework { example.render(&view, &device, &queue, &spawner); frame.present(); + let image_bitmap = offscreen_canvas.transfer_to_image_bitmap().expect("couldn't transfer offscreen canvas to image bitmap."); + bitmap_renderer.transfer_from_image_bitmap(&image_bitmap); } _ => {} } @@ -261,7 +283,7 @@ mod framework { } pub fn run(title: &str) { - use wasm_bindgen::{prelude::*, JsCast}; + use wasm_bindgen::prelude::*; let title = title.to_owned(); wasm_bindgen_futures::spawn_local(async move {