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:
bors[bot]
2021-01-11 19:03:40 +00:00
committed by GitHub
2 changed files with 73 additions and 12 deletions

View File

@@ -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,

View File

@@ -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 {