[D3D12] Signed texture SRVs

This commit is contained in:
Triang3l 2018-10-09 21:44:18 +03:00
parent 7603de218b
commit 7bc79cbd01
5 changed files with 345 additions and 181 deletions

View File

@ -2196,8 +2196,7 @@ bool D3D12CommandProcessor::UpdateBindings(
gpu_handle_textures_vertex_ = view_gpu_handle; gpu_handle_textures_vertex_ = view_gpu_handle;
for (uint32_t i = 0; i < texture_count_vertex; ++i) { for (uint32_t i = 0; i < texture_count_vertex; ++i) {
const D3D12Shader::TextureSRV& srv = textures_vertex[i]; const D3D12Shader::TextureSRV& srv = textures_vertex[i];
texture_cache_->WriteTextureSRV(srv.fetch_constant, srv.dimension, texture_cache_->WriteTextureSRV(srv, view_cpu_handle);
view_cpu_handle);
view_cpu_handle.ptr += descriptor_size_view; view_cpu_handle.ptr += descriptor_size_view;
view_gpu_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; gpu_handle_textures_pixel_ = view_gpu_handle;
for (uint32_t i = 0; i < texture_count_pixel; ++i) { for (uint32_t i = 0; i < texture_count_pixel; ++i) {
const D3D12Shader::TextureSRV& srv = textures_pixel[i]; const D3D12Shader::TextureSRV& srv = textures_pixel[i];
texture_cache_->WriteTextureSRV(srv.fetch_constant, srv.dimension, texture_cache_->WriteTextureSRV(srv, view_cpu_handle);
view_cpu_handle);
view_cpu_handle.ptr += descriptor_size_view; view_cpu_handle.ptr += descriptor_size_view;
view_gpu_handle.ptr += descriptor_size_view; view_gpu_handle.ptr += descriptor_size_view;
} }

View File

@ -1740,11 +1740,9 @@ DXGI_FORMAT RenderTargetCache::GetColorDXGIFormat(
case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16: case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16:
return DXGI_FORMAT_R16G16B16A16_FLOAT; return DXGI_FORMAT_R16G16B16A16_FLOAT;
case ColorRenderTargetFormat::k_16_16: case ColorRenderTargetFormat::k_16_16:
// TODO(Triang3l): Change to SNORM when signed textures are supported. return DXGI_FORMAT_R16G16_SNORM;
return DXGI_FORMAT_R16G16_UNORM;
case ColorRenderTargetFormat::k_16_16_16_16: case ColorRenderTargetFormat::k_16_16_16_16:
// TODO(Triang3l): Change to SNORM when signed textures are supported. return DXGI_FORMAT_R16G16B16A16_SNORM;
return DXGI_FORMAT_R16G16B16A16_UNORM;
case ColorRenderTargetFormat::k_16_16_FLOAT: case ColorRenderTargetFormat::k_16_16_FLOAT:
return DXGI_FORMAT_R16G16_FLOAT; return DXGI_FORMAT_R16G16_FLOAT;
case ColorRenderTargetFormat::k_32_FLOAT: case ColorRenderTargetFormat::k_32_FLOAT:

View File

@ -50,209 +50,277 @@ namespace d3d12 {
const TextureCache::HostFormat TextureCache::host_formats_[64] = { const TextureCache::HostFormat TextureCache::host_formats_[64] = {
// k_1_REVERSE // k_1_REVERSE
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_1 // k_1
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_8 // k_8
{DXGI_FORMAT_R8_UNORM, LoadMode::k8bpb, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_R8_TYPELESS, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_SNORM,
LoadMode::kUnknown, DXGI_FORMAT_R8_UNORM, ResolveTileMode::k8bpp}, LoadMode::k8bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_R8_UNORM, ResolveTileMode::k8bpp},
// k_1_5_5_5 // 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, LoadMode::kUnknown, DXGI_FORMAT_R8G8B8A8_UNORM,
ResolveTileMode::k16bppRGBA}, ResolveTileMode::k16bppRGBA},
// k_5_6_5 // k_5_6_5
{DXGI_FORMAT_B5G6R5_UNORM, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_B5G6R5_UNORM, ResolveTileMode::k16bpp}, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_B5G6R5_UNORM, ResolveTileMode::k16bpp},
// k_6_5_5 // k_6_5_5
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_8_8_8_8 // 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}, LoadMode::kUnknown, DXGI_FORMAT_R8G8B8A8_UNORM, ResolveTileMode::k32bpp},
// k_2_10_10_10 // 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, LoadMode::kUnknown, DXGI_FORMAT_R10G10B10A2_UNORM,
ResolveTileMode::k32bpp}, ResolveTileMode::k32bpp},
// k_8_A // k_8_A
{DXGI_FORMAT_R8_UNORM, LoadMode::k8bpb, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_R8_TYPELESS, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_SNORM,
LoadMode::kUnknown, DXGI_FORMAT_R8_UNORM, ResolveTileMode::k8bpp}, LoadMode::k8bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_R8_UNORM, ResolveTileMode::k8bpp},
// k_8_B // k_8_B
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_8_8 // k_8_8
{DXGI_FORMAT_R8G8_UNORM, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_R8G8_TYPELESS, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_SNORM,
LoadMode::kUnknown, DXGI_FORMAT_R8G8_UNORM, ResolveTileMode::k16bpp}, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_R8G8_UNORM, ResolveTileMode::k16bpp},
// k_Cr_Y1_Cb_Y0_REP // k_Cr_Y1_Cb_Y0_REP
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_Y1_Cr_Y0_Cb_REP // k_Y1_Cr_Y0_Cb_REP
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_16_16_EDRAM // k_16_16_EDRAM
// Not usable as a texture, also has -32...32 range. // Not usable as a texture, also has -32...32 range.
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_8_8_8_8_A // k_8_8_8_8_A
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_4_4_4_4 // 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, LoadMode::kUnknown, DXGI_FORMAT_R8G8B8A8_UNORM,
ResolveTileMode::k16bppRGBA}, ResolveTileMode::k16bppRGBA},
// k_10_11_11 // k_10_11_11
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_11_11_10 // k_11_11_10
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_DXT1 // k_DXT1
{DXGI_FORMAT_BC1_UNORM, LoadMode::k64bpb, DXGI_FORMAT_R8G8B8A8_UNORM, {DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN,
LoadMode::kDXT1ToRGBA8, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::k64bpb, DXGI_FORMAT_R8G8B8A8_UNORM, LoadMode::kDXT1ToRGBA8,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_DXT2_3 // k_DXT2_3
{DXGI_FORMAT_BC2_UNORM, LoadMode::k128bpb, DXGI_FORMAT_R8G8B8A8_UNORM, {DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_UNKNOWN,
LoadMode::kDXT3ToRGBA8, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::k128bpb, DXGI_FORMAT_R8G8B8A8_UNORM, LoadMode::kDXT3ToRGBA8,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_DXT4_5 // k_DXT4_5
{DXGI_FORMAT_BC3_UNORM, LoadMode::k128bpb, DXGI_FORMAT_R8G8B8A8_UNORM, {DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_UNKNOWN,
LoadMode::kDXT5ToRGBA8, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::k128bpb, DXGI_FORMAT_R8G8B8A8_UNORM, LoadMode::kDXT5ToRGBA8,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_16_16_16_16_EDRAM // k_16_16_16_16_EDRAM
// Not usable as a texture, also has -32...32 range. // Not usable as a texture, also has -32...32 range.
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// R32_FLOAT for depth because shaders would require an additional SRV to // R32_FLOAT for depth because shaders would require an additional SRV to
// sample stencil, which we don't provide. // sample stencil, which we don't provide.
// k_24_8 // k_24_8
{DXGI_FORMAT_R32_FLOAT, LoadMode::kDepthUnorm, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kDepthUnorm, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_24_8_FLOAT // k_24_8_FLOAT
{DXGI_FORMAT_R32_FLOAT, LoadMode::kDepthFloat, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kDepthFloat, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_16 // k_16
{DXGI_FORMAT_R16_UNORM, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_SNORM,
LoadMode::kUnknown, DXGI_FORMAT_R16_UNORM, ResolveTileMode::k16bpp}, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_R16_UNORM, ResolveTileMode::k16bpp},
// k_16_16 // k_16_16
{DXGI_FORMAT_R16G16_UNORM, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, // TODO(Triang3l): Check if this is the correct way of specifying a signed
LoadMode::kUnknown, DXGI_FORMAT_R16G16_UNORM, ResolveTileMode::k32bpp}, // 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 // k_16_16_16_16
{DXGI_FORMAT_R16G16B16A16_UNORM, LoadMode::k64bpb, DXGI_FORMAT_UNKNOWN, // TODO(Triang3l): Check if this is the correct way of specifying a signed
LoadMode::kUnknown, DXGI_FORMAT_R16G16B16A16_UNORM, // 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}, ResolveTileMode::k64bpp},
// k_16_EXPAND // k_16_EXPAND
{DXGI_FORMAT_R16_FLOAT, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT,
LoadMode::kUnknown, DXGI_FORMAT_R16_FLOAT, ResolveTileMode::k16bpp}, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_R16_FLOAT, ResolveTileMode::k16bpp},
// k_16_16_EXPAND // 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}, LoadMode::kUnknown, DXGI_FORMAT_R16G16_FLOAT, ResolveTileMode::k32bpp},
// k_16_16_16_16_EXPAND // 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, LoadMode::kUnknown, DXGI_FORMAT_R16G16B16A16_FLOAT,
ResolveTileMode::k64bpp}, ResolveTileMode::k64bpp},
// k_16_FLOAT // k_16_FLOAT
{DXGI_FORMAT_R16_FLOAT, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT,
LoadMode::kUnknown, DXGI_FORMAT_R16_FLOAT, ResolveTileMode::k16bpp}, LoadMode::k16bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_R16_FLOAT, ResolveTileMode::k16bpp},
// k_16_16_FLOAT // 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}, LoadMode::kUnknown, DXGI_FORMAT_R16G16_FLOAT, ResolveTileMode::k32bpp},
// k_16_16_16_16_FLOAT // 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, LoadMode::kUnknown, DXGI_FORMAT_R16G16B16A16_FLOAT,
ResolveTileMode::k64bpp}, ResolveTileMode::k64bpp},
// k_32 // k_32
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_32_32 // k_32_32
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_32_32_32_32 // k_32_32_32_32
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_32_FLOAT // k_32_FLOAT
{DXGI_FORMAT_R32_FLOAT, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT,
LoadMode::kUnknown, DXGI_FORMAT_R32_FLOAT, ResolveTileMode::k32bpp}, LoadMode::k32bpb, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_R32_FLOAT, ResolveTileMode::k32bpp},
// k_32_32_FLOAT // 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}, LoadMode::kUnknown, DXGI_FORMAT_R32G32_FLOAT, ResolveTileMode::k64bpp},
// k_32_32_32_32_FLOAT // 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}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_32_AS_8 // k_32_AS_8
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_32_AS_8_8 // k_32_AS_8_8
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_16_MPEG // k_16_MPEG
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_16_16_MPEG // k_16_16_MPEG
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_8_INTERLACED // k_8_INTERLACED
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_32_AS_8_INTERLACED // k_32_AS_8_INTERLACED
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_32_AS_8_8_INTERLACED // k_32_AS_8_8_INTERLACED
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_16_INTERLACED // k_16_INTERLACED
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_16_MPEG_INTERLACED // k_16_MPEG_INTERLACED
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_16_16_MPEG_INTERLACED // k_16_16_MPEG_INTERLACED
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_DXN // k_DXN
{DXGI_FORMAT_BC5_UNORM, LoadMode::k128bpb, DXGI_FORMAT_R8G8_UNORM, {DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_UNKNOWN,
LoadMode::kDXNToRG8, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::k128bpb, DXGI_FORMAT_R8G8_UNORM, LoadMode::kDXNToRG8,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_8_8_8_8_AS_16_16_16_16 // 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}, LoadMode::kUnknown, DXGI_FORMAT_R8G8B8A8_UNORM, ResolveTileMode::k32bpp},
// k_DXT1_AS_16_16_16_16 // k_DXT1_AS_16_16_16_16
{DXGI_FORMAT_BC1_UNORM, LoadMode::k64bpb, DXGI_FORMAT_R8G8B8A8_UNORM, {DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN,
LoadMode::kDXT1ToRGBA8, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::k64bpb, DXGI_FORMAT_R8G8B8A8_UNORM, LoadMode::kDXT1ToRGBA8,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_DXT2_3_AS_16_16_16_16 // k_DXT2_3_AS_16_16_16_16
{DXGI_FORMAT_BC2_UNORM, LoadMode::k128bpb, DXGI_FORMAT_R8G8B8A8_UNORM, {DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_UNKNOWN,
LoadMode::kDXT3ToRGBA8, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::k128bpb, DXGI_FORMAT_R8G8B8A8_UNORM, LoadMode::kDXT3ToRGBA8,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_DXT4_5_AS_16_16_16_16 // k_DXT4_5_AS_16_16_16_16
{DXGI_FORMAT_BC3_UNORM, LoadMode::k128bpb, DXGI_FORMAT_R8G8B8A8_UNORM, {DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_UNKNOWN,
LoadMode::kDXT5ToRGBA8, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::k128bpb, DXGI_FORMAT_R8G8B8A8_UNORM, LoadMode::kDXT5ToRGBA8,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_2_10_10_10_AS_16_16_16_16 // 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, LoadMode::kUnknown, DXGI_FORMAT_R10G10B10A2_UNORM,
ResolveTileMode::k32bpp}, ResolveTileMode::k32bpp},
// k_10_11_11_AS_16_16_16_16 // k_10_11_11_AS_16_16_16_16
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_11_11_10_AS_16_16_16_16 // k_11_11_10_AS_16_16_16_16
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_32_32_32_FLOAT // k_32_32_32_FLOAT
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_DXT3A // k_DXT3A
{DXGI_FORMAT_R8_UNORM, LoadMode::kDXT3A, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kDXT3A, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_DXT5A // k_DXT5A
{DXGI_FORMAT_BC4_UNORM, LoadMode::k64bpb, DXGI_FORMAT_R8_UNORM, {DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_UNKNOWN,
LoadMode::kDXT5AToR8, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::k64bpb, DXGI_FORMAT_R8_UNORM, LoadMode::kDXT5AToR8,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_CTX1 // k_CTX1
{DXGI_FORMAT_R8G8_UNORM, LoadMode::kCTX1, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kCTX1, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_DXT3A_AS_1_1_1_1 // k_DXT3A_AS_1_1_1_1
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
// k_8_8_8_8_GAMMA // 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}, LoadMode::kUnknown, DXGI_FORMAT_R8G8B8A8_UNORM, ResolveTileMode::k32bpp},
// k_2_10_10_10_FLOAT_EDRAM // k_2_10_10_10_FLOAT_EDRAM
// Not usable as a texture. // Not usable as a texture.
{DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown}, LoadMode::kUnknown, DXGI_FORMAT_UNKNOWN, LoadMode::kUnknown,
DXGI_FORMAT_UNKNOWN, ResolveTileMode::kUnknown},
}; };
const char* const TextureCache::dimension_names_[4] = {"1D", "2D", "3D", const char* const TextureCache::dimension_names_[4] = {"1D", "2D", "3D",
@ -414,17 +482,27 @@ void TextureCache::BeginFrame() {
// is requested again. // is requested again.
ClearBindings(); ClearBindings();
unsupported_formats_used_ = 0; std::memset(unsupported_format_features_used_, 0,
sizeof(unsupported_format_features_used_));
} }
void TextureCache::EndFrame() { void TextureCache::EndFrame() {
if (unsupported_formats_used_ != 0) { // Report used unsupported texture formats.
XELOGE("Unsupported texture formats used in the frame:"); bool unsupported_header_written = false;
uint32_t format; for (uint32_t i = 0; i < 64; ++i) {
while (xe::bit_scan_forward(unsupported_formats_used_, &format)) { uint32_t unsupported_features = unsupported_format_features_used_[i];
unsupported_formats_used_ &= ~(1ull << format); if (unsupported_features == 0) {
XELOGE("* %s", FormatInfo::Get(TextureFormat(format))->name); 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 = auto group =
reinterpret_cast<const xenos::xe_gpu_fetch_group_t*>(&regs.values[r]); reinterpret_cast<const xenos::xe_gpu_fetch_group_t*>(&regs.values[r]);
TextureKey old_key = binding.key; TextureKey old_key = binding.key;
TextureKeyFromFetchConstant(group->texture_fetch, binding.key, BindingInfoFromFetchConstant(group->texture_fetch, binding.key,
binding.swizzle); &binding.swizzle, &binding.has_unsigned,
&binding.has_signed);
texture_keys_in_sync_ |= index_bit; texture_keys_in_sync_ |= index_bit;
if (binding.key.IsInvalid()) { if (binding.key.IsInvalid()) {
binding.texture = nullptr; binding.texture = nullptr;
@ -511,32 +590,59 @@ uint64_t TextureCache::GetDescriptorHashForActiveTextures(
// There can be multiple SRVs of the same texture. // There can be multiple SRVs of the same texture.
XXH64_update(&hash_state, &texture_srv.dimension, XXH64_update(&hash_state, &texture_srv.dimension,
sizeof(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 = const TextureBinding& binding =
texture_bindings_[texture_srv.fetch_constant]; texture_bindings_[texture_srv.fetch_constant];
XXH64_update(&hash_state, &binding.key, sizeof(binding.key)); XXH64_update(&hash_state, &binding.key, sizeof(binding.key));
XXH64_update(&hash_state, &binding.swizzle, sizeof(binding.swizzle)); 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); return XXH64_digest(&hash_state);
} }
void TextureCache::WriteTextureSRV(uint32_t fetch_constant, void TextureCache::WriteTextureSRV(const D3D12Shader::TextureSRV& texture_srv,
TextureDimension shader_dimension,
D3D12_CPU_DESCRIPTOR_HANDLE handle) { 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; 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) { if (desc.Format == DXGI_FORMAT_UNKNOWN) {
// A null descriptor must still have a valid format. // A null descriptor must still have a valid format.
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
resource = nullptr;
} }
// XE_GPU_SWIZZLE and D3D12_SHADER_COMPONENT_MAPPING are the same except for // XE_GPU_SWIZZLE and D3D12_SHADER_COMPONENT_MAPPING are the same except for
// one bit. // one bit.
desc.Shader4ComponentMapping = desc.Shader4ComponentMapping =
binding.swizzle | binding.swizzle |
D3D12_SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES; D3D12_SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES;
ID3D12Resource* resource = switch (texture_srv.dimension) {
binding.texture != nullptr ? binding.texture->resource : nullptr;
switch (shader_dimension) {
case TextureDimension::k3D: case TextureDimension::k3D:
desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;
desc.Texture3D.MostDetailedMip = 0; desc.Texture3D.MostDetailedMip = 0;
@ -810,7 +916,8 @@ bool TextureCache::RequestSwapTexture(D3D12_CPU_DESCRIPTOR_HANDLE handle,
auto& fetch = group->texture_fetch; auto& fetch = group->texture_fetch;
TextureKey key; TextureKey key;
uint32_t swizzle; 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) { if (key.base_page == 0 || key.dimension != Dimension::k2D) {
return false; return false;
} }
@ -823,7 +930,7 @@ bool TextureCache::RequestSwapTexture(D3D12_CPU_DESCRIPTOR_HANDLE handle,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
texture->state = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; texture->state = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc; 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.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srv_desc.Shader4ComponentMapping = srv_desc.Shader4ComponentMapping =
swizzle | swizzle |
@ -851,13 +958,22 @@ bool TextureCache::IsDecompressionNeeded(TextureFormat format, uint32_t width,
(height & (format_info->block_height - 1)) != 0; (height & (format_info->block_height - 1)) != 0;
} }
void TextureCache::TextureKeyFromFetchConstant( void TextureCache::BindingInfoFromFetchConstant(
const xenos::xe_gpu_texture_fetch_t& fetch, TextureKey& key_out, 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. // Reset the key and the swizzle.
key_out.MakeInvalid(); key_out.MakeInvalid();
swizzle_out = xenos::XE_GPU_SWIZZLE_0 | (xenos::XE_GPU_SWIZZLE_0 << 3) | if (swizzle_out != nullptr) {
(xenos::XE_GPU_SWIZZLE_0 << 6) | (xenos::XE_GPU_SWIZZLE_0 << 9); *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) { if (fetch.type != 2) {
XELOGGPU("Texture fetch type is not 2 - ignoring!"); XELOGGPU("Texture fetch type is not 2 - ignoring!");
@ -940,6 +1056,7 @@ void TextureCache::TextureKeyFromFetchConstant(
key_out.format = format; key_out.format = format;
key_out.endianness = Endian(fetch.endianness); key_out.endianness = Endian(fetch.endianness);
if (swizzle_out != nullptr) {
uint32_t swizzle = fetch.swizzle; uint32_t swizzle = fetch.swizzle;
const uint32_t swizzle_constant_mask = 4 | (4 << 3) | (4 << 6) | (4 << 9); const uint32_t swizzle_constant_mask = 4 | (4 << 3) | (4 << 6) | (4 << 9);
uint32_t swizzle_constant = swizzle & swizzle_constant_mask; uint32_t swizzle_constant = swizzle & swizzle_constant_mask;
@ -951,14 +1068,28 @@ void TextureCache::TextureKeyFromFetchConstant(
// k_4_4_4_4 already have red and blue swapped in the load shader for // k_4_4_4_4 already have red and blue swapped in the load shader for
// simplicity. // simplicity.
if (format == TextureFormat::k_DXT3A || format == TextureFormat::k_DXT5A) { if (format == TextureFormat::k_DXT3A || format == TextureFormat::k_DXT5A) {
// DXT3A is emulated as R8, DXT5A is emulated as BC4 or (for unaligned size) // DXT3A is emulated as R8, DXT5A is emulated as BC4 or (for unaligned
// R8, but DXT5 alpha (in the red component of R8 and BC4) should be // size) R8, but DXT5 alpha (in the red component of R8 and BC4) should be
// replicated. // replicated.
// http://fileadmin.cs.lth.se/cs/Personal/Michael_Doggett/talks/unc-xenos-doggett.pdf // 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). // 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 &= ~((swizzle_not_constant >> 1) | (swizzle_not_constant >> 2));
} }
swizzle_out = swizzle; *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;
}
} }
void TextureCache::LogTextureKeyAction(TextureKey key, const char* action) { 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 // Create the resource. If failed to create one, don't create a texture object
// at all so it won't be in indeterminate state. // at all so it won't be in indeterminate state.
D3D12_RESOURCE_DESC desc; D3D12_RESOURCE_DESC desc;
desc.Format = GetDXGIFormat(key); desc.Format = GetDXGIResourceFormat(key);
if (desc.Format == DXGI_FORMAT_UNKNOWN) { 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; return nullptr;
} }
if (key.dimension == Dimension::k3D) { if (key.dimension == Dimension::k3D) {

View File

@ -117,8 +117,7 @@ class TextureCache {
const D3D12Shader::TextureSRV* texture_srvs, const D3D12Shader::TextureSRV* texture_srvs,
uint32_t texture_srv_count) const; uint32_t texture_srv_count) const;
void WriteTextureSRV(uint32_t fetch_constant, void WriteTextureSRV(const D3D12Shader::TextureSRV& texture_srv,
TextureDimension shader_dimension,
D3D12_CPU_DESCRIPTOR_HANDLE handle); D3D12_CPU_DESCRIPTOR_HANDLE handle);
SamplerParameters GetSamplerParameters( SamplerParameters GetSamplerParameters(
@ -165,6 +164,9 @@ class TextureCache {
struct LoadModeInfo { struct LoadModeInfo {
const void* shader; const void* shader;
size_t shader_size; 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 // Tiling modes for storing textures after resolving - needed only for the
@ -195,14 +197,26 @@ class TextureCache {
struct HostFormat { struct HostFormat {
// Format info for the regular case. // 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; LoadMode load_mode;
// TODO(Triang3l): Integer formats.
// Uncompression info for when the regular host format for this texture is // Uncompression info for when the regular host format for this texture is
// block-compressed, but the size is not block-aligned, and thus such // block-compressed, but the size is not block-aligned, and thus such
// texture cannot be created in Direct3D on PC and needs decompression, // 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; DXGI_FORMAT dxgi_format_uncompressed;
LoadMode decompress_mode; LoadMode decompress_mode;
// For writing textures after resolving render targets. The format itself // For writing textures after resolving render targets. The format itself
// must be renderable, because resolving is done by drawing a quad into a // must be renderable, because resolving is done by drawing a quad into a
// texture of this format. // texture of this format.
@ -351,6 +365,10 @@ class TextureCache {
struct TextureBinding { struct TextureBinding {
TextureKey key; TextureKey key;
uint32_t swizzle; 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; Texture* texture;
}; };
@ -358,22 +376,35 @@ class TextureCache {
// of block-compressed textures with 4x4-aligned dimensions on PC). // of block-compressed textures with 4x4-aligned dimensions on PC).
static bool IsDecompressionNeeded(TextureFormat format, uint32_t width, static bool IsDecompressionNeeded(TextureFormat format, uint32_t width,
uint32_t height); uint32_t height);
static inline DXGI_FORMAT GetDXGIFormat(TextureFormat format, uint32_t width, static inline DXGI_FORMAT GetDXGIResourceFormat(TextureFormat format,
uint32_t width,
uint32_t height) { uint32_t height) {
const HostFormat& host_format = host_formats_[uint32_t(format)]; const HostFormat& host_format = host_formats_[uint32_t(format)];
return IsDecompressionNeeded(format, width, height) return IsDecompressionNeeded(format, width, height)
? host_format.dxgi_format_uncompressed ? host_format.dxgi_format_uncompressed
: host_format.dxgi_format; : host_format.dxgi_format_resource;
} }
static inline DXGI_FORMAT GetDXGIFormat(TextureKey key) { static inline DXGI_FORMAT GetDXGIResourceFormat(TextureKey key) {
return GetDXGIFormat(key.format, key.width, key.height); 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 // Converts a texture fetch constant to a texture key, normalizing and
// validating the values, or creating an invalid key. // validating the values, or creating an invalid key, and also gets the
static void TextureKeyFromFetchConstant( // swizzle and used signedness.
static void BindingInfoFromFetchConstant(
const xenos::xe_gpu_texture_fetch_t& fetch, TextureKey& key_out, 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 LogTextureKeyAction(TextureKey key, const char* action);
static void LogTextureAction(const Texture* texture, 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 // Unsupported texture formats used during this frame (for research and
// testing). // 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 } // namespace d3d12

View File

@ -87,9 +87,9 @@ class DxbcShaderTranslator : public ShaderTranslator {
uint32_t color_output_map[4]; uint32_t color_output_map[4];
}; };
// 96 textures at most because there are 32 fetch constants, and textures can // 192 textures at most because there are 32 fetch constants, and textures can
// be 2D array, 3D or cube. // be 2D array, 3D or cube, and also signed and unsigned.
static constexpr uint32_t kMaxTextureSRVIndexBits = 7; static constexpr uint32_t kMaxTextureSRVIndexBits = 8;
static constexpr uint32_t kMaxTextureSRVs = static constexpr uint32_t kMaxTextureSRVs =
(1 << kMaxTextureSRVIndexBits) - 1; (1 << kMaxTextureSRVIndexBits) - 1;
struct TextureSRV { struct TextureSRV {