Skip to content

Commit

Permalink
Improve Presentation Api (#2803)
Browse files Browse the repository at this point in the history
* Add new presentation modes

* Expand presentation formats

* Add Surface::get_supported_modes

* Update to rust 2021 and improve some metal surface code

* Update wgpu-types/src/lib.rs

Co-authored-by: bjorn3 <[email protected]>

* Fix windows build errors

* Fix issues with ALLOW_TEARING

Co-authored-by: bjorn3 <[email protected]>
  • Loading branch information
cwfitzgerald and bjorn3 authored Jun 30, 2022
1 parent 98597da commit ea05b44
Show file tree
Hide file tree
Showing 26 changed files with 277 additions and 80 deletions.
2 changes: 1 addition & 1 deletion cts_runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.1.0"
authors = [
"Luca Casonato <[email protected]>",
]
edition = "2018"
edition = "2021"
description = "CTS runner for wgpu"
license = "MIT OR Apache-2.0"
publish = false
Expand Down
2 changes: 1 addition & 1 deletion deno_webgpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
name = "deno_webgpu"
version = "0.54.0"
authors = ["the Deno authors"]
edition = "2018"
edition = "2021"
license = "MIT"
readme = "README.md"
repository = "https://github.com/gfx-rs/wgpu"
Expand Down
2 changes: 1 addition & 1 deletion dummy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.1.0"
authors = [
"Dzmitry Malyshau <[email protected]>",
]
edition = "2018"
edition = "2021"
license = "MIT OR Apache-2.0"
publish = false

Expand Down
2 changes: 1 addition & 1 deletion player/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.1.0"
authors = [
"Dzmitry Malyshau <[email protected]>",
]
edition = "2018"
edition = "2021"
description = "WebGPU trace player"
homepage = "https://github.com/gfx-rs/wgpu"
repository = "https://github.com/gfx-rs/wgpu"
Expand Down
2 changes: 1 addition & 1 deletion run-wasm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "run-wasm"
version = "0.1.0"
edition = "2018"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Expand Down
2 changes: 1 addition & 1 deletion wgpu-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "wgpu-core"
version = "0.12.0"
authors = ["wgpu developers"]
edition = "2018"
edition = "2021"
description = "WebGPU core logic on wgpu-hal"
homepage = "https://github.com/gfx-rs/wgpu"
repository = "https://github.com/gfx-rs/wgpu"
Expand Down
63 changes: 56 additions & 7 deletions wgpu-core/src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3134,7 +3134,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self,
surface_id: id::SurfaceId,
adapter_id: id::AdapterId,
) -> Result<Vec<TextureFormat>, instance::GetSurfacePreferredFormatError> {
) -> Result<Vec<TextureFormat>, instance::GetSurfaceSupportError> {
profiling::scope!("Surface::get_supported_formats");
let hub = A::hub(self);
let mut token = Token::root();
Expand All @@ -3143,13 +3143,33 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let (adapter_guard, mut _token) = hub.adapters.read(&mut token);
let adapter = adapter_guard
.get(adapter_id)
.map_err(|_| instance::GetSurfacePreferredFormatError::InvalidAdapter)?;
.map_err(|_| instance::GetSurfaceSupportError::InvalidAdapter)?;
let surface = surface_guard
.get(surface_id)
.map_err(|_| instance::GetSurfacePreferredFormatError::InvalidSurface)?;
.map_err(|_| instance::GetSurfaceSupportError::InvalidSurface)?;

surface.get_supported_formats(adapter)
}
pub fn surface_get_supported_modes<A: HalApi>(
&self,
surface_id: id::SurfaceId,
adapter_id: id::AdapterId,
) -> Result<Vec<wgt::PresentMode>, instance::GetSurfaceSupportError> {
profiling::scope!("Surface::get_supported_modes");
let hub = A::hub(self);
let mut token = Token::root();

let (surface_guard, mut token) = self.surfaces.read(&mut token);
let (adapter_guard, mut _token) = hub.adapters.read(&mut token);
let adapter = adapter_guard
.get(adapter_id)
.map_err(|_| instance::GetSurfaceSupportError::InvalidAdapter)?;
let surface = surface_guard
.get(surface_id)
.map_err(|_| instance::GetSurfaceSupportError::InvalidSurface)?;

surface.get_supported_modes(adapter)
}

pub fn device_features<A: HalApi>(
&self,
Expand Down Expand Up @@ -4955,11 +4975,40 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
);
}
if !caps.present_modes.contains(&config.present_mode) {
log::warn!(
"Surface does not support present mode: {:?}, falling back to FIFO",
config.present_mode,
let new_mode = loop {
// Automatic present mode checks.
//
// The "Automatic" modes are never supported by the backends.
match config.present_mode {
wgt::PresentMode::AutoVsync => {
if caps.present_modes.contains(&wgt::PresentMode::FifoRelaxed) {
break wgt::PresentMode::FifoRelaxed;
}
if caps.present_modes.contains(&wgt::PresentMode::Fifo) {
break wgt::PresentMode::Fifo;
}
}
wgt::PresentMode::AutoNoVsync => {
if caps.present_modes.contains(&wgt::PresentMode::Immediate) {
break wgt::PresentMode::Immediate;
}
if caps.present_modes.contains(&wgt::PresentMode::Mailbox) {
break wgt::PresentMode::Mailbox;
}
}
_ => {}
}
return Err(E::UnsupportedPresentMode {
requested: config.present_mode,
available: caps.present_modes.clone(),
});
};

log::info!(
"Automatically choosing presentation mode by rule {:?}. Chose {new_mode:?}",
config.present_mode
);
config.present_mode = wgt::PresentMode::Fifo;
config.present_mode = new_mode;
}
if !caps.formats.contains(&config.format) {
return Err(E::UnsupportedFormat {
Expand Down
23 changes: 20 additions & 3 deletions wgpu-core/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,22 +155,39 @@ impl Surface {
pub fn get_supported_formats<A: HalApi>(
&self,
adapter: &Adapter<A>,
) -> Result<Vec<wgt::TextureFormat>, GetSurfacePreferredFormatError> {
) -> Result<Vec<wgt::TextureFormat>, GetSurfaceSupportError> {
let suf = A::get_surface(self);
let mut caps = unsafe {
profiling::scope!("surface_capabilities");
adapter
.raw
.adapter
.surface_capabilities(&suf.raw)
.ok_or(GetSurfacePreferredFormatError::UnsupportedQueueFamily)?
.ok_or(GetSurfaceSupportError::UnsupportedQueueFamily)?
};

// TODO: maybe remove once we support texture view changing srgb-ness
caps.formats.sort_by_key(|f| !f.describe().srgb);

Ok(caps.formats)
}

pub fn get_supported_modes<A: HalApi>(
&self,
adapter: &Adapter<A>,
) -> Result<Vec<wgt::PresentMode>, GetSurfaceSupportError> {
let suf = A::get_surface(self);
let caps = unsafe {
profiling::scope!("surface_capabilities");
adapter
.raw
.adapter
.surface_capabilities(&suf.raw)
.ok_or(GetSurfaceSupportError::UnsupportedQueueFamily)?
};

Ok(caps.present_modes)
}
}

pub struct Adapter<A: hal::Api> {
Expand Down Expand Up @@ -341,7 +358,7 @@ pub enum IsSurfaceSupportedError {
}

#[derive(Clone, Debug, Error)]
pub enum GetSurfacePreferredFormatError {
pub enum GetSurfaceSupportError {
#[error("invalid adapter")]
InvalidAdapter,
#[error("invalid surface")]
Expand Down
5 changes: 5 additions & 0 deletions wgpu-core/src/present.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ pub enum ConfigureSurfaceError {
requested: wgt::TextureFormat,
available: Vec<wgt::TextureFormat>,
},
#[error("requested present mode {requested:?} is not in the list of supported present modes: {available:?}")]
UnsupportedPresentMode {
requested: wgt::PresentMode,
available: Vec<wgt::PresentMode>,
},
#[error("requested usage is not supported")]
UnsupportedUsage,
}
Expand Down
2 changes: 1 addition & 1 deletion wgpu-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "wgpu-hal"
version = "0.12.0"
authors = ["wgpu developers"]
edition = "2018"
edition = "2021"
description = "WebGPU hardware abstraction layer"
homepage = "https://github.com/gfx-rs/wgpu"
repository = "https://github.com/gfx-rs/wgpu"
Expand Down
19 changes: 4 additions & 15 deletions wgpu-hal/src/dx12/adapter.rs
Original file line number Diff line number Diff line change
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,20 +426,9 @@ impl crate::Adapter<super::Api> for super::Adapter {
}
};

let mut present_modes = vec![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),
}
let mut present_modes = vec![wgt::PresentMode::Mailbox, wgt::PresentMode::Fifo];
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
Original file line number Diff line number Diff line change
@@ -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
17 changes: 11 additions & 6 deletions wgpu-hal/src/dx12/mod.rs
Original file line number Diff line number Diff line change
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 @@ -556,11 +559,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 @@ -771,9 +774,11 @@ 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),
wgt::PresentMode::Mailbox => (1, 0),
m => unreachable!("Cannot make surface with present mode {m:?}"),
};

profiling::scope!("IDXGISwapchain3::Present");
Expand Down
16 changes: 11 additions & 5 deletions wgpu-hal/src/metal/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,13 +281,18 @@ impl crate::Adapter<super::Api> for super::Adapter {
None
};

let mut formats = vec![
wgt::TextureFormat::Bgra8Unorm,
wgt::TextureFormat::Bgra8UnormSrgb,
wgt::TextureFormat::Rgba16Float,
];
if self.shared.private_caps.format_rgb10a2_unorm_surface {
formats.push(wgt::TextureFormat::Rgb10a2Unorm);
}

let pc = &self.shared.private_caps;
Some(crate::SurfaceCapabilities {
formats: vec![
wgt::TextureFormat::Bgra8Unorm,
wgt::TextureFormat::Bgra8UnormSrgb,
wgt::TextureFormat::Rgba16Float,
],
formats,
//Note: this is hardcoded in `CAMetalLayer` documentation
swap_chain_sizes: if pc.can_set_maximum_drawables_count {
2..=3
Expand Down Expand Up @@ -575,6 +580,7 @@ impl super::PrivateCapabilities {
format_rgba8_srgb_no_write: !Self::supports_any(device, RGBA8_SRGB),
format_rgb10a2_unorm_all: Self::supports_any(device, RGB10A2UNORM_ALL),
format_rgb10a2_unorm_no_write: !Self::supports_any(device, RGB10A2UNORM_ALL),
format_rgb10a2_unorm_surface: os_is_mac,
format_rgb10a2_uint_color: !Self::supports_any(device, RGB10A2UINT_COLOR_WRITE),
format_rgb10a2_uint_color_write: Self::supports_any(device, RGB10A2UINT_COLOR_WRITE),
format_rg11b10_all: Self::supports_any(device, RG11B10FLOAT_ALL),
Expand Down
1 change: 1 addition & 0 deletions wgpu-hal/src/metal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ struct PrivateCapabilities {
format_rgba8_srgb_no_write: bool,
format_rgb10a2_unorm_all: bool,
format_rgb10a2_unorm_no_write: bool,
format_rgb10a2_unorm_surface: bool,
format_rgb10a2_uint_color: bool,
format_rgb10a2_uint_color_write: bool,
format_rg11b10_all: bool,
Expand Down
Loading

0 comments on commit ea05b44

Please sign in to comment.