mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
Merge #1142
1142: Move get_swap_chain_preferred_format from device to adapter and check formats r=kvark a=niklaskorz
**Connections**
https://github.com/gfx-rs/wgpu-rs/issues/123#issuecomment-757831458
**Description**
Not all devices actually support `Bgra8UnormSrgb`. If this is the case, a similar format like `Rgba8UnormSrgb` can be used.
**Testing**
e5ebfa70a4/learn-wgpu/src/lib.rs (L137)
- Output on MacBook Pro 13" Intel 2020 macOS Metal: `Format: Bgra8UnormSrgb`
- Output on OnePlus 7 Pro Android Vulkan: `Format: Rgba8UnormSrgb`
Co-authored-by: Niklas Korz <niklas@niklaskorz.de>
This commit is contained in:
@@ -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<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
pub fn adapter_get_swap_chain_preferred_format<B: GfxBackend>(
|
||||
&self,
|
||||
adapter_id: id::AdapterId,
|
||||
surface_id: id::SurfaceId,
|
||||
) -> Result<TextureFormat, instance::GetSwapChainPreferredFormatError> {
|
||||
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<B: GfxBackend>(
|
||||
&self,
|
||||
device_id: id::DeviceId,
|
||||
@@ -3885,17 +3907,6 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.push(layout_id);
|
||||
}
|
||||
|
||||
pub fn device_get_swap_chain_preferred_format<B: GfxBackend>(
|
||||
&self,
|
||||
_device_id: id::DeviceId,
|
||||
) -> Result<TextureFormat, InvalidDevice> {
|
||||
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<B: GfxBackend>(
|
||||
&self,
|
||||
device_id: id::DeviceId,
|
||||
|
||||
@@ -250,6 +250,44 @@ impl<B: GfxBackend> Adapter<B> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_swap_chain_preferred_format(
|
||||
&self,
|
||||
surface: &mut Surface,
|
||||
) -> Result<wgt::TextureFormat, GetSwapChainPreferredFormatError> {
|
||||
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<B: hal::Backend> crate::hub::Resource for Adapter<B> {
|
||||
}
|
||||
}
|
||||
|
||||
#[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 {
|
||||
|
||||
Reference in New Issue
Block a user