Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[dx12] Use typeless formats for textures that might be viewed as srgb or non-srgb #3555

Merged
merged 1 commit into from
Mar 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ By @teoxoy in [#3436](https://github.com/gfx-rs/wgpu/pull/3436)
#### 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

Expand Down
48 changes: 39 additions & 9 deletions wgpu-hal/src/auxil/dxgi/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down
15 changes: 13 additions & 2 deletions wgpu-hal/src/dx12/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<crate::dx12::types::D3D12_FEATURE_DATA_D3D12_OPTIONS3>() as _,
)
};
hr == 0 && features3.CastingFullyTypedFormatSupported != 0
};

let private_caps = super::PrivateCapabilities {
instance_flags,
Expand All @@ -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
Expand Down
20 changes: 6 additions & 14 deletions wgpu-hal/src/dx12/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,20 +406,12 @@ impl crate::Device<super::Api> 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,
Expand Down
2 changes: 2 additions & 0 deletions wgpu-hal/src/dx12/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 _};
Expand Down Expand Up @@ -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)]
Expand Down
34 changes: 34 additions & 0 deletions wgpu-hal/src/dx12/types.rs
Original file line number Diff line number Diff line change
@@ -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,
}
}