From b7b335ac632d63be3c8a5f64339950bfc99cac8d Mon Sep 17 00:00:00 2001 From: nmzik Date: Sat, 10 Oct 2026 23:47:47 +0200 Subject: [PATCH] gpu: admit block-compressed textures in PS5 R64 tiling --- src/graphics/guest_gpu/tile.cpp | 4 +- tests/ShaderRecompilerComputeTests.cpp | 58 +++++++++++++++++++------- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/graphics/guest_gpu/tile.cpp b/src/graphics/guest_gpu/tile.cpp index 3d07ae06..7043ca40 100644 --- a/src/graphics/guest_gpu/tile.cpp +++ b/src/graphics/guest_gpu/tile.cpp @@ -299,8 +299,8 @@ bool TileGetTextureBlockLayout(Prospero::BufferFormat format, Prospero::TileMode if (!TileGetTextureElementLayout(format, element)) { return false; } - if ((family == TileBlockFamily::Depth64KB || family == TileBlockFamily::RenderTarget64KB) && - Prospero::RenderTargetBytesPerElement(format) != element.bytes) { + if (family == TileBlockFamily::Depth64KB && + (element.texel_width != 1 || element.texel_height != 1)) { return false; } diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index e8aa0e55..bb6d3339 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -17744,39 +17744,47 @@ public: } // Exercise the real texture-layout/info-building seam for every format - // admitted by each standard tile mode. Formats sharing a byte/block width + // admitted by each texture tile mode. Formats sharing a byte/block width // intentionally share a shader, but this loop still validates their // texel-to-element conversion (notably every BCn format). - struct StandardMode { + struct TextureMode { Prospero::TileMode tile; TileBlockFamily family; }; - constexpr StandardMode standard_modes[] = { + constexpr TextureMode texture_modes[] = { {Prospero::TileMode::kStandard256B, TileBlockFamily::Standard256B}, {Prospero::TileMode::kStandard4KB, TileBlockFamily::Standard4KB}, {Prospero::TileMode::kStandard64KB, TileBlockFamily::Standard64KB}, {Prospero::TileMode::kPrt, TileBlockFamily::Prt64KB}, + {Prospero::TileMode::kRenderTarget, TileBlockFamily::RenderTarget64KB}, + {Prospero::TileMode::kDepth, TileBlockFamily::Depth64KB}, }; - struct RenderTargetFormatCase { + struct TextureTileFormatCase { Prospero::BufferFormat format; u32 bytes_per_element; + bool depth_supported; }; - constexpr RenderTargetFormatCase render_target_formats[] = { - {Prospero::BufferFormat::k8Srgb, 1}, - {Prospero::BufferFormat::k8_8Srgb, 2}, - {Prospero::BufferFormat::k9_9_9_5Float, 0}, + constexpr TextureTileFormatCase texture_tile_formats[] = { + {Prospero::BufferFormat::k8Srgb, 1, true}, + {Prospero::BufferFormat::k8_8Srgb, 2, true}, + {Prospero::BufferFormat::k9_9_9_5Float, 4, true}, + {Prospero::BufferFormat::kBc1Srgb, 8, false}, + {Prospero::BufferFormat::kBc7Srgb, 16, false}, + {Prospero::BufferFormat::k32_32_32_32Float, 16, false}, }; - for (const auto &test : render_target_formats) { + for (const auto &test : texture_tile_formats) { for (const auto tile : {Prospero::TileMode::kDepth, Prospero::TileMode::kRenderTarget}) { TileTextureBlockLayout texture{}; const bool supported = TileGetTextureBlockLayout(test.format, tile, false, texture); - Require(name, "RT format policy", - supported == (test.bytes_per_element != 0) && + const bool expected = tile == Prospero::TileMode::kRenderTarget || + test.depth_supported; + Require(name, "texture tile format policy", + supported == expected && (!supported || texture.block.bytes_per_element == test.bytes_per_element), - "RT/depth tile format support or element size is incorrect"); + "texture tile policy used attachment format restrictions"); } } { @@ -17809,7 +17817,7 @@ public: if (Prospero::IsFmaskTextureFormat(format)) { continue; } - for (const auto &mode : standard_modes) { + for (const auto &mode : texture_modes) { TileTextureBlockLayout texture{}; if (!TileGetTextureBlockLayout(format, mode.tile, false, texture)) { continue; @@ -17846,7 +17854,27 @@ public: } } Require(name, "format coverage", format_cases != 0, - "no CPU-supported standard formats were tested"); + "no CPU-supported texture formats were tested"); + + { + constexpr auto format = Prospero::BufferFormat::kBc1Srgb; + constexpr auto tile = Prospero::TileMode::kRenderTarget; + constexpr u32 layers = 8; + const auto captured = + MakeTilingImage(format, 2048, 2048, 1, layers, tile, 0, false); + Require(name, "PPSA19577 BC1 array footprint", + captured.data.size == 0x1000000 && + captured.tiled_slice_stride == 0x200000 && + captured.first_tail_level == 1 && + captured.tiling.block.block_width == 128 && + captured.tiling.block.block_height == 64 && + captured.mip_layout[0].pitch == 512 && + captured.mip_layout[0].height == 512, + "R64 BC1 texture lost its compressed blocks or array stride"); + const auto small = + MakeTilingImage(format, 67, 51, 1, layers, tile, 0, false); + check_round_trip("R64 BC1 array", small.data.size, small); + } { constexpr auto format = Prospero::BufferFormat::k11_11_10UInt; @@ -17949,7 +17977,7 @@ public: check_round_trip("array", total.size, layout); } - for (const auto &mode : standard_modes) { + for (const auto &mode : texture_modes) { constexpr auto format = Prospero::BufferFormat::k32Float; constexpr u32 levels = 2; TileBlockLayout block{};