From 8df05d923d2e77a8c510fe51136882a14a814b82 Mon Sep 17 00:00:00 2001 From: Simon Gellis Date: Sat, 15 Feb 2025 16:55:21 -0500 Subject: [PATCH] Share one wgpu instance across all windows --- src/app.rs | 76 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 12 deletions(-) diff --git a/src/app.rs b/src/app.rs index 00e358f..0de36b1 100644 --- a/src/app.rs +++ b/src/app.rs @@ -35,6 +35,7 @@ fn load_icon() -> anyhow::Result { pub struct Application { icon: Option>, + wgpu: WgpuState, client: EmulatorClient, proxy: EventLoopProxy, mappings: MappingProvider, @@ -51,6 +52,7 @@ impl Application { proxy: EventLoopProxy, debug_port: Option, ) -> Self { + let wgpu = WgpuState::new(); let icon = load_icon().ok().map(Arc::new); let persistence = Persistence::new(); let mappings = MappingProvider::new(persistence.clone()); @@ -62,6 +64,7 @@ impl Application { } Self { icon, + wgpu, client, proxy, mappings, @@ -80,7 +83,7 @@ impl Application { } self.viewports.insert( viewport_id, - Viewport::new(event_loop, self.icon.clone(), window), + Viewport::new(event_loop, &self.wgpu, self.icon.clone(), window), ); } } @@ -238,6 +241,58 @@ impl ApplicationHandler for Application { } } +struct WgpuState { + instance: Arc, + adapter: Arc, + device: Arc, + queue: Arc, +} + +impl WgpuState { + fn new() -> Self { + let egui_wgpu::WgpuConfiguration { + wgpu_setup: + egui_wgpu::WgpuSetup::CreateNew { + #[allow(unused)] + supported_backends, + device_descriptor, + .. + }, + .. + } = egui_wgpu::WgpuConfiguration::default() + else { + panic!("required fields not found") + }; + #[cfg(windows)] + let supported_backends = wgpu::util::backend_bits_from_env() + .unwrap_or((wgpu::Backends::PRIMARY | wgpu::Backends::GL) - wgpu::Backends::VULKAN); + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { + backends: supported_backends, + ..wgpu::InstanceDescriptor::default() + }); + + let adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::HighPerformance, + compatible_surface: None, + force_fallback_adapter: false, + })) + .expect("could not create adapter"); + + let trace_path = std::env::var("WGPU_TRACE"); + let (device, queue) = pollster::block_on(adapter.request_device( + &(*device_descriptor)(&adapter), + trace_path.ok().as_ref().map(std::path::Path::new), + )) + .expect("could not request device"); + Self { + instance: Arc::new(instance), + adapter: Arc::new(adapter), + device: Arc::new(device), + queue: Arc::new(queue), + } + } +} + struct Viewport { painter: egui_wgpu::winit::Painter, ctx: Context, @@ -251,6 +306,7 @@ struct Viewport { impl Viewport { pub fn new( event_loop: &ActiveEventLoop, + wgpu: &WgpuState, icon: Option>, mut app: Box, ) -> Self { @@ -274,20 +330,16 @@ impl Viewport { }); egui_extras::install_image_loaders(&ctx); - #[allow(unused_mut)] - let mut wgpu_config = egui_wgpu::WgpuConfiguration { + let wgpu_config = egui_wgpu::WgpuConfiguration { present_mode: wgpu::PresentMode::AutoNoVsync, + wgpu_setup: egui_wgpu::WgpuSetup::Existing { + instance: wgpu.instance.clone(), + adapter: wgpu.adapter.clone(), + device: wgpu.device.clone(), + queue: wgpu.queue.clone(), + }, ..egui_wgpu::WgpuConfiguration::default() }; - #[cfg(windows)] - { - if let egui_wgpu::WgpuSetup::CreateNew { - supported_backends, .. - } = &mut wgpu_config.wgpu_setup - { - *supported_backends -= wgpu::Backends::VULKAN; - } - } let mut painter = egui_wgpu::winit::Painter::new(ctx.clone(), wgpu_config, 1, None, false, true);