Skip to content

Commit

Permalink
Fix issues with ALLOW_TEARING
Browse files Browse the repository at this point in the history
  • Loading branch information
cwfitzgerald committed Jun 25, 2022
1 parent f49e4e3 commit 24c2921
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 21 deletions.
17 changes: 3 additions & 14 deletions wgpu-hal/src/dx12/adapter.rs
Expand Up @@ -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},
};

Expand Down Expand Up @@ -426,19 +426,8 @@ impl crate::Adapter<super::Api> 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::<minwindef::BOOL>() 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 {
Expand Down
22 changes: 21 additions & 1 deletion 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) {
Expand Down Expand Up @@ -37,11 +39,28 @@ impl crate::Instance<super::Api> 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::<minwindef::BOOL>() 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,
})
}
Expand All @@ -54,6 +73,7 @@ impl crate::Instance<super::Api> 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),
Expand Down
14 changes: 9 additions & 5 deletions wgpu-hal/src/dx12/mod.rs
Expand Up @@ -88,6 +88,7 @@ const ZERO_BUFFER_SIZE: wgt::BufferAddress = 256 << 10;
pub struct Instance {
factory: native::DxgiFactory,
library: Arc<native::D3D12Lib>,
supports_allow_tearing: bool,
_lib_dxgi: native::DxgiLib,
flags: crate::InstanceFlags,
}
Expand All @@ -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,
}
}
Expand Down Expand Up @@ -128,6 +130,7 @@ enum SurfaceTarget {
pub struct Surface {
factory: native::DxgiFactory,
target: SurfaceTarget,
supports_allow_tearing: bool,
swap_chain: Option<SwapChain>,
}

Expand Down Expand Up @@ -554,11 +557,11 @@ impl crate::Surface<Api> 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);
Expand Down Expand Up @@ -769,6 +772,7 @@ impl crate::Queue<Api> 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),
Expand Down
3 changes: 2 additions & 1 deletion wgpu/examples/framework.rs
Expand Up @@ -272,7 +272,7 @@ fn start<E: Example>(
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);

Expand Down Expand Up @@ -311,6 +311,7 @@ fn start<E: Example>(
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);
}
Expand Down

0 comments on commit 24c2921

Please sign in to comment.