From 24c292188aae30690c3688c0480667613f2a74c5 Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Sat, 25 Jun 2022 19:38:14 -0400 Subject: [PATCH] Fix issues with ALLOW_TEARING --- wgpu-hal/src/dx12/adapter.rs | 17 +++-------------- wgpu-hal/src/dx12/instance.rs | 22 +++++++++++++++++++++- wgpu-hal/src/dx12/mod.rs | 14 +++++++++----- wgpu/examples/framework.rs | 3 ++- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index f994aaf2a1..2dc23fd6d1 100644 --- a/wgpu-hal/src/dx12/adapter.rs +++ b/wgpu-hal/src/dx12/adapter.rs @@ -4,7 +4,7 @@ use crate::{ }; use std::{mem, sync::Arc, thread}; use winapi::{ - shared::{dxgi, dxgi1_2, dxgi1_5, minwindef, windef, winerror}, + shared::{dxgi, dxgi1_2, windef, winerror}, um::{d3d12, d3d12sdklayers, winuser}, }; @@ -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_modes.push(wgt::PresentMode::Immediate); } Some(crate::SurfaceCapabilities { diff --git a/wgpu-hal/src/dx12/instance.rs b/wgpu-hal/src/dx12/instance.rs index 6129d53a71..2f115a6a62 100644 --- a/wgpu-hal/src/dx12/instance.rs +++ b/wgpu-hal/src/dx12/instance.rs @@ -1,6 +1,8 @@ +use winapi::shared::{dxgi1_5, minwindef}; + use super::SurfaceTarget; use crate::auxil::{self, dxgi::result::HResult as _}; -use std::sync::Arc; +use std::{mem, sync::Arc}; impl Drop for super::Instance { fn drop(&mut self) { @@ -37,11 +39,28 @@ impl crate::Instance for super::Instance { desc.flags, )?; + let mut supports_allow_tearing = false; + #[allow(trivial_casts)] + if let Some(factory5) = 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, + } + } + Ok(Self { // The call to create_factory will only succeed if we get a factory4, so this is safe. factory, library: Arc::new(lib_main), _lib_dxgi: lib_dxgi, + supports_allow_tearing, flags: desc.flags, }) } @@ -54,6 +73,7 @@ impl crate::Instance for super::Instance { raw_window_handle::RawWindowHandle::Win32(handle) => Ok(super::Surface { factory: self.factory, target: SurfaceTarget::WndHandle(handle.hwnd as *mut _), + supports_allow_tearing: self.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 44062ee0c7..65b64ff80d 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -88,6 +88,7 @@ const ZERO_BUFFER_SIZE: wgt::BufferAddress = 256 << 10; pub struct Instance { factory: native::DxgiFactory, library: Arc, + supports_allow_tearing: bool, _lib_dxgi: native::DxgiLib, flags: crate::InstanceFlags, } @@ -100,6 +101,7 @@ impl Instance { Surface { factory: self.factory, target: SurfaceTarget::Visual(native::WeakPtr::from_raw(visual)), + supports_allow_tearing: self.supports_allow_tearing, swap_chain: None, } } @@ -128,6 +130,7 @@ enum SurfaceTarget { pub struct Surface { factory: native::DxgiFactory, target: SurfaceTarget, + supports_allow_tearing: bool, swap_chain: Option, } @@ -554,11 +557,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 +772,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), diff --git a/wgpu/examples/framework.rs b/wgpu/examples/framework.rs index 0d8ed6df4b..31df10da04 100644 --- a/wgpu/examples/framework.rs +++ b/wgpu/examples/framework.rs @@ -272,7 +272,7 @@ fn start( format: surface.get_supported_formats(&adapter)[0], width: size.width, height: size.height, - present_mode: wgpu::PresentMode::Fifo, + present_mode: wgpu::PresentMode::Mailbox, }; surface.configure(&device, &config); @@ -311,6 +311,7 @@ fn start( log::info!("Resizing to {:?}", size); config.width = size.width.max(1); config.height = size.height.max(1); + config.present_mode = wgpu::PresentMode::Immediate; example.resize(&config, &device, &queue); surface.configure(&device, &config); }