diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index ad5f72f878..6ff7349405 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -8,7 +8,7 @@ use crate::{ hub::{ GfxBackend, Global, GlobalIdentityHandlerFactory, Hub, Input, InvalidId, Storage, Token, }, - id, pipeline, resource, span, swap_chain, + id, instance, pipeline, resource, span, swap_chain, track::{BufferState, TextureSelector, TextureState, TrackerSet}, validation::{self, check_buffer_usage, check_texture_usage}, FastHashMap, FastHashSet, Label, LabelHelpers, LifeGuard, MultiRefCount, PrivateFeatures, @@ -2379,6 +2379,28 @@ pub struct ImplicitPipelineIds<'a, G: GlobalIdentityHandlerFactory> { } impl Global { + pub fn adapter_get_swap_chain_preferred_format( + &self, + adapter_id: id::AdapterId, + surface_id: id::SurfaceId, + ) -> Result { + span!(_guard, INFO, "Adapter::get_swap_chain_preferred_format"); + + let hub = B::hub(self); + let mut token = Token::root(); + + let (mut surface_guard, mut token) = self.surfaces.write(&mut token); + let (adapter_guard, mut _token) = hub.adapters.read(&mut token); + let adapter = adapter_guard + .get(adapter_id) + .map_err(|_| instance::GetSwapChainPreferredFormatError::InvalidAdapter)?; + let surface = surface_guard + .get_mut(surface_id) + .map_err(|_| instance::GetSwapChainPreferredFormatError::InvalidSurface)?; + + adapter.get_swap_chain_preferred_format(surface) + } + pub fn device_features( &self, device_id: id::DeviceId, @@ -3885,17 +3907,6 @@ impl Global { .push(layout_id); } - pub fn device_get_swap_chain_preferred_format( - &self, - _device_id: id::DeviceId, - ) -> Result { - span!(_guard, INFO, "Device::get_swap_chain_preferred_format"); - //TODO: we can query the formats like done in `device_create_swapchain`, - // but its not clear which format in the list to return. - // For now, return `Bgra8UnormSrgb` that we know is supported everywhere. - Ok(TextureFormat::Bgra8UnormSrgb) - } - pub fn device_create_swap_chain( &self, device_id: id::DeviceId, diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index 0f3e3e4d30..79a6983d14 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -250,6 +250,44 @@ impl Adapter { } } + pub fn get_swap_chain_preferred_format( + &self, + surface: &mut Surface, + ) -> Result { + span!(_guard, INFO, "Adapter::get_swap_chain_preferred_format"); + + let formats = { + let surface = B::get_surface_mut(surface); + let queue_family = &self.raw.queue_families[0]; + if !surface.supports_queue_family(queue_family) { + return Err(GetSwapChainPreferredFormatError::UnsupportedQueueFamily); + } + surface.supported_formats(&self.raw.physical_device) + }; + if let Some(formats) = formats { + // Check the four formats mentioned in the WebGPU spec: + // Bgra8UnormSrgb, Rgba8UnormSrgb, Bgra8Unorm, Rgba8Unorm + // Also, prefer sRGB over linear as it is better in + // representing perceived colors. + if formats.contains(&hal::format::Format::Bgra8Srgb) { + return Ok(wgt::TextureFormat::Bgra8UnormSrgb); + } + if formats.contains(&hal::format::Format::Rgba8Srgb) { + return Ok(wgt::TextureFormat::Rgba8UnormSrgb); + } + if formats.contains(&hal::format::Format::Bgra8Unorm) { + return Ok(wgt::TextureFormat::Bgra8Unorm); + } + if formats.contains(&hal::format::Format::Rgba8Unorm) { + return Ok(wgt::TextureFormat::Rgba8Unorm); + } + return Err(GetSwapChainPreferredFormatError::NotFound); + } + + // If no formats were returned, use Bgra8UnormSrgb + Ok(wgt::TextureFormat::Bgra8UnormSrgb) + } + pub(crate) fn get_texture_format_features( &self, format: wgt::TextureFormat, @@ -448,6 +486,18 @@ impl crate::hub::Resource for Adapter { } } +#[derive(Clone, Debug, Error)] +pub enum GetSwapChainPreferredFormatError { + #[error("no suitable format found")] + NotFound, + #[error("invalid adapter")] + InvalidAdapter, + #[error("invalid surface")] + InvalidSurface, + #[error("surface does not support the adapter's queue family")] + UnsupportedQueueFamily, +} + #[derive(Clone, Debug, Error)] /// Error when requesting a device from the adaptor pub enum RequestDeviceError {