[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;
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;
}

View File

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

View File

@ -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<const xenos::xe_gpu_fetch_group_t*>(&regs.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) {

View File

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

View File

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