diff --git a/wgpu/examples/framework.rs b/wgpu/examples/framework.rs index 6a052d7075..e665e4386c 100644 --- a/wgpu/examples/framework.rs +++ b/wgpu/examples/framework.rs @@ -1,4 +1,4 @@ -use futures::{task::{LocalSpawn}, executor::{block_on, LocalPool}}; +use futures::task::LocalSpawn; #[cfg(not(target_arch = "wasm32"))] use std::time::{Duration, Instant}; use winit::{ @@ -54,7 +54,18 @@ pub trait Example: 'static + Sized { ); } -pub fn run(title: &str) { +struct Setup { + window: winit::window::Window, + event_loop: EventLoop<()>, + instance: wgpu::Instance, + size: winit::dpi::PhysicalSize, + surface: wgpu::Surface, + adapter: wgpu::Adapter, + device: wgpu::Device, + queue: wgpu::Queue, +} + +async fn setup(title: &str) -> Setup { let event_loop = EventLoop::new(); let mut builder = winit::window::WindowBuilder::new(); builder = builder.with_title(title); @@ -65,6 +76,67 @@ pub fn run(title: &str) { } let window = builder.build(&event_loop).unwrap(); + log::info!("Initializing the surface..."); + + let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY); + let (size, surface) = unsafe { + let size = window.inner_size(); + let surface = instance.create_surface(&window); + (size, surface) + }; + + let (needed_extensions, unsafe_extensions) = E::needed_extensions(); + + let adapter = instance + .request_adapter( + &wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::Default, + compatible_surface: Some(&surface), + }, + unsafe_extensions, + ) + .await + .unwrap(); + + let adapter_extensions = adapter.extensions(); + + let trace_dir = std::env::var("WGPU_TRACE"); + let (device, queue) = adapter + .request_device( + &wgpu::DeviceDescriptor { + extensions: adapter_extensions & needed_extensions, + limits: wgpu::Limits::default(), + shader_validation: true, + }, + trace_dir.ok().as_ref().map(std::path::Path::new), + ) + .await + .unwrap(); + + Setup { + window, + event_loop, + instance, + size, + surface, + adapter, + device, + queue, + } +} + +fn start( + Setup { + window, + event_loop, + instance, + size, + surface, + adapter, + device, + queue, + }: Setup, +) { #[cfg(not(target_arch = "wasm32"))] let (mut pool, spawner) = { env_logger::init(); @@ -75,10 +147,11 @@ pub fn run(title: &str) { wgpu::util::initialize_default_subscriber(chrome_tracing_dir.ok()); }; - let local_pool = LocalPool::new(); + let local_pool = futures::executor::LocalPool::new(); let spawner = local_pool.spawner(); (local_pool, spawner) }; + #[cfg(target_arch = "wasm32")] let spawner = { use futures::{future::LocalFutureObj, task::SpawnError}; @@ -109,47 +182,6 @@ pub fn run(title: &str) { WebSpawner {} }; - log::info!("Initializing the surface..."); - - let (size, surface, instance, adapter, device, queue) = block_on(async { - let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY); - let (size, surface) = unsafe { - let size = window.inner_size(); - let surface = instance.create_surface(&window); - (size, surface) - }; - - let (needed_extensions, unsafe_extensions) = E::needed_extensions(); - - let adapter = instance - .request_adapter( - &wgpu::RequestAdapterOptions { - power_preference: wgpu::PowerPreference::Default, - compatible_surface: Some(&surface), - }, - unsafe_extensions, - ) - .await - .unwrap(); - - let adapter_extensions = adapter.extensions(); - - let trace_dir = std::env::var("WGPU_TRACE"); - let (device, queue) = adapter - .request_device( - &wgpu::DeviceDescriptor { - extensions: adapter_extensions & needed_extensions, - limits: wgpu::Limits::default(), - shader_validation: true, - }, - trace_dir.ok().as_ref().map(std::path::Path::new), - ) - .await - .unwrap(); - - (size, surface, instance, adapter, device, queue) - }); - let mut sc_desc = wgpu::SwapChainDescriptor { usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, // TODO: Allow srgb unconditionally @@ -244,6 +276,21 @@ pub fn run(title: &str) { }); } +#[cfg(not(target_arch = "wasm32"))] +pub fn run(title: &str) { + let setup = futures::executor::block_on(setup::(title)); + start::(setup); +} + +#[cfg(target_arch = "wasm32")] +pub fn run(title: &str) { + let title = title.to_owned(); + wasm_bindgen_futures::spawn_local(async move { + let setup = setup::(&title).await; + start::(setup); + }); +} + // This allows treating the framework as a standalone example, // thus avoiding listing the example names in `Cargo.toml`. #[allow(dead_code)]