diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index f994aaf2a11..4c840f6caec 100644 --- a/wgpu-hal/src/dx12/adapter.rs +++ b/wgpu-hal/src/dx12/adapter.rs @@ -426,19 +426,8 @@ impl crate::Adapter for super::Adapter { }; let mut present_modes = vec![wgt::PresentMode::Mailbox, wgt::PresentMode::Fifo]; - #[allow(trivial_casts)] - if let Some(factory5) = surface.factory.as_factory5() { - let mut allow_tearing: minwindef::BOOL = minwindef::FALSE; - let hr = factory5.CheckFeatureSupport( - dxgi1_5::DXGI_FEATURE_PRESENT_ALLOW_TEARING, - &mut allow_tearing as *mut _ as *mut _, - mem::size_of::() as _, - ); - - match hr.into_result() { - Err(err) => log::warn!("Unable to check for tearing support: {}", err), - Ok(()) => present_modes.push(wgt::PresentMode::Immediate), - } + if surface.supports_allow_tearing { + present_mode.push(wgt::PresentMode::Immediate); } Some(crate::SurfaceCapabilities { diff --git a/wgpu-hal/src/dx12/instance.rs b/wgpu-hal/src/dx12/instance.rs index 6129d53a717..4066d095f43 100644 --- a/wgpu-hal/src/dx12/instance.rs +++ b/wgpu-hal/src/dx12/instance.rs @@ -50,10 +50,27 @@ impl crate::Instance for super::Instance { &self, has_handle: &impl raw_window_handle::HasRawWindowHandle, ) -> Result { + let mut supports_allow_tearing = false; + #[allow(trivial_casts)] + if let Some(factory5) = self.factory.as_factory5() { + let mut allow_tearing: minwindef::BOOL = minwindef::FALSE; + let hr = factory5.CheckFeatureSupport( + dxgi1_5::DXGI_FEATURE_PRESENT_ALLOW_TEARING, + &mut allow_tearing as *mut _ as *mut _, + mem::size_of::() as _, + ); + + match hr.into_result() { + Err(err) => log::warn!("Unable to check for tearing support: {}", err), + Ok(()) => supports_allow_tearing = true, + } + } + match has_handle.raw_window_handle() { raw_window_handle::RawWindowHandle::Win32(handle) => Ok(super::Surface { factory: self.factory, target: SurfaceTarget::WndHandle(handle.hwnd as *mut _), + supports_allow_tearing, swap_chain: None, }), _ => Err(crate::InstanceError), diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index 44062ee0c7c..78f8bb4049f 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -128,6 +128,7 @@ enum SurfaceTarget { pub struct Surface { factory: native::DxgiFactory, target: SurfaceTarget, + supports_allow_tearing: bool, swap_chain: Option, } @@ -554,11 +555,11 @@ impl crate::Surface for Surface { config: &crate::SurfaceConfiguration, ) -> Result<(), crate::SurfaceError> { let mut flags = dxgi::DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; - match config.present_mode { - wgt::PresentMode::Immediate => { - flags |= dxgi::DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; - } - _ => {} + // We always set ALLOW_TEARING on the swapchain no matter + // what kind of swapchain we want because ResizeBuffers + // cannot change if ALLOW_TEARING is applied to the swapchain. + if self.supports_allow_tearing { + flags |= dxgi::DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; } let non_srgb_format = auxil::dxgi::conv::map_texture_format_nosrgb(config.format); @@ -769,6 +770,7 @@ impl crate::Queue for Queue { sc.acquired_count -= 1; let (interval, flags) = match sc.present_mode { + // We only allow immediate if ALLOW_TEARING is valid. wgt::PresentMode::Immediate => (0, dxgi::DXGI_PRESENT_ALLOW_TEARING), wgt::PresentMode::Mailbox => (0, 0), wgt::PresentMode::Fifo => (1, 0),