diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 8a9eb0fbbe..35a26d4a14 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -3013,12 +3013,12 @@ impl Global { .map_err(|_| instance::IsSurfaceSupportedError::InvalidSurface)?; Ok(adapter.is_surface_supported(surface)) } - pub fn surface_get_preferred_format( + pub fn surface_get_supported_formats( &self, surface_id: id::SurfaceId, adapter_id: id::AdapterId, - ) -> Result { - profiling::scope!("surface_get_preferred_format"); + ) -> Result, instance::GetSurfacePreferredFormatError> { + profiling::scope!("Surface::get_supported_formats"); let hub = A::hub(self); let mut token = Token::root(); @@ -3031,7 +3031,7 @@ impl Global { .get(surface_id) .map_err(|_| instance::GetSurfacePreferredFormatError::InvalidSurface)?; - surface.get_preferred_format(adapter) + surface.get_supported_formats(adapter) } pub fn device_features( diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index 907c65d08c..39fc65343d 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -152,21 +152,10 @@ impl crate::hub::Resource for Surface { } impl Surface { - pub fn get_preferred_format( + pub fn get_supported_formats( &self, adapter: &Adapter, - ) -> Result { - // Check the four formats mentioned in the WebGPU spec. - // Also, prefer sRGB over linear as it is better in - // representing perceived colors. - let preferred_formats = [ - wgt::TextureFormat::Bgra8UnormSrgb, - wgt::TextureFormat::Rgba8UnormSrgb, - wgt::TextureFormat::Bgra8Unorm, - wgt::TextureFormat::Rgba8Unorm, - wgt::TextureFormat::Rgba16Float, - ]; - + ) -> Result, GetSurfacePreferredFormatError> { let suf = A::get_surface(self); let caps = unsafe { profiling::scope!("surface_capabilities"); @@ -177,11 +166,11 @@ impl Surface { .ok_or(GetSurfacePreferredFormatError::UnsupportedQueueFamily)? }; - preferred_formats - .iter() - .cloned() - .find(|preferred| caps.formats.contains(preferred)) - .ok_or(GetSurfacePreferredFormatError::NotFound) + if caps.formats.is_empty() { + return Err(GetSurfacePreferredFormatError::NotFound); + } + + Ok(caps.formats) } } diff --git a/wgpu/examples/framework.rs b/wgpu/examples/framework.rs index 63c91fd80e..35a398594c 100644 --- a/wgpu/examples/framework.rs +++ b/wgpu/examples/framework.rs @@ -198,7 +198,11 @@ fn start( let spawner = Spawner::new(); let mut config = wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT, - format: surface.get_preferred_format(&adapter).unwrap(), + format: *surface + .get_supported_formats(&adapter) + .unwrap() + .first() + .unwrap(), width: size.width, height: size.height, present_mode: wgpu::PresentMode::Mailbox, diff --git a/wgpu/examples/hello-triangle/main.rs b/wgpu/examples/hello-triangle/main.rs index fe6f0c2132..c1d292d41c 100644 --- a/wgpu/examples/hello-triangle/main.rs +++ b/wgpu/examples/hello-triangle/main.rs @@ -46,7 +46,11 @@ async fn run(event_loop: EventLoop<()>, window: Window) { push_constant_ranges: &[], }); - let swapchain_format = surface.get_preferred_format(&adapter).unwrap(); + let swapchain_format = *surface + .get_supported_formats(&adapter) + .unwrap() + .first() + .unwrap(); let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: None, diff --git a/wgpu/examples/hello-windows/main.rs b/wgpu/examples/hello-windows/main.rs index ca725f44b3..7ead1cbc8e 100644 --- a/wgpu/examples/hello-windows/main.rs +++ b/wgpu/examples/hello-windows/main.rs @@ -33,7 +33,12 @@ impl ViewportDesc { let config = wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT, - format: self.surface.get_preferred_format(adapter).unwrap(), + format: *self + .surface + .get_supported_formats(adapter) + .unwrap() + .first() + .unwrap(), width: size.width, height: size.height, present_mode: wgpu::PresentMode::Fifo, diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index 58acf88c3b..f6bb271126 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -932,17 +932,17 @@ impl crate::Context for Context { } } - fn surface_get_preferred_format( + fn surface_get_supported_formats( &self, surface: &Self::SurfaceId, adapter: &Self::AdapterId, - ) -> Option { + ) -> Option> { let global = &self.0; - match wgc::gfx_select!(adapter => global.surface_get_preferred_format(surface.id, *adapter)) + match wgc::gfx_select!(adapter => global.surface_get_supported_formats(surface.id, *adapter)) { - Ok(format) => Some(format), + Ok(formats) => Some(formats), Err(wgc::instance::GetSurfacePreferredFormatError::UnsupportedQueueFamily) => None, - Err(err) => self.handle_error_fatal(err, "Surface::get_preferred_format"), + Err(err) => self.handle_error_fatal(err, "Surface::get_supported_formats"), } } diff --git a/wgpu/src/backend/web.rs b/wgpu/src/backend/web.rs index af496942c8..7a2e99277a 100644 --- a/wgpu/src/backend/web.rs +++ b/wgpu/src/backend/web.rs @@ -553,56 +553,6 @@ fn map_texture_format(texture_format: wgt::TextureFormat) -> web_sys::GpuTexture } } -fn map_texture_format_from_web_sys( - texture_format: web_sys::GpuTextureFormat, -) -> wgt::TextureFormat { - use web_sys::GpuTextureFormat as tf; - use wgt::TextureFormat; - match texture_format { - tf::R8unorm => TextureFormat::R8Unorm, - tf::R8snorm => TextureFormat::R8Snorm, - tf::R8uint => TextureFormat::R8Uint, - tf::R8sint => TextureFormat::R8Sint, - tf::R16uint => TextureFormat::R16Uint, - tf::R16sint => TextureFormat::R16Sint, - tf::R16float => TextureFormat::R16Float, - tf::Rg8unorm => TextureFormat::Rg8Unorm, - tf::Rg8snorm => TextureFormat::Rg8Snorm, - tf::Rg8uint => TextureFormat::Rg8Uint, - tf::Rg8sint => TextureFormat::Rg8Sint, - tf::R32uint => TextureFormat::R32Uint, - tf::R32sint => TextureFormat::R32Sint, - tf::R32float => TextureFormat::R32Float, - tf::Rg16uint => TextureFormat::Rg16Uint, - tf::Rg16sint => TextureFormat::Rg16Sint, - tf::Rg16float => TextureFormat::Rg16Float, - tf::Rgba8unorm => TextureFormat::Rgba8Unorm, - tf::Rgba8unormSrgb => TextureFormat::Rgba8UnormSrgb, - tf::Rgba8snorm => TextureFormat::Rgba8Snorm, - tf::Rgba8uint => TextureFormat::Rgba8Uint, - tf::Rgba8sint => TextureFormat::Rgba8Sint, - tf::Bgra8unorm => TextureFormat::Bgra8Unorm, - tf::Bgra8unormSrgb => TextureFormat::Bgra8UnormSrgb, - tf::Rgb10a2unorm => TextureFormat::Rgb10a2Unorm, - tf::Rg11b10ufloat => TextureFormat::Rg11b10Float, - tf::Rg32uint => TextureFormat::Rg32Uint, - tf::Rg32sint => TextureFormat::Rg32Sint, - tf::Rg32float => TextureFormat::Rg32Float, - tf::Rgba16uint => TextureFormat::Rgba16Uint, - tf::Rgba16sint => TextureFormat::Rgba16Sint, - tf::Rgba16float => TextureFormat::Rgba16Float, - tf::Rgba32uint => TextureFormat::Rgba32Uint, - tf::Rgba32sint => TextureFormat::Rgba32Sint, - tf::Rgba32float => TextureFormat::Rgba32Float, - tf::Depth32float => TextureFormat::Depth32Float, - tf::Depth32floatStencil8 => TextureFormat::Depth32FloatStencil8, - tf::Depth24plus => TextureFormat::Depth24Plus, - tf::Depth24plusStencil8 => TextureFormat::Depth24PlusStencil8, - tf::Depth24unormStencil8 => TextureFormat::Depth24UnormStencil8, - _ => unimplemented!(), - } -} - fn map_texture_component_type( sample_type: wgt::TextureSampleType, ) -> web_sys::GpuTextureSampleType { @@ -1188,13 +1138,18 @@ impl crate::Context for Context { format.describe().guaranteed_format_features } - fn surface_get_preferred_format( + fn surface_get_supported_formats( &self, - surface: &Self::SurfaceId, - adapter: &Self::AdapterId, - ) -> Option { - let format = map_texture_format_from_web_sys(surface.0.get_preferred_format(&adapter.0)); - Some(format) + _surface: &Self::SurfaceId, + _adapter: &Self::AdapterId, + ) -> Option> { + // https://gpuweb.github.io/gpuweb/#supported-context-formats + let formats = vec![ + wgt::TextureFormat::Bgra8Unorm, + wgt::TextureFormat::Rgba8Unorm, + wgt::TextureFormat::Rgba16Float, + ]; + Some(formats) } fn surface_configure( diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 38ae0fab0f..8eb5afe11e 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -225,11 +225,11 @@ trait Context: Debug + Send + Sized + Sync { format: TextureFormat, ) -> TextureFormatFeatures; - fn surface_get_preferred_format( + fn surface_get_supported_formats( &self, surface: &Self::SurfaceId, adapter: &Self::AdapterId, - ) -> Option; + ) -> Option>; fn surface_configure( &self, surface: &Self::SurfaceId, @@ -3435,11 +3435,12 @@ impl Drop for SurfaceTexture { } impl Surface { - /// Returns an optimal texture format to use for the [`Surface`] with this adapter. + /// Returns a vec of supported texture formats to use for the [`Surface`] with this adapter. + /// Note: The first format in the vector is preferred /// /// Returns None if the surface is incompatible with the adapter. - pub fn get_preferred_format(&self, adapter: &Adapter) -> Option { - Context::surface_get_preferred_format(&*self.context, &self.id, &adapter.id) + pub fn get_supported_formats(&self, adapter: &Adapter) -> Option> { + Context::surface_get_supported_formats(&*self.context, &self.id, &adapter.id) } /// Initializes [`Surface`] for presentation.