diff --git a/Cargo.lock b/Cargo.lock index e5dc05b12cc..68f288c1836 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1079,9 +1079,10 @@ dependencies = [ [[package]] name = "d3d12" version = "0.7.0" +source = "git+https://github.com/gfx-rs/wgpu#7774f310218bd688e27e7688f3ddf8cd39226c96" dependencies = [ "bitflags 2.4.0", - "libloading 0.8.0", + "libloading 0.7.4", "winapi", ] @@ -2441,6 +2442,7 @@ dependencies = [ [[package]] name = "naga" version = "0.14.2" +source = "git+https://github.com/gfx-rs/wgpu#7774f310218bd688e27e7688f3ddf8cd39226c96" dependencies = [ "bit-set", "bitflags 2.4.0", @@ -4224,6 +4226,7 @@ checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" [[package]] name = "wgpu" version = "0.18.0" +source = "git+https://github.com/gfx-rs/wgpu#7774f310218bd688e27e7688f3ddf8cd39226c96" dependencies = [ "arrayvec", "cfg-if", @@ -4247,10 +4250,12 @@ dependencies = [ [[package]] name = "wgpu-core" version = "0.18.0" +source = "git+https://github.com/gfx-rs/wgpu#7774f310218bd688e27e7688f3ddf8cd39226c96" dependencies = [ "arrayvec", "bit-vec", "bitflags 2.4.0", + "cfg_aliases", "codespan-reporting", "indexmap", "log", @@ -4270,6 +4275,7 @@ dependencies = [ [[package]] name = "wgpu-hal" version = "0.18.0" +source = "git+https://github.com/gfx-rs/wgpu#7774f310218bd688e27e7688f3ddf8cd39226c96" dependencies = [ "android_system_properties", "arrayvec", @@ -4277,6 +4283,7 @@ dependencies = [ "bit-set", "bitflags 2.4.0", "block", + "cfg_aliases", "core-graphics-types", "d3d12", "glow 0.13.0 (git+https://github.com/grovesNL/glow.git?rev=29ff917a2b2ff7ce0a81b2cc5681de6d4735b36e)", @@ -4288,7 +4295,7 @@ dependencies = [ "js-sys", "khronos-egl", "libc", - "libloading 0.8.0", + "libloading 0.7.4", "log", "metal", "naga", @@ -4311,6 +4318,7 @@ dependencies = [ [[package]] name = "wgpu-types" version = "0.18.0" +source = "git+https://github.com/gfx-rs/wgpu#7774f310218bd688e27e7688f3ddf8cd39226c96" dependencies = [ "bitflags 2.4.0", "js-sys", diff --git a/Cargo.toml b/Cargo.toml index 78632938b68..e70fd9d3a16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,9 +54,6 @@ puffin = "0.18" raw-window-handle = "0.5.0" thiserror = "1.0.37" -wgpu = { path = "../wgpu/wgpu", features = [ +wgpu = { git = "https://github.com/gfx-rs/wgpu", commit = "7774f31", features = [ "fragile-send-sync-non-atomic-wasm", -] } # Make the renderer `Sync` even on wasm32, because it makes the code simpler: - -# Use this to build wgpu with WebGL support on the Web *instead* of using WebGPU. -#wgpu = { version = "0.18.0", features = ["webgl"] } +] } # Make the renderer `Sync` even on wasm32, because it makes the code simpler:# TODO: Use a stable version of wgpu. diff --git a/crates/eframe/src/native/glow_integration.rs b/crates/eframe/src/native/glow_integration.rs index 6c2a0654c1b..fd1b502590a 100644 --- a/crates/eframe/src/native/glow_integration.rs +++ b/crates/eframe/src/native/glow_integration.rs @@ -126,7 +126,7 @@ struct Viewport { // These three live and die together. // TODO(emilk): clump them together into one struct! gl_surface: Option>, - window: Option>, + window: Option>, egui_winit: Option, } @@ -373,7 +373,7 @@ impl WinitApp for GlowWinitApp { self.running.as_ref().map(|r| &r.integration) } - fn window(&self, window_id: WindowId) -> Option> { + fn window(&self, window_id: WindowId) -> Option> { let running = self.running.as_ref()?; let glutin = running.glutin.borrow(); let viewport_id = *glutin.viewport_from_window.get(&window_id)?; @@ -952,7 +952,7 @@ impl GlutinWindowContext { screenshot_requested: false, viewport_ui_cb: None, gl_surface: None, - window: window.map(Rc::new), + window: window.map(Arc::new), egui_winit: None, }, ); @@ -1031,7 +1031,7 @@ impl GlutinWindowContext { ); viewport.info.minimized = window.is_minimized(); viewport.info.maximized = Some(window.is_maximized()); - viewport.window.insert(Rc::new(window)) + viewport.window.insert(Arc::new(window)) }; viewport.egui_winit.get_or_insert_with(|| { @@ -1120,7 +1120,7 @@ impl GlutinWindowContext { .expect("viewport doesn't exist") } - fn window(&self, viewport_id: ViewportId) -> Rc { + fn window(&self, viewport_id: ViewportId) -> Arc { self.viewport(viewport_id) .window .clone() diff --git a/crates/eframe/src/native/wgpu_integration.rs b/crates/eframe/src/native/wgpu_integration.rs index 395eb04297a..2141883b529 100644 --- a/crates/eframe/src/native/wgpu_integration.rs +++ b/crates/eframe/src/native/wgpu_integration.rs @@ -84,7 +84,7 @@ pub struct Viewport { /// Window surface state that's initialized when the app starts running via a Resumed event /// and on Android will also be destroyed if the application is paused. - window: Option>, + window: Option>, /// `window` and `egui_winit` are initialized together. egui_winit: Option, @@ -170,9 +170,11 @@ impl WgpuWinitApp { self.native_options.viewport.transparent.unwrap_or(false), ); + let window = Arc::new(window); + { crate::profile_scope!("set_window"); - pollster::block_on(painter.set_window(ViewportId::ROOT, Some(&window)))?; + pollster::block_on(painter.set_window(ViewportId::ROOT, Some(window.clone())))?; } let wgpu_render_state = painter.render_state(); @@ -260,7 +262,7 @@ impl WgpuWinitApp { }, screenshot_requested: false, viewport_ui_cb: None, - window: Some(Rc::new(window)), + window: Some(window), egui_winit: Some(egui_winit), }, ); @@ -323,7 +325,7 @@ impl WinitApp for WgpuWinitApp { self.running.as_ref().map(|r| &r.integration) } - fn window(&self, window_id: WindowId) -> Option> { + fn window(&self, window_id: WindowId) -> Option> { self.running .as_ref() .and_then(|r| { @@ -544,7 +546,8 @@ impl WgpuWinitRunning { { crate::profile_scope!("set_window"); - if let Err(err) = pollster::block_on(painter.set_window(viewport_id, Some(window))) + if let Err(err) = + pollster::block_on(painter.set_window(viewport_id, Some(window.clone()))) { log::warn!("Failed to set window: {err}"); } @@ -797,7 +800,10 @@ impl Viewport { Ok(window) => { windows_id.insert(window.id(), viewport_id); - if let Err(err) = pollster::block_on(painter.set_window(viewport_id, Some(&window))) + let window = Arc::new(window); + + if let Err(err) = + pollster::block_on(painter.set_window(viewport_id, Some(window.clone()))) { log::error!("on set_window: viewport_id {viewport_id:?} {err}"); } @@ -813,7 +819,7 @@ impl Viewport { self.info.minimized = window.is_minimized(); self.info.maximized = Some(window.is_maximized()); - self.window = Some(Rc::new(window)); + self.window = Some(window); } Err(err) => { log::error!("Failed to create window: {err}"); @@ -930,7 +936,7 @@ fn render_immediate_viewport( { crate::profile_scope!("set_window"); - if let Err(err) = pollster::block_on(painter.set_window(ids.this, Some(window))) { + if let Err(err) = pollster::block_on(painter.set_window(ids.this, Some(window.clone()))) { log::error!( "when rendering viewport_id={:?}, set_window Error {err}", ids.this diff --git a/crates/eframe/src/native/winit_integration.rs b/crates/eframe/src/native/winit_integration.rs index a7e4bb384b3..541253c0818 100644 --- a/crates/eframe/src/native/winit_integration.rs +++ b/crates/eframe/src/native/winit_integration.rs @@ -1,4 +1,4 @@ -use std::{rc::Rc, time::Instant}; +use std::{sync::Arc, time::Instant}; use winit::{ event_loop::EventLoopWindowTarget, @@ -68,7 +68,7 @@ pub trait WinitApp { fn integration(&self) -> Option<&EpiIntegration>; - fn window(&self, window_id: WindowId) -> Option>; + fn window(&self, window_id: WindowId) -> Option>; fn window_id_from_viewport_id(&self, id: ViewportId) -> Option; diff --git a/crates/egui-wgpu/src/winit.rs b/crates/egui-wgpu/src/winit.rs index 39d20ed6ab5..19940ff6f3b 100644 --- a/crates/egui-wgpu/src/winit.rs +++ b/crates/egui-wgpu/src/winit.rs @@ -187,82 +187,46 @@ impl Painter { /// # Errors /// If the provided wgpu configuration does not match an available device. pub async fn set_window( + &mut self, + viewport_id: ViewportId, + window: Option>, + ) -> Result<(), crate::WgpuError> { + crate::profile_scope!("Painter::set_window"); // profile_function gives bad names for async functions + + if let Some(window) = window { + let size = window.inner_size(); + if self.surfaces.get(&viewport_id).is_none() { + let surface = self.instance.create_surface(window)?; + self.add_surface(surface, viewport_id, size).await?; + } + } else { + log::warn!("No window - clearing all surfaces"); + self.surfaces.clear(); + } + Ok(()) + } + + /// Updates (or clears) the [`winit::window::Window`] associated with the [`Painter`] without taking ownership of the window. + /// + /// Like [`set_window`](Self::set_window) except: + /// + /// # Safety + /// The user is responsible for ensuring that the window is alive for as long as it is set. + pub async unsafe fn set_window_unsafe( &mut self, viewport_id: ViewportId, window: Option<&winit::window::Window>, ) -> Result<(), crate::WgpuError> { - crate::profile_scope!("Painter::set_window"); // profle_function gives bad names for async functions + crate::profile_scope!("Painter::set_window_unsafe"); // profile_function gives bad names for async functions if let Some(window) = window { let size = window.inner_size(); if self.surfaces.get(&viewport_id).is_none() { let surface = unsafe { - crate::profile_scope!("create_surface"); self.instance .create_surface_unsafe(wgpu::SurfaceTargetUnsafe::from_window(&window)?)? }; - - let render_state = if let Some(render_state) = &self.render_state { - render_state - } else { - let render_state = RenderState::create( - &self.configuration, - &self.instance, - &surface, - self.depth_format, - self.msaa_samples, - ) - .await?; - self.render_state.get_or_insert(render_state) - }; - - let alpha_mode = if self.support_transparent_backbuffer { - let supported_alpha_modes = - surface.get_capabilities(&render_state.adapter).alpha_modes; - - // Prefer pre multiplied over post multiplied! - if supported_alpha_modes.contains(&wgpu::CompositeAlphaMode::PreMultiplied) { - wgpu::CompositeAlphaMode::PreMultiplied - } else if supported_alpha_modes - .contains(&wgpu::CompositeAlphaMode::PostMultiplied) - { - wgpu::CompositeAlphaMode::PostMultiplied - } else { - log::warn!("Transparent window was requested, but the active wgpu surface does not support a `CompositeAlphaMode` with transparency."); - wgpu::CompositeAlphaMode::Auto - } - } else { - wgpu::CompositeAlphaMode::Auto - }; - - let supports_screenshot = - !matches!(render_state.adapter.get_info().backend, wgpu::Backend::Gl); - - self.surfaces.insert( - viewport_id, - SurfaceState { - surface, - width: size.width, - height: size.height, - alpha_mode, - supports_screenshot, - }, - ); - - let Some(width) = NonZeroU32::new(size.width) else { - log::debug!("The window width was zero; skipping generate textures"); - return Ok(()); - }; - let Some(height) = NonZeroU32::new(size.height) else { - log::debug!("The window height was zero; skipping generate textures"); - return Ok(()); - }; - - self.resize_and_generate_depth_texture_view_and_msaa_view( - viewport_id, - width, - height, - ); + self.add_surface(surface, viewport_id, size).await?; } } else { log::warn!("No window - clearing all surfaces"); @@ -271,6 +235,64 @@ impl Painter { Ok(()) } + async fn add_surface( + &mut self, + surface: wgpu::Surface<'static>, + viewport_id: ViewportId, + size: winit::dpi::PhysicalSize, + ) -> Result<(), crate::WgpuError> { + let render_state = if let Some(render_state) = &self.render_state { + render_state + } else { + let render_state = RenderState::create( + &self.configuration, + &self.instance, + &surface, + self.depth_format, + self.msaa_samples, + ) + .await?; + self.render_state.get_or_insert(render_state) + }; + let alpha_mode = if self.support_transparent_backbuffer { + let supported_alpha_modes = surface.get_capabilities(&render_state.adapter).alpha_modes; + + // Prefer pre multiplied over post multiplied! + if supported_alpha_modes.contains(&wgpu::CompositeAlphaMode::PreMultiplied) { + wgpu::CompositeAlphaMode::PreMultiplied + } else if supported_alpha_modes.contains(&wgpu::CompositeAlphaMode::PostMultiplied) { + wgpu::CompositeAlphaMode::PostMultiplied + } else { + log::warn!("Transparent window was requested, but the active wgpu surface does not support a `CompositeAlphaMode` with transparency."); + wgpu::CompositeAlphaMode::Auto + } + } else { + wgpu::CompositeAlphaMode::Auto + }; + let supports_screenshot = + !matches!(render_state.adapter.get_info().backend, wgpu::Backend::Gl); + self.surfaces.insert( + viewport_id, + SurfaceState { + surface, + width: size.width, + height: size.height, + alpha_mode, + supports_screenshot, + }, + ); + let Some(width) = NonZeroU32::new(size.width) else { + log::debug!("The window width was zero; skipping generate textures"); + return Ok(()); + }; + let Some(height) = NonZeroU32::new(size.height) else { + log::debug!("The window height was zero; skipping generate textures"); + return Ok(()); + }; + self.resize_and_generate_depth_texture_view_and_msaa_view(viewport_id, width, height); + Ok(()) + } + /// Returns the maximum texture dimension supported if known /// /// This API will only return a known dimension after `set_window()` has been called