From 7bc79cbd017653a6e0e1d0ad5dbb88e39ccd8cb7 Mon Sep 17 00:00:00 2001 From: Triang3l Date: Tue, 9 Oct 2018 21:44:18 +0300 Subject: [PATCH] [D3D12] Signed texture SRVs --- .../gpu/d3d12/d3d12_command_processor.cc | 6 +- src/xenia/gpu/d3d12/render_target_cache.cc | 6 +- src/xenia/gpu/d3d12/texture_cache.cc | 446 ++++++++++++------ src/xenia/gpu/d3d12/texture_cache.h | 62 ++- src/xenia/gpu/dxbc_shader_translator.h | 6 +- 5 files changed, 345 insertions(+), 181 deletions(-) diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.cc b/src/xenia/gpu/d3d12/d3d12_command_processor.cc index 51fc49d7e..dc634a4f5 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.cc @@ -2196,8 +2196,7 @@ bool D3D12CommandProcessor::UpdateBindings( gpu_handle_textures_vertex_ = view_gpu_handle; for (uint32_t i = 0; i < texture_count_vertex; ++i) { const D3D12Shader::TextureSRV& srv = textures_vertex[i]; - texture_cache_->WriteTextureSRV(srv.fetch_constant, srv.dimension, - view_cpu_handle); + texture_cache_->WriteTextureSRV(srv, view_cpu_handle); view_cpu_handle.ptr += descriptor_size_view; view_gpu_handle.ptr += descriptor_size_view; } @@ -2212,8 +2211,7 @@ bool D3D12CommandProcessor::UpdateBindings( gpu_handle_textures_pixel_ = view_gpu_handle; for (uint32_t i = 0; i < texture_count_pixel; ++i) { const D3D12Shader::TextureSRV& srv = textures_pixel[i]; - texture_cache_->WriteTextureSRV(srv.fetch_constant, srv.dimension, - view_cpu_handle); + texture_cache_->WriteTextureSRV(srv, view_cpu_handle); view_cpu_handle.ptr += descriptor_size_view; view_gpu_handle.ptr += descriptor_size_view; } diff --git a/src/xenia/gpu/d3d12/render_target_cache.cc b/src/xenia/gpu/d3d12/render_target_cache.cc index c22a67159..2227b6f45 100644 --- a/src/xenia/gpu/d3d12/render_target_cache.cc +++ b/src/xenia/gpu/d3d12/render_target_cache.cc @@ -1740,11 +1740,9 @@ DXGI_FORMAT RenderTargetCache::GetColorDXGIFormat( case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16: return DXGI_FORMAT_R16G16B16A16_FLOAT; case ColorRenderTargetFormat::k_16_16: - // TODO(Triang3l): Change to SNORM when signed textures are supported. - return DXGI_FORMAT_R16G16_UNORM; + return DXGI_FORMAT_R16G16_SNORM; case ColorRenderTargetFormat::k_16_16_16_16: - // TODO(Triang3l): Change to SNORM when signed textures are supported. - return DXGI_FORMAT_R16G16B16A16_UNORM; + return DXGI_FORMAT_R16G16B16A16_SNORM; case ColorRenderTargetFormat::k_16_16_FLOAT: return DXGI_FORMAT_R16G16_FLOAT; case ColorRenderTargetFormat::k_32_FLOAT: diff --git a/src/xenia/gpu/d3d12/texture_cache.cc b/src/xenia/gpu/d3d12/texture_cache.cc index 58bec4edd..20cb576f9 100644 --- a/src/xenia/gpu/d3d12/texture_cache.cc +++ b/src/xenia/gpu/d3d12/texture_cache.cc @@ -50,209 +50,277 @@ namespace d3d12 { const TextureCache::HostFormat TextureCache::host_formats_[64] = { // k_1_REVERSE - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_1 - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_8 - {DXGI_FORMAT_R8_UNORM, LoadMode::k8bpb, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_R8_UNORM, ResolveTileMode::k8bpp}, + {DXGI_FORMAT_R8_TYPELESS, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_SNORM, + LoadMode::k8bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_R8_UNORM, ResolveTileMode::k8bpp}, // k_1_5_5_5 - {DXGI_FORMAT_B5G5R5A1_UNORM, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, + {DXGI_FORMAT_B5G5R5A1_UNORM, DXGI_FORMAT_B5G5R5A1_UNORM, + DXGI_FORMAT_UNKNOWN, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_R8G8B8A8_UNORM, ResolveTileMode::k16bppRGBA}, // k_5_6_5 - {DXGI_FORMAT_B5G6R5_UNORM, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_B5G6R5_UNORM, ResolveTileMode::k16bpp}, + {DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_UNKNOWN, + LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_B5G6R5_UNORM, ResolveTileMode::k16bpp}, // k_6_5_5 - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_8_8_8_8 - {DXGI_FORMAT_R8G8B8A8_UNORM, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, + {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_SNORM, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_R8G8B8A8_UNORM, ResolveTileMode::k32bpp}, // k_2_10_10_10 - {DXGI_FORMAT_R10G10B10A2_UNORM, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, + {DXGI_FORMAT_R10G10B10A2_TYPELESS, DXGI_FORMAT_R10G10B10A2_UNORM, + DXGI_FORMAT_UNKNOWN, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_R10G10B10A2_UNORM, ResolveTileMode::k32bpp}, // k_8_A - {DXGI_FORMAT_R8_UNORM, LoadMode::k8bpb, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_R8_UNORM, ResolveTileMode::k8bpp}, + {DXGI_FORMAT_R8_TYPELESS, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_SNORM, + LoadMode::k8bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_R8_UNORM, ResolveTileMode::k8bpp}, // k_8_B - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_8_8 - {DXGI_FORMAT_R8G8_UNORM, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_R8G8_UNORM, ResolveTileMode::k16bpp}, + {DXGI_FORMAT_R8G8_TYPELESS, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_SNORM, + LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_R8G8_UNORM, ResolveTileMode::k16bpp}, // k_Cr_Y1_Cb_Y0_REP - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_Y1_Cr_Y0_Cb_REP - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_16_16_EDRAM // Not usable as a texture, also has -32...32 range. - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_8_8_8_8_A - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_4_4_4_4 - {DXGI_FORMAT_B4G4R4A4_UNORM, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, + {DXGI_FORMAT_B4G4R4A4_UNORM, DXGI_FORMAT_B4G4R4A4_UNORM, + DXGI_FORMAT_UNKNOWN, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_R8G8B8A8_UNORM, ResolveTileMode::k16bppRGBA}, // k_10_11_11 - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_11_11_10 - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_DXT1 - {DXGI_FORMAT_BC1_UNORM, LoadMode::k64bpb, DXGI_FORMAT_R8G8B8A8_UNORM, - LoadMode::kDXT1ToRGBA8, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, + LoadMode::k64bpb, DXGI_FORMAT_R8G8B8A8_UNORM, LoadMode::kDXT1ToRGBA8, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_DXT2_3 - {DXGI_FORMAT_BC2_UNORM, LoadMode::k128bpb, DXGI_FORMAT_R8G8B8A8_UNORM, - LoadMode::kDXT3ToRGBA8, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_UNKNOWN, + LoadMode::k128bpb, DXGI_FORMAT_R8G8B8A8_UNORM, LoadMode::kDXT3ToRGBA8, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_DXT4_5 - {DXGI_FORMAT_BC3_UNORM, LoadMode::k128bpb, DXGI_FORMAT_R8G8B8A8_UNORM, - LoadMode::kDXT5ToRGBA8, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_UNKNOWN, + LoadMode::k128bpb, DXGI_FORMAT_R8G8B8A8_UNORM, LoadMode::kDXT5ToRGBA8, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_16_16_16_16_EDRAM // Not usable as a texture, also has -32...32 range. - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // R32_FLOAT for depth because shaders would require an additional SRV to // sample stencil, which we don't provide. // k_24_8 - {DXGI_FORMAT_R32_FLOAT, LoadMode::kDepthUnorm, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, + LoadMode::kDepthUnorm, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_24_8_FLOAT - {DXGI_FORMAT_R32_FLOAT, LoadMode::kDepthFloat, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, + LoadMode::kDepthFloat, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_16 - {DXGI_FORMAT_R16_UNORM, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_R16_UNORM, ResolveTileMode::k16bpp}, + {DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_SNORM, + LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_R16_UNORM, ResolveTileMode::k16bpp}, // k_16_16 - {DXGI_FORMAT_R16G16_UNORM, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_R16G16_UNORM, ResolveTileMode::k32bpp}, + // TODO(Triang3l): Check if this is the correct way of specifying a signed + // resolve destination format. + {DXGI_FORMAT_R16G16_TYPELESS, DXGI_FORMAT_R16G16_UNORM, + DXGI_FORMAT_R16G16_SNORM, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_R16G16_SNORM, ResolveTileMode::k32bpp}, // k_16_16_16_16 - {DXGI_FORMAT_R16G16B16A16_UNORM, LoadMode::k64bpb, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_R16G16B16A16_UNORM, + // TODO(Triang3l): Check if this is the correct way of specifying a signed + // resolve destination format. + {DXGI_FORMAT_R16G16B16A16_TYPELESS, DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_SNORM, LoadMode::k64bpb, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_R16G16B16A16_SNORM, ResolveTileMode::k64bpp}, // k_16_EXPAND - {DXGI_FORMAT_R16_FLOAT, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_R16_FLOAT, ResolveTileMode::k16bpp}, + {DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, + LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_R16_FLOAT, ResolveTileMode::k16bpp}, // k_16_16_EXPAND - {DXGI_FORMAT_R16G16_FLOAT, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, + {DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, + DXGI_FORMAT_R16G16_FLOAT, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_R16G16_FLOAT, ResolveTileMode::k32bpp}, // k_16_16_16_16_EXPAND - {DXGI_FORMAT_R16G16B16A16_FLOAT, LoadMode::k64bpb, DXGI_FORMAT_UNKNOWN, + {DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, LoadMode::k64bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_R16G16B16A16_FLOAT, ResolveTileMode::k64bpp}, // k_16_FLOAT - {DXGI_FORMAT_R16_FLOAT, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_R16_FLOAT, ResolveTileMode::k16bpp}, + {DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, + LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_R16_FLOAT, ResolveTileMode::k16bpp}, // k_16_16_FLOAT - {DXGI_FORMAT_R16G16_FLOAT, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, + {DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, + DXGI_FORMAT_R16G16_FLOAT, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_R16G16_FLOAT, ResolveTileMode::k32bpp}, // k_16_16_16_16_FLOAT - {DXGI_FORMAT_R16G16B16A16_FLOAT, LoadMode::k64bpb, DXGI_FORMAT_UNKNOWN, + {DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, LoadMode::k64bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_R16G16B16A16_FLOAT, ResolveTileMode::k64bpp}, // k_32 - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_32_32 - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_32_32_32_32 - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_32_FLOAT - {DXGI_FORMAT_R32_FLOAT, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_R32_FLOAT, ResolveTileMode::k32bpp}, + {DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, + LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_R32_FLOAT, ResolveTileMode::k32bpp}, // k_32_32_FLOAT - {DXGI_FORMAT_R32G32_FLOAT, LoadMode::k64bpb, DXGI_FORMAT_UNKNOWN, + {DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_R32G32_FLOAT, LoadMode::k64bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_R32G32_FLOAT, ResolveTileMode::k64bpp}, // k_32_32_32_32_FLOAT - {DXGI_FORMAT_R32G32B32A32_FLOAT, LoadMode::k128bpb, DXGI_FORMAT_UNKNOWN, + {DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, LoadMode::k128bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_32_AS_8 - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_32_AS_8_8 - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_16_MPEG - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_16_16_MPEG - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_8_INTERLACED - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_32_AS_8_INTERLACED - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_32_AS_8_8_INTERLACED - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_16_INTERLACED - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_16_MPEG_INTERLACED - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_16_16_MPEG_INTERLACED - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_DXN - {DXGI_FORMAT_BC5_UNORM, LoadMode::k128bpb, DXGI_FORMAT_R8G8_UNORM, - LoadMode::kDXNToRG8, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_UNKNOWN, + LoadMode::k128bpb, DXGI_FORMAT_R8G8_UNORM, LoadMode::kDXNToRG8, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_8_8_8_8_AS_16_16_16_16 - {DXGI_FORMAT_R8G8B8A8_UNORM, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, + {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_SNORM, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_R8G8B8A8_UNORM, ResolveTileMode::k32bpp}, // k_DXT1_AS_16_16_16_16 - {DXGI_FORMAT_BC1_UNORM, LoadMode::k64bpb, DXGI_FORMAT_R8G8B8A8_UNORM, - LoadMode::kDXT1ToRGBA8, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, + LoadMode::k64bpb, DXGI_FORMAT_R8G8B8A8_UNORM, LoadMode::kDXT1ToRGBA8, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_DXT2_3_AS_16_16_16_16 - {DXGI_FORMAT_BC2_UNORM, LoadMode::k128bpb, DXGI_FORMAT_R8G8B8A8_UNORM, - LoadMode::kDXT3ToRGBA8, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_UNKNOWN, + LoadMode::k128bpb, DXGI_FORMAT_R8G8B8A8_UNORM, LoadMode::kDXT3ToRGBA8, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_DXT4_5_AS_16_16_16_16 - {DXGI_FORMAT_BC3_UNORM, LoadMode::k128bpb, DXGI_FORMAT_R8G8B8A8_UNORM, - LoadMode::kDXT5ToRGBA8, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_UNKNOWN, + LoadMode::k128bpb, DXGI_FORMAT_R8G8B8A8_UNORM, LoadMode::kDXT5ToRGBA8, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_2_10_10_10_AS_16_16_16_16 - {DXGI_FORMAT_R10G10B10A2_UNORM, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, + {DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, + DXGI_FORMAT_UNKNOWN, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_R10G10B10A2_UNORM, ResolveTileMode::k32bpp}, // k_10_11_11_AS_16_16_16_16 - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_11_11_10_AS_16_16_16_16 - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_32_32_32_FLOAT - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_DXT3A - {DXGI_FORMAT_R8_UNORM, LoadMode::kDXT3A, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_UNKNOWN, + LoadMode::kDXT3A, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_DXT5A - {DXGI_FORMAT_BC4_UNORM, LoadMode::k64bpb, DXGI_FORMAT_R8_UNORM, - LoadMode::kDXT5AToR8, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_UNKNOWN, + LoadMode::k64bpb, DXGI_FORMAT_R8_UNORM, LoadMode::kDXT5AToR8, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_CTX1 - {DXGI_FORMAT_R8G8_UNORM, LoadMode::kCTX1, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN, + LoadMode::kCTX1, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_DXT3A_AS_1_1_1_1 - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, // k_8_8_8_8_GAMMA - {DXGI_FORMAT_R8G8B8A8_UNORM, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, + {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_SNORM, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_R8G8B8A8_UNORM, ResolveTileMode::k32bpp}, // k_2_10_10_10_FLOAT_EDRAM // Not usable as a texture. - {DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, - LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, + {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, + LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, + DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, }; const char* const TextureCache::dimension_names_[4] = {"1D", "2D", "3D", @@ -414,17 +482,27 @@ void TextureCache::BeginFrame() { // is requested again. ClearBindings(); - unsupported_formats_used_ = 0; + std::memset(unsupported_format_features_used_, 0, + sizeof(unsupported_format_features_used_)); } void TextureCache::EndFrame() { - if (unsupported_formats_used_ != 0) { - XELOGE("Unsupported texture formats used in the frame:"); - uint32_t format; - while (xe::bit_scan_forward(unsupported_formats_used_, &format)) { - unsupported_formats_used_ &= ~(1ull << format); - XELOGE("* %s", FormatInfo::Get(TextureFormat(format))->name); + // Report used unsupported texture formats. + bool unsupported_header_written = false; + for (uint32_t i = 0; i < 64; ++i) { + uint32_t unsupported_features = unsupported_format_features_used_[i]; + if (unsupported_features == 0) { + continue; } + if (!unsupported_header_written) { + XELOGE("Unsupported texture formats used in the frame:"); + unsupported_header_written = true; + } + XELOGE("* %s%s%s%s", FormatInfo::Get(TextureFormat(i))->name, + unsupported_features & kUnsupportedResourceBit ? " resource" : "", + unsupported_features & kUnsupportedUnormBit ? " unorm" : "", + unsupported_features & kUnsupportedSnormBit ? " snorm" : ""); + unsupported_format_features_used_[i] = 0; } } @@ -464,8 +542,9 @@ void TextureCache::RequestTextures(uint32_t used_vertex_texture_mask, auto group = reinterpret_cast(®s.values[r]); TextureKey old_key = binding.key; - TextureKeyFromFetchConstant(group->texture_fetch, binding.key, - binding.swizzle); + BindingInfoFromFetchConstant(group->texture_fetch, binding.key, + &binding.swizzle, &binding.has_unsigned, + &binding.has_signed); texture_keys_in_sync_ |= index_bit; if (binding.key.IsInvalid()) { binding.texture = nullptr; @@ -511,32 +590,59 @@ uint64_t TextureCache::GetDescriptorHashForActiveTextures( // There can be multiple SRVs of the same texture. XXH64_update(&hash_state, &texture_srv.dimension, sizeof(texture_srv.dimension)); + XXH64_update(&hash_state, &texture_srv.is_signed, + sizeof(texture_srv.is_signed)); + XXH64_update(&hash_state, &texture_srv.is_sign_required, + sizeof(texture_srv.is_sign_required)); const TextureBinding& binding = texture_bindings_[texture_srv.fetch_constant]; XXH64_update(&hash_state, &binding.key, sizeof(binding.key)); XXH64_update(&hash_state, &binding.swizzle, sizeof(binding.swizzle)); + XXH64_update(&hash_state, &binding.has_unsigned, + sizeof(binding.has_unsigned)); + XXH64_update(&hash_state, &binding.has_signed, sizeof(binding.has_signed)); } return XXH64_digest(&hash_state); } -void TextureCache::WriteTextureSRV(uint32_t fetch_constant, - TextureDimension shader_dimension, +void TextureCache::WriteTextureSRV(const D3D12Shader::TextureSRV& texture_srv, D3D12_CPU_DESCRIPTOR_HANDLE handle) { - const TextureBinding& binding = texture_bindings_[fetch_constant]; + const TextureBinding& binding = texture_bindings_[texture_srv.fetch_constant]; + ID3D12Resource* resource = + binding.texture != nullptr ? binding.texture->resource : nullptr; D3D12_SHADER_RESOURCE_VIEW_DESC desc; - desc.Format = GetDXGIFormat(binding.key); + desc.Format = DXGI_FORMAT_UNKNOWN; + if (texture_srv.is_signed) { + // Not supporting signed compressed textures - hopefully DXN and DXT5A are + // not used as signed. + if (binding.has_signed || texture_srv.is_sign_required) { + desc.Format = + host_formats_[uint32_t(binding.key.format)].dxgi_format_snorm; + if (desc.Format == DXGI_FORMAT_UNKNOWN) { + unsupported_format_features_used_[uint32_t(binding.key.format)] |= + kUnsupportedSnormBit; + } + } + } else { + if (binding.has_unsigned || texture_srv.is_sign_required) { + desc.Format = GetDXGIUnormFormat(binding.key); + if (desc.Format == DXGI_FORMAT_UNKNOWN) { + unsupported_format_features_used_[uint32_t(binding.key.format)] |= + kUnsupportedUnormBit; + } + } + } if (desc.Format == DXGI_FORMAT_UNKNOWN) { // A null descriptor must still have a valid format. desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + resource = nullptr; } // XE_GPU_SWIZZLE and D3D12_SHADER_COMPONENT_MAPPING are the same except for // one bit. desc.Shader4ComponentMapping = binding.swizzle | D3D12_SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES; - ID3D12Resource* resource = - binding.texture != nullptr ? binding.texture->resource : nullptr; - switch (shader_dimension) { + switch (texture_srv.dimension) { case TextureDimension::k3D: desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; desc.Texture3D.MostDetailedMip = 0; @@ -810,7 +916,8 @@ bool TextureCache::RequestSwapTexture(D3D12_CPU_DESCRIPTOR_HANDLE handle, auto& fetch = group->texture_fetch; TextureKey key; uint32_t swizzle; - TextureKeyFromFetchConstant(group->texture_fetch, key, swizzle); + BindingInfoFromFetchConstant(group->texture_fetch, key, &swizzle, nullptr, + nullptr); if (key.base_page == 0 || key.dimension != Dimension::k2D) { return false; } @@ -823,7 +930,7 @@ bool TextureCache::RequestSwapTexture(D3D12_CPU_DESCRIPTOR_HANDLE handle, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); texture->state = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc; - srv_desc.Format = GetDXGIFormat(key); + srv_desc.Format = GetDXGIUnormFormat(key); srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; srv_desc.Shader4ComponentMapping = swizzle | @@ -851,13 +958,22 @@ bool TextureCache::IsDecompressionNeeded(TextureFormat format, uint32_t width, (height & (format_info->block_height - 1)) != 0; } -void TextureCache::TextureKeyFromFetchConstant( +void TextureCache::BindingInfoFromFetchConstant( const xenos::xe_gpu_texture_fetch_t& fetch, TextureKey& key_out, - uint32_t& swizzle_out) { + uint32_t* swizzle_out, bool* has_unsigned_out, bool* has_signed_out) { // Reset the key and the swizzle. key_out.MakeInvalid(); - swizzle_out = xenos::XE_GPU_SWIZZLE_0 | (xenos::XE_GPU_SWIZZLE_0 << 3) | - (xenos::XE_GPU_SWIZZLE_0 << 6) | (xenos::XE_GPU_SWIZZLE_0 << 9); + if (swizzle_out != nullptr) { + *swizzle_out = xenos::XE_GPU_SWIZZLE_0 | (xenos::XE_GPU_SWIZZLE_0 << 3) | + (xenos::XE_GPU_SWIZZLE_0 << 6) | + (xenos::XE_GPU_SWIZZLE_0 << 9); + } + if (has_unsigned_out != nullptr) { + *has_unsigned_out = false; + } + if (has_signed_out != nullptr) { + *has_signed_out = false; + } if (fetch.type != 2) { XELOGGPU("Texture fetch type is not 2 - ignoring!"); @@ -940,25 +1056,40 @@ void TextureCache::TextureKeyFromFetchConstant( key_out.format = format; key_out.endianness = Endian(fetch.endianness); - uint32_t swizzle = fetch.swizzle; - const uint32_t swizzle_constant_mask = 4 | (4 << 3) | (4 << 6) | (4 << 9); - uint32_t swizzle_constant = swizzle & swizzle_constant_mask; - uint32_t swizzle_not_constant = swizzle_constant ^ swizzle_constant_mask; - // Get rid of 6 and 7 values (to prevent device losses if the game has - // something broken) the quick and dirty way - by changing them to 4 and 5. - swizzle &= ~(swizzle_constant >> 1); - // Remap the swizzle according to the texture format. k_1_5_5_5, k_5_6_5 and - // k_4_4_4_4 already have red and blue swapped in the load shader for - // simplicity. - if (format == TextureFormat::k_DXT3A || format == TextureFormat::k_DXT5A) { - // DXT3A is emulated as R8, DXT5A is emulated as BC4 or (for unaligned size) - // R8, but DXT5 alpha (in the red component of R8 and BC4) should be - // replicated. - // http://fileadmin.cs.lth.se/cs/Personal/Michael_Doggett/talks/unc-xenos-doggett.pdf - // If not 0.0 or 1.0 (if the high bit isn't set), make 0 (red). - swizzle &= ~((swizzle_not_constant >> 1) | (swizzle_not_constant >> 2)); + if (swizzle_out != nullptr) { + uint32_t swizzle = fetch.swizzle; + const uint32_t swizzle_constant_mask = 4 | (4 << 3) | (4 << 6) | (4 << 9); + uint32_t swizzle_constant = swizzle & swizzle_constant_mask; + uint32_t swizzle_not_constant = swizzle_constant ^ swizzle_constant_mask; + // Get rid of 6 and 7 values (to prevent device losses if the game has + // something broken) the quick and dirty way - by changing them to 4 and 5. + swizzle &= ~(swizzle_constant >> 1); + // Remap the swizzle according to the texture format. k_1_5_5_5, k_5_6_5 and + // k_4_4_4_4 already have red and blue swapped in the load shader for + // simplicity. + if (format == TextureFormat::k_DXT3A || format == TextureFormat::k_DXT5A) { + // DXT3A is emulated as R8, DXT5A is emulated as BC4 or (for unaligned + // size) R8, but DXT5 alpha (in the red component of R8 and BC4) should be + // replicated. + // http://fileadmin.cs.lth.se/cs/Personal/Michael_Doggett/talks/unc-xenos-doggett.pdf + // If not 0.0 or 1.0 (if the high bit isn't set), make 0 (red). + swizzle &= ~((swizzle_not_constant >> 1) | (swizzle_not_constant >> 2)); + } + *swizzle_out = swizzle; + } + + if (has_unsigned_out != nullptr) { + *has_unsigned_out = TextureSign(fetch.sign_x) != TextureSign::kSigned || + TextureSign(fetch.sign_y) != TextureSign::kSigned || + TextureSign(fetch.sign_z) != TextureSign::kSigned || + TextureSign(fetch.sign_w) != TextureSign::kSigned; + } + if (has_signed_out != nullptr) { + *has_signed_out = TextureSign(fetch.sign_x) == TextureSign::kSigned || + TextureSign(fetch.sign_y) == TextureSign::kSigned || + TextureSign(fetch.sign_z) == TextureSign::kSigned || + TextureSign(fetch.sign_w) == TextureSign::kSigned; } - swizzle_out = swizzle; } void TextureCache::LogTextureKeyAction(TextureKey key, const char* action) { @@ -1001,9 +1132,10 @@ TextureCache::Texture* TextureCache::FindOrCreateTexture(TextureKey key) { // Create the resource. If failed to create one, don't create a texture object // at all so it won't be in indeterminate state. D3D12_RESOURCE_DESC desc; - desc.Format = GetDXGIFormat(key); + desc.Format = GetDXGIResourceFormat(key); if (desc.Format == DXGI_FORMAT_UNKNOWN) { - unsupported_formats_used_ |= 1ull << uint32_t(key.format); + unsupported_format_features_used_[uint32_t(key.format)] |= + kUnsupportedResourceBit; return nullptr; } if (key.dimension == Dimension::k3D) { diff --git a/src/xenia/gpu/d3d12/texture_cache.h b/src/xenia/gpu/d3d12/texture_cache.h index 9e0e0d991..fecd5556b 100644 --- a/src/xenia/gpu/d3d12/texture_cache.h +++ b/src/xenia/gpu/d3d12/texture_cache.h @@ -117,8 +117,7 @@ class TextureCache { const D3D12Shader::TextureSRV* texture_srvs, uint32_t texture_srv_count) const; - void WriteTextureSRV(uint32_t fetch_constant, - TextureDimension shader_dimension, + void WriteTextureSRV(const D3D12Shader::TextureSRV& texture_srv, D3D12_CPU_DESCRIPTOR_HANDLE handle); SamplerParameters GetSamplerParameters( @@ -165,6 +164,9 @@ class TextureCache { struct LoadModeInfo { const void* shader; size_t shader_size; + // TODO(Triang3l): Whether signed and integer textures need to be separate + // resources loaded differently than unorm textures (k_10_11_11, + // k_11_11_10 because they are expanded to R16G16B16A16). }; // Tiling modes for storing textures after resolving - needed only for the @@ -195,14 +197,26 @@ class TextureCache { struct HostFormat { // Format info for the regular case. - DXGI_FORMAT dxgi_format; + // DXGI format (typeless when different signedness or number representation + // is used) for the texture resource. + DXGI_FORMAT dxgi_format_resource; + // DXGI format for unsigned normalized or unsigned/signed float SRV. + DXGI_FORMAT dxgi_format_unorm; + // DXGI format for signed normalized or unsigned/signed float SRV. + DXGI_FORMAT dxgi_format_snorm; LoadMode load_mode; + + // TODO(Triang3l): Integer formats. + // Uncompression info for when the regular host format for this texture is // block-compressed, but the size is not block-aligned, and thus such // texture cannot be created in Direct3D on PC and needs decompression, - // however, such textures are common, for instance, in Halo 3. + // however, such textures are common, for instance, in Halo 3. This only + // supports unsigned normalized formats - let's hope GPUSIGN_SIGNED was not + // used for DXN and DXT5A. DXGI_FORMAT dxgi_format_uncompressed; LoadMode decompress_mode; + // For writing textures after resolving render targets. The format itself // must be renderable, because resolving is done by drawing a quad into a // texture of this format. @@ -351,6 +365,10 @@ class TextureCache { struct TextureBinding { TextureKey key; uint32_t swizzle; + // Whether the fetch has unsigned/biased/gamma components. + bool has_unsigned; + // Whether the fetch has signed components. + bool has_signed; Texture* texture; }; @@ -358,22 +376,35 @@ class TextureCache { // of block-compressed textures with 4x4-aligned dimensions on PC). static bool IsDecompressionNeeded(TextureFormat format, uint32_t width, uint32_t height); - static inline DXGI_FORMAT GetDXGIFormat(TextureFormat format, uint32_t width, - uint32_t height) { + static inline DXGI_FORMAT GetDXGIResourceFormat(TextureFormat format, + uint32_t width, + uint32_t height) { const HostFormat& host_format = host_formats_[uint32_t(format)]; return IsDecompressionNeeded(format, width, height) ? host_format.dxgi_format_uncompressed - : host_format.dxgi_format; + : host_format.dxgi_format_resource; } - static inline DXGI_FORMAT GetDXGIFormat(TextureKey key) { - return GetDXGIFormat(key.format, key.width, key.height); + static inline DXGI_FORMAT GetDXGIResourceFormat(TextureKey key) { + return GetDXGIResourceFormat(key.format, key.width, key.height); + } + static inline DXGI_FORMAT GetDXGIUnormFormat(TextureFormat format, + uint32_t width, + uint32_t height) { + const HostFormat& host_format = host_formats_[uint32_t(format)]; + return IsDecompressionNeeded(format, width, height) + ? host_format.dxgi_format_uncompressed + : host_format.dxgi_format_unorm; + } + static inline DXGI_FORMAT GetDXGIUnormFormat(TextureKey key) { + return GetDXGIUnormFormat(key.format, key.width, key.height); } // Converts a texture fetch constant to a texture key, normalizing and - // validating the values, or creating an invalid key. - static void TextureKeyFromFetchConstant( + // validating the values, or creating an invalid key, and also gets the + // swizzle and used signedness. + static void BindingInfoFromFetchConstant( const xenos::xe_gpu_texture_fetch_t& fetch, TextureKey& key_out, - uint32_t& swizzle_out); + uint32_t* swizzle_out, bool* has_unsigned_out, bool* has_signed_out); static void LogTextureKeyAction(TextureKey key, const char* action); static void LogTextureAction(const Texture* texture, const char* action); @@ -426,7 +457,12 @@ class TextureCache { // Unsupported texture formats used during this frame (for research and // testing). - uint64_t unsupported_formats_used_; + enum : uint8_t { + kUnsupportedResourceBit = 1, + kUnsupportedUnormBit = kUnsupportedResourceBit << 1, + kUnsupportedSnormBit = kUnsupportedUnormBit << 1, + }; + uint8_t unsupported_format_features_used_[64]; }; } // namespace d3d12 diff --git a/src/xenia/gpu/dxbc_shader_translator.h b/src/xenia/gpu/dxbc_shader_translator.h index 25dea4017..9e84772b5 100644 --- a/src/xenia/gpu/dxbc_shader_translator.h +++ b/src/xenia/gpu/dxbc_shader_translator.h @@ -87,9 +87,9 @@ class DxbcShaderTranslator : public ShaderTranslator { uint32_t color_output_map[4]; }; - // 96 textures at most because there are 32 fetch constants, and textures can - // be 2D array, 3D or cube. - static constexpr uint32_t kMaxTextureSRVIndexBits = 7; + // 192 textures at most because there are 32 fetch constants, and textures can + // be 2D array, 3D or cube, and also signed and unsigned. + static constexpr uint32_t kMaxTextureSRVIndexBits = 8; static constexpr uint32_t kMaxTextureSRVs = (1 << kMaxTextureSRVIndexBits) - 1; struct TextureSRV {