mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-21 22:33:49 +00:00
Improve Presentation Api (#2803)
* 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 <17426603+bjorn3@users.noreply.github.com> * Fix windows build errors * Fix issues with ALLOW_TEARING Co-authored-by: bjorn3 <17426603+bjorn3@users.noreply.github.com>
This commit is contained in:
parent
98597da1ec
commit
ea05b44f38
@ -4,7 +4,7 @@ version = "0.1.0"
|
||||
authors = [
|
||||
"Luca Casonato <hello@lcas.dev>",
|
||||
]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
description = "CTS runner for wgpu"
|
||||
license = "MIT OR Apache-2.0"
|
||||
publish = false
|
||||
|
@ -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"
|
||||
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
||||
authors = [
|
||||
"Dzmitry Malyshau <kvark@mozilla.com>",
|
||||
]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
publish = false
|
||||
|
||||
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
||||
authors = [
|
||||
"Dzmitry Malyshau <kvark@mozilla.com>",
|
||||
]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
description = "WebGPU trace player"
|
||||
homepage = "https://github.com/gfx-rs/wgpu"
|
||||
repository = "https://github.com/gfx-rs/wgpu"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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();
|
||||
@ -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,
|
||||
@ -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 {
|
||||
|
@ -155,7 +155,7 @@ 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");
|
||||
@ -163,7 +163,7 @@ impl Surface {
|
||||
.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
|
||||
@ -171,6 +171,23 @@ impl Surface {
|
||||
|
||||
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> {
|
||||
@ -341,7 +358,7 @@ pub enum IsSurfaceSupportedError {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
pub enum GetSurfacePreferredFormatError {
|
||||
pub enum GetSurfaceSupportError {
|
||||
#[error("invalid adapter")]
|
||||
InvalidAdapter,
|
||||
#[error("invalid surface")]
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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,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 {
|
||||
|
@ -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<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,
|
||||
})
|
||||
}
|
||||
@ -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),
|
||||
|
@ -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,
|
||||
}
|
||||
@ -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<SwapChain>,
|
||||
}
|
||||
|
||||
@ -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);
|
||||
@ -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");
|
||||
|
@ -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
|
||||
@ -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),
|
||||
|
@ -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,
|
||||
|
@ -170,7 +170,11 @@ impl crate::Surface<super::Api> for super::Surface {
|
||||
|
||||
let render_layer = self.render_layer.lock();
|
||||
let framebuffer_only = config.usage == crate::TextureUses::COLOR_TARGET;
|
||||
let display_sync = config.present_mode != wgt::PresentMode::Immediate;
|
||||
let display_sync = match config.present_mode {
|
||||
wgt::PresentMode::Fifo => true,
|
||||
wgt::PresentMode::Immediate => false,
|
||||
m => unreachable!("Unsupported present mode: {m:?}"),
|
||||
};
|
||||
let drawable_size = CGSize::new(config.extent.width as f64, config.extent.height as f64);
|
||||
|
||||
match config.composite_alpha_mode {
|
||||
|
@ -1613,22 +1613,9 @@ impl crate::Adapter<super::Api> for super::Adapter {
|
||||
}
|
||||
};
|
||||
|
||||
let supported_formats = [
|
||||
wgt::TextureFormat::Rgba8Unorm,
|
||||
wgt::TextureFormat::Rgba8UnormSrgb,
|
||||
wgt::TextureFormat::Bgra8Unorm,
|
||||
wgt::TextureFormat::Bgra8UnormSrgb,
|
||||
wgt::TextureFormat::Rgba16Float,
|
||||
];
|
||||
let formats = supported_formats
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter(|&format| {
|
||||
let vk_format = self.private_caps.map_texture_format(format);
|
||||
raw_surface_formats
|
||||
.iter()
|
||||
.any(|sf| sf.format == vk_format || sf.format == vk::Format::UNDEFINED)
|
||||
})
|
||||
let formats = raw_surface_formats
|
||||
.into_iter()
|
||||
.filter_map(conv::map_vk_surface_formats)
|
||||
.collect();
|
||||
Some(crate::SurfaceCapabilities {
|
||||
formats,
|
||||
|
@ -144,6 +144,24 @@ impl super::PrivateCapabilities {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_vk_surface_formats(sf: vk::SurfaceFormatKHR) -> Option<wgt::TextureFormat> {
|
||||
use ash::vk::Format as F;
|
||||
use wgt::TextureFormat as Tf;
|
||||
// List we care about pulled from https://vulkan.gpuinfo.org/listsurfaceformats.php
|
||||
Some(match sf.format {
|
||||
F::B8G8R8A8_UNORM => Tf::Bgra8Unorm,
|
||||
F::B8G8R8A8_SRGB => Tf::Bgra8UnormSrgb,
|
||||
F::R8G8B8A8_SNORM => Tf::Rgba8Snorm,
|
||||
F::R8G8B8A8_UNORM => Tf::Rgba8Unorm,
|
||||
F::R8G8B8A8_SRGB => Tf::Rgba8UnormSrgb,
|
||||
F::R16G16B16A16_SFLOAT => Tf::Rgba16Float,
|
||||
F::R16G16B16A16_SNORM => Tf::Rgba16Snorm,
|
||||
F::R16G16B16A16_UNORM => Tf::Rgba16Unorm,
|
||||
F::A2B10G10R10_UNORM_PACK32 => Tf::Rgb10a2Unorm,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
impl crate::Attachment<'_, super::Api> {
|
||||
pub(super) fn make_attachment_key(
|
||||
&self,
|
||||
@ -405,7 +423,10 @@ pub fn map_present_mode(mode: wgt::PresentMode) -> vk::PresentModeKHR {
|
||||
wgt::PresentMode::Immediate => vk::PresentModeKHR::IMMEDIATE,
|
||||
wgt::PresentMode::Mailbox => vk::PresentModeKHR::MAILBOX,
|
||||
wgt::PresentMode::Fifo => vk::PresentModeKHR::FIFO,
|
||||
//wgt::PresentMode::Relaxed => vk::PresentModeKHR::FIFO_RELAXED,
|
||||
wgt::PresentMode::FifoRelaxed => vk::PresentModeKHR::FIFO_RELAXED,
|
||||
wgt::PresentMode::AutoNoVsync | wgt::PresentMode::AutoVsync => {
|
||||
unreachable!("Cannot create swapchain with Auto PresentationMode")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
name = "wgpu-info"
|
||||
version = "0.12.0"
|
||||
authors = ["wgpu developers"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
description = "Adapter information and per-adapter test program"
|
||||
homepage = "https://github.com/gfx-rs/wgpu"
|
||||
repository = "https://github.com/gfx-rs/wgpu"
|
||||
|
@ -2,7 +2,7 @@
|
||||
name = "wgpu-types"
|
||||
version = "0.12.0"
|
||||
authors = ["wgpu developers"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
description = "WebGPU types"
|
||||
homepage = "https://github.com/gfx-rs/wgpu"
|
||||
repository = "https://github.com/gfx-rs/wgpu"
|
||||
|
@ -2949,20 +2949,75 @@ impl<T> Default for CommandEncoderDescriptor<Option<T>> {
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub enum PresentMode {
|
||||
/// The presentation engine does **not** wait for a vertical blanking period and
|
||||
/// the request is presented immediately. This is a low-latency presentation mode,
|
||||
/// but visible tearing may be observed. Will fallback to `Fifo` if unavailable on the
|
||||
/// selected platform and backend. Not optimal for mobile.
|
||||
Immediate = 0,
|
||||
/// The presentation engine waits for the next vertical blanking period to update
|
||||
/// the current image, but frames may be submitted without delay. This is a low-latency
|
||||
/// presentation mode and visible tearing will **not** be observed. Will fallback to `Fifo`
|
||||
/// if unavailable on the selected platform and backend. Not optimal for mobile.
|
||||
Mailbox = 1,
|
||||
/// The presentation engine waits for the next vertical blanking period to update
|
||||
/// the current image. The framerate will be capped at the display refresh rate,
|
||||
/// corresponding to the `VSync`. Tearing cannot be observed. Optimal for mobile.
|
||||
/// Chooses FifoRelaxed -> Fifo based on availability.
|
||||
///
|
||||
/// Because of the fallback behavior, it is supported everywhere.
|
||||
AutoVsync = 0,
|
||||
/// Chooses Immediate -> Mailbox -> Fifo (on web) based on availability.
|
||||
///
|
||||
/// Because of the fallback behavior, it is supported everywhere.
|
||||
AutoNoVsync = 1,
|
||||
/// Presentation frames are kept in a First-In-First-Out queue approximately 3 frames
|
||||
/// long. Every vertical blanking period, the presentation engine will pop a frame
|
||||
/// off the queue to display. If there is no frame to display, it will present the same
|
||||
/// frame again until the next vblank.
|
||||
///
|
||||
/// When a present command is executed on the gpu, the presented image is added on the queue.
|
||||
///
|
||||
/// No tearing will be observed.
|
||||
///
|
||||
/// Calls to get_current_texture will block until there is a spot in the queue.
|
||||
///
|
||||
/// Supported on all platforms.
|
||||
///
|
||||
/// If you don't know what mode to choose, choose this mode. This is traditionally called "Vsync On".
|
||||
Fifo = 2,
|
||||
/// Presentation frames are kept in a First-In-First-Out queue approximately 3 frames
|
||||
/// long. Every vertical blanking period, the presentation engine will pop a frame
|
||||
/// off the queue to display. If there is no frame to display, it will present the
|
||||
/// same frame until there is a frame in the queue. The moment there is a frame in the
|
||||
/// queue, it will immediately pop the frame off the queue.
|
||||
///
|
||||
/// When a present command is executed on the gpu, the presented image is added on the queue.
|
||||
///
|
||||
/// Tearing will be observed if frames last more than one vblank as the front buffer.
|
||||
///
|
||||
/// Calls to get_current_texture will block until there is a spot in the queue.
|
||||
///
|
||||
/// Supported on AMD on Vulkan.
|
||||
///
|
||||
/// This is traditionally called "Adaptive Vsync"
|
||||
FifoRelaxed = 3,
|
||||
/// Presentation frames are not queued at all. The moment a present command
|
||||
/// is executed on the GPU, the presented image is swapped onto the front buffer
|
||||
/// immediately.
|
||||
///
|
||||
/// Tearing can be observed.
|
||||
///
|
||||
/// Supported on most platforms except older DX12.
|
||||
///
|
||||
/// This is traditionally called "Vsync Off".
|
||||
Immediate = 4,
|
||||
/// Presentation frames are kept in a single-frame queue. Every vertical blanking period,
|
||||
/// the presentation engine will pop a frame from the queue. If there is no frame to display,
|
||||
/// it will present the same frame again until the next vblank.
|
||||
///
|
||||
/// When a present command is executed on the gpu, the frame will be put into the queue.
|
||||
/// If there was already a frame in the queue, the new frame will _replace_ the old frame
|
||||
/// on the queue.
|
||||
///
|
||||
/// No tearing will be observed.
|
||||
///
|
||||
/// Supported on DX11/12 on Windows 10, and NVidia on Vulkan.
|
||||
///
|
||||
/// This is traditionally called "Fast Vsync"
|
||||
Mailbox = 5,
|
||||
}
|
||||
|
||||
impl Default for PresentMode {
|
||||
fn default() -> Self {
|
||||
Self::Fifo
|
||||
}
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
|
@ -2,7 +2,7 @@
|
||||
name = "wgpu"
|
||||
version = "0.12.0"
|
||||
authors = ["wgpu developers"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
description = "Rusty WebGPU API wrapper"
|
||||
homepage = "https://wgpu.rs/"
|
||||
repository = "https://github.com/gfx-rs/wgpu/tree/v0.12"
|
||||
|
@ -72,7 +72,7 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
|
||||
format: swapchain_format,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
present_mode: wgpu::PresentMode::Mailbox,
|
||||
present_mode: wgpu::PresentMode::Fifo,
|
||||
};
|
||||
|
||||
surface.configure(&device, &config);
|
||||
|
@ -20,6 +20,7 @@ use std::{
|
||||
slice,
|
||||
sync::Arc,
|
||||
};
|
||||
use wgt::PresentMode;
|
||||
|
||||
const LABEL: &str = "label";
|
||||
|
||||
@ -972,7 +973,21 @@ impl crate::Context for Context {
|
||||
match wgc::gfx_select!(adapter => global.surface_get_supported_formats(surface.id, *adapter))
|
||||
{
|
||||
Ok(formats) => formats,
|
||||
Err(wgc::instance::GetSurfacePreferredFormatError::UnsupportedQueueFamily) => vec![],
|
||||
Err(wgc::instance::GetSurfaceSupportError::UnsupportedQueueFamily) => vec![],
|
||||
Err(err) => self.handle_error_fatal(err, "Surface::get_supported_formats"),
|
||||
}
|
||||
}
|
||||
|
||||
fn surface_get_supported_modes(
|
||||
&self,
|
||||
surface: &Self::SurfaceId,
|
||||
adapter: &Self::AdapterId,
|
||||
) -> Vec<PresentMode> {
|
||||
let global = &self.0;
|
||||
match wgc::gfx_select!(adapter => global.surface_get_supported_modes(surface.id, *adapter))
|
||||
{
|
||||
Ok(modes) => modes,
|
||||
Err(wgc::instance::GetSurfaceSupportError::UnsupportedQueueFamily) => vec![],
|
||||
Err(err) => self.handle_error_fatal(err, "Surface::get_supported_formats"),
|
||||
}
|
||||
}
|
||||
|
@ -1207,12 +1207,23 @@ impl crate::Context for Context {
|
||||
]
|
||||
}
|
||||
|
||||
fn surface_get_supported_modes(
|
||||
&self,
|
||||
_surface: &Self::SurfaceId,
|
||||
_adapter: &Self::AdapterId,
|
||||
) -> Vec<wgt::PresentMode> {
|
||||
vec![wgt::PresentMode::Fifo]
|
||||
}
|
||||
|
||||
fn surface_configure(
|
||||
&self,
|
||||
surface: &Self::SurfaceId,
|
||||
device: &Self::DeviceId,
|
||||
config: &wgt::SurfaceConfiguration,
|
||||
) {
|
||||
if let wgt::PresentMode::Mailbox | wgt::PresentMode::Immediate = config.present_mode {
|
||||
panic!("Only FIFO/Auto* is supported on web");
|
||||
}
|
||||
let mut mapped =
|
||||
web_sys::GpuCanvasConfiguration::new(&device.0, map_texture_format(config.format));
|
||||
mapped.usage(config.usage.bits());
|
||||
|
@ -230,6 +230,11 @@ trait Context: Debug + Send + Sized + Sync {
|
||||
surface: &Self::SurfaceId,
|
||||
adapter: &Self::AdapterId,
|
||||
) -> Vec<TextureFormat>;
|
||||
fn surface_get_supported_modes(
|
||||
&self,
|
||||
surface: &Self::SurfaceId,
|
||||
adapter: &Self::AdapterId,
|
||||
) -> Vec<PresentMode>;
|
||||
fn surface_configure(
|
||||
&self,
|
||||
surface: &Self::SurfaceId,
|
||||
@ -3554,6 +3559,13 @@ impl Surface {
|
||||
Context::surface_get_supported_formats(&*self.context, &self.id, &adapter.id)
|
||||
}
|
||||
|
||||
/// Returns a vec of supported presentation modes to use for the [`Surface`] with this adapter.
|
||||
///
|
||||
/// Returns an empty vector if the surface is incompatible with the adapter.
|
||||
pub fn get_supported_modes(&self, adapter: &Adapter) -> Vec<PresentMode> {
|
||||
Context::surface_get_supported_modes(&*self.context, &self.id, &adapter.id)
|
||||
}
|
||||
|
||||
/// Initializes [`Surface`] for presentation.
|
||||
///
|
||||
/// # Panics
|
||||
|
Loading…
Reference in New Issue
Block a user