From 54e4c8654d85eb28262db0a24d07e4c6db612b38 Mon Sep 17 00:00:00 2001 From: Teodor Tanasoaia <28601907+teoxoy@users.noreply.github.com> Date: Fri, 3 Mar 2023 20:42:34 +0100 Subject: [PATCH] [dx12] use typeless formats for textures that might be viewed as srgb or non-srgb (#3555) query `CastingFullyTypedFormatSupported` and skip typeless formats if available --- CHANGELOG.md | 1 + wgpu-hal/src/auxil/dxgi/conv.rs | 48 ++++++++++++++++++++++++++------- wgpu-hal/src/dx12/adapter.rs | 15 +++++++++-- wgpu-hal/src/dx12/device.rs | 20 +++++--------- wgpu-hal/src/dx12/mod.rs | 2 ++ wgpu-hal/src/dx12/types.rs | 34 +++++++++++++++++++++++ 6 files changed, 95 insertions(+), 25 deletions(-) create mode 100644 wgpu-hal/src/dx12/types.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index d09a34126..d03013dad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -114,6 +114,7 @@ By @teoxoy in [#3534](https://github.com/gfx-rs/wgpu/pull/3534) #### DX12 - Fix DXC validation issues when using a custom `dxil_path`. By @Elabajaba in [#3434](https://github.com/gfx-rs/wgpu/pull/3434) +- Use typeless formats for textures that might be viewed as srgb or non-srgb. By @teoxoy in [#3555](https://github.com/gfx-rs/wgpu/pull/3555) #### GLES diff --git a/wgpu-hal/src/auxil/dxgi/conv.rs b/wgpu-hal/src/auxil/dxgi/conv.rs index 696e953d1..9cec14323 100644 --- a/wgpu-hal/src/auxil/dxgi/conv.rs +++ b/wgpu-hal/src/auxil/dxgi/conv.rs @@ -163,17 +163,47 @@ pub fn map_texture_format_for_copy( }) } -pub fn map_texture_format_depth_stencil_typeless( +pub fn map_texture_format_for_resource( format: wgt::TextureFormat, + usage: crate::TextureUses, + has_view_formats: bool, + casting_fully_typed_format_supported: bool, ) -> dxgiformat::DXGI_FORMAT { - match format { - wgt::TextureFormat::Depth16Unorm => dxgiformat::DXGI_FORMAT_R16_TYPELESS, - wgt::TextureFormat::Depth32Float => dxgiformat::DXGI_FORMAT_R32_TYPELESS, - wgt::TextureFormat::Depth32FloatStencil8 => dxgiformat::DXGI_FORMAT_R32G8X24_TYPELESS, - wgt::TextureFormat::Stencil8 - | wgt::TextureFormat::Depth24Plus - | wgt::TextureFormat::Depth24PlusStencil8 => dxgiformat::DXGI_FORMAT_R24G8_TYPELESS, - _ => unreachable!(), + use wgt::TextureFormat as Tf; + use winapi::shared::dxgiformat::*; + + if casting_fully_typed_format_supported { + map_texture_format(format) + + // We might view this resource as srgb or non-srgb + } else if has_view_formats { + match format { + Tf::Rgba8Unorm | Tf::Rgba8UnormSrgb => DXGI_FORMAT_R8G8B8A8_TYPELESS, + Tf::Bgra8Unorm | Tf::Bgra8UnormSrgb => DXGI_FORMAT_B8G8R8A8_TYPELESS, + Tf::Bc1RgbaUnorm | Tf::Bc1RgbaUnormSrgb => DXGI_FORMAT_BC1_TYPELESS, + Tf::Bc2RgbaUnorm | Tf::Bc2RgbaUnormSrgb => DXGI_FORMAT_BC2_TYPELESS, + Tf::Bc3RgbaUnorm | Tf::Bc3RgbaUnormSrgb => DXGI_FORMAT_BC3_TYPELESS, + Tf::Bc7RgbaUnorm | Tf::Bc7RgbaUnormSrgb => DXGI_FORMAT_BC7_TYPELESS, + format => map_texture_format(format), + } + + // We might view this resource as SRV/UAV but also as DSV + } else if format.is_depth_stencil_format() + && usage.intersects( + crate::TextureUses::RESOURCE + | crate::TextureUses::STORAGE_READ + | crate::TextureUses::STORAGE_READ_WRITE, + ) + { + match format { + Tf::Depth16Unorm => DXGI_FORMAT_R16_TYPELESS, + Tf::Depth32Float => DXGI_FORMAT_R32_TYPELESS, + Tf::Depth32FloatStencil8 => DXGI_FORMAT_R32G8X24_TYPELESS, + Tf::Stencil8 | Tf::Depth24Plus | Tf::Depth24PlusStencil8 => DXGI_FORMAT_R24G8_TYPELESS, + _ => unreachable!(), + } + } else { + map_texture_format(format) } } diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index 82ac921c9..a77484c30 100644 --- a/wgpu-hal/src/dx12/adapter.rs +++ b/wgpu-hal/src/dx12/adapter.rs @@ -151,8 +151,18 @@ impl super::Adapter { hr == 0 && features2.DepthBoundsTestSupported != 0 }; - //Note: `D3D12_FEATURE_D3D12_OPTIONS3::CastingFullyTypedFormatSupported` can be checked - // to know if we can skip "typeless" formats entirely. + let casting_fully_typed_format_supported = { + let mut features3: crate::dx12::types::D3D12_FEATURE_DATA_D3D12_OPTIONS3 = + unsafe { mem::zeroed() }; + let hr = unsafe { + device.CheckFeatureSupport( + 21, // D3D12_FEATURE_D3D12_OPTIONS3 + &mut features3 as *mut _ as *mut _, + mem::size_of::() as _, + ) + }; + hr == 0 && features3.CastingFullyTypedFormatSupported != 0 + }; let private_caps = super::PrivateCapabilities { instance_flags, @@ -166,6 +176,7 @@ impl super::Adapter { super::MemoryArchitecture::NonUnified }, heap_create_not_zeroed: false, //TODO: winapi support for Options7 + casting_fully_typed_format_supported, }; // Theoretically vram limited, but in practice 2^20 is the limit diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 62a7710ce..24fea5566 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -406,20 +406,12 @@ impl crate::Device for super::Device { Height: desc.size.height, DepthOrArraySize: desc.size.depth_or_array_layers as u16, MipLevels: desc.mip_level_count as u16, - Format: if crate::FormatAspects::from(desc.format).contains(crate::FormatAspects::COLOR) - || !desc.usage.intersects( - crate::TextureUses::RESOURCE - | crate::TextureUses::STORAGE_READ - | crate::TextureUses::STORAGE_READ_WRITE, - ) { - auxil::dxgi::conv::map_texture_format(desc.format) - } else { - // This branch is needed if it's a depth texture, and it's ever needed to be viewed as SRV or UAV, - // because then we'd create a non-depth format view of it. - // Note: we can skip this branch if - // `D3D12_FEATURE_D3D12_OPTIONS3::CastingFullyTypedFormatSupported` - auxil::dxgi::conv::map_texture_format_depth_stencil_typeless(desc.format) - }, + Format: auxil::dxgi::conv::map_texture_format_for_resource( + desc.format, + desc.usage, + !desc.view_formats.is_empty(), + self.private_caps.casting_fully_typed_format_supported, + ), SampleDesc: dxgitype::DXGI_SAMPLE_DESC { Count: desc.sample_count, Quality: 0, diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index 560701900..390a5693a 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -41,6 +41,7 @@ mod device; mod instance; mod shader_compilation; mod suballocation; +mod types; mod view; use crate::auxil::{self, dxgi::result::HResult as _}; @@ -174,6 +175,7 @@ struct PrivateCapabilities { memory_architecture: MemoryArchitecture, #[allow(unused)] // TODO: Exists until windows-rs is standard, then it can probably be removed? heap_create_not_zeroed: bool, + casting_fully_typed_format_supported: bool, } #[derive(Default)] diff --git a/wgpu-hal/src/dx12/types.rs b/wgpu-hal/src/dx12/types.rs new file mode 100644 index 000000000..dec4e7133 --- /dev/null +++ b/wgpu-hal/src/dx12/types.rs @@ -0,0 +1,34 @@ +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +winapi::ENUM! { + enum D3D12_VIEW_INSTANCING_TIER { + D3D12_VIEW_INSTANCING_TIER_NOT_SUPPORTED = 0, + D3D12_VIEW_INSTANCING_TIER_1 = 1, + D3D12_VIEW_INSTANCING_TIER_2 = 2, + D3D12_VIEW_INSTANCING_TIER_3 = 3, + } +} + +winapi::ENUM! { + enum D3D12_COMMAND_LIST_SUPPORT_FLAGS { + D3D12_COMMAND_LIST_SUPPORT_FLAG_NONE = 0, + // D3D12_COMMAND_LIST_SUPPORT_FLAG_DIRECT, + // D3D12_COMMAND_LIST_SUPPORT_FLAG_BUNDLE, + // D3D12_COMMAND_LIST_SUPPORT_FLAG_COMPUTE, + // D3D12_COMMAND_LIST_SUPPORT_FLAG_COPY, + // D3D12_COMMAND_LIST_SUPPORT_FLAG_VIDEO_DECODE, + // D3D12_COMMAND_LIST_SUPPORT_FLAG_VIDEO_PROCESS, + // D3D12_COMMAND_LIST_SUPPORT_FLAG_VIDEO_ENCODE, + } +} + +winapi::STRUCT! { + struct D3D12_FEATURE_DATA_D3D12_OPTIONS3 { + CopyQueueTimestampQueriesSupported: winapi::shared::minwindef::BOOL, + CastingFullyTypedFormatSupported: winapi::shared::minwindef::BOOL, + WriteBufferImmediateSupportFlags: D3D12_COMMAND_LIST_SUPPORT_FLAGS, + ViewInstancingTier: D3D12_VIEW_INSTANCING_TIER, + BarycentricsSupported: winapi::shared::minwindef::BOOL, + } +}