diff --git a/src/graphics/guest_gpu/tile.cpp b/src/graphics/guest_gpu/tile.cpp index 0c2cb86bd..39da3a093 100644 --- a/src/graphics/guest_gpu/tile.cpp +++ b/src/graphics/guest_gpu/tile.cpp @@ -1238,38 +1238,6 @@ bool TileGetDccSize(uint32_t width, uint32_t height, uint32_t slices, return true; } -bool TileGetRenderTargetMipLayout(uint32_t width, uint32_t height, uint32_t pitch, - uint32_t bytes_per_element, uint32_t levels, - TileSizeAlign& total_size, TileSizeOffset* level_sizes, - TilePaddedSize* padded_size) { - total_size = {}; - if (width == 0 || height == 0 || levels == 0 || levels > 16 || - pitch != TileGetRenderTargetPitch(width, bytes_per_element)) { - return false; - } - uint32_t max_levels = 1; - uint32_t max_dimension = std::max(width, height); - while (max_dimension > 1) { - max_dimension >>= 1u; - max_levels++; - } - if (levels > max_levels) { - return false; - } - auto format = Prospero::BufferFormat::kInvalid; - switch (bytes_per_element) { - case 1: format = Prospero::BufferFormat::k8UNorm; break; - case 2: format = Prospero::BufferFormat::k16UNorm; break; - case 4: format = Prospero::BufferFormat::k32Float; break; - case 8: format = Prospero::BufferFormat::k16_16_16_16Float; break; - case 16: format = Prospero::BufferFormat::k32_32_32_32Float; break; - default: return false; - } - TileGetTextureSize(format, width, height, levels, Prospero::TileMode::kRenderTarget, - &total_size, level_sizes, padded_size); - return total_size.size != 0 && total_size.align == 65536; -} - void TileGetTextureSize(Prospero::BufferFormat format, uint32_t width, uint32_t height, uint32_t levels, Prospero::TileMode tile, TileSizeAlign* total_size, TileSizeOffset* level_sizes, TilePaddedSize* padded_size) { diff --git a/src/graphics/guest_gpu/tile.h b/src/graphics/guest_gpu/tile.h index e259dc63d..cac2f5e74 100644 --- a/src/graphics/guest_gpu/tile.h +++ b/src/graphics/guest_gpu/tile.h @@ -126,10 +126,6 @@ bool TileGetRenderTargetSize(uint32_t width, uint32_t height, uint32_t pitch bool TileGetDccSize(uint32_t width, uint32_t height, uint32_t slices, uint32_t bytes_per_element, uint32_t levels, Prospero::TileMode tile, TileSizeAlign& total_size, uint32_t num_fragments_log2 = 0); -bool TileGetRenderTargetMipLayout(uint32_t width, uint32_t height, uint32_t pitch, - uint32_t bytes_per_element, uint32_t levels, - TileSizeAlign& total_size, TileSizeOffset* level_sizes, - TilePaddedSize* padded_size); void TileGetTextureSize(Prospero::BufferFormat format, uint32_t width, uint32_t height, uint32_t levels, Prospero::TileMode tile, TileSizeAlign* total_size, TileSizeOffset* level_sizes, TilePaddedSize* padded_size); diff --git a/src/graphics/host_gpu/renderer/colorRenderTarget.cpp b/src/graphics/host_gpu/renderer/colorRenderTarget.cpp index 9c4877cad..4d7c3736b 100644 --- a/src/graphics/host_gpu/renderer/colorRenderTarget.cpp +++ b/src/graphics/host_gpu/renderer/colorRenderTarget.cpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace Libs::Graphics { @@ -200,8 +201,7 @@ void RenderExecutor::ResolveRenderColorTarget(CommandBuffer& buffer, RenderColor " layer=%u/%u\n", rt.attrib3.dimension, rt.attrib3.depth, view.base_layer, view.image_layers); } - // PPSA28068: the linear EULA target and its sampled view must share the padded pitch. - if (!tile || volume || texture_tile) { + if (samples == 1) { pitch = TileGetTexturePitch(transfer_format, width, rt.attrib3.tile_mode); } else { pitch = TileGetRenderTargetPitch(width, bytes_per_element, rt.attrib.num_fragments); @@ -232,28 +232,23 @@ void RenderExecutor::ResolveRenderColorTarget(CommandBuffer& buffer, RenderColor } else { TileSizeAlign layout {}; bool valid_layout = false; - if (!tile || texture_tile) { + if (samples == 1) { TileGetTextureSize(transfer_format, width, height, levels, rt.attrib3.tile_mode, &layout, mip_sizes, mip_padded); - const auto alignment = tile ? texture_tile_layout.block.block_size : 256u; - valid_layout = layout.size != 0 && layout.align == alignment; + valid_layout = layout.size != 0 && layout.align != 0 && + (rt.attrib3.tile_mode != Prospero::TileMode::kRenderTarget || + levels <= std::bit_width(std::max(width, height))); } else { - valid_layout = - levels == 1 ? TileGetRenderTargetSize(width, height, pitch, bytes_per_element, - layout, rt.attrib.num_fragments) - : TileGetRenderTargetMipLayout(width, height, pitch, bytes_per_element, - levels, layout, mip_sizes, mip_padded); + valid_layout = TileGetRenderTargetSize(width, height, pitch, bytes_per_element, + layout, rt.attrib.num_fragments); + mip_sizes[0] = {layout.size, 0, 0, 0, 0, 0}; + mip_padded[0] = {pitch, height}; } if (!valid_layout) { EXIT("unsupported render-target layout: %ux%u pitch=%u bytes=%u levels=%u\n", width, height, pitch, bytes_per_element, levels); } size = layout.size; - EXIT_IF(size > UINT32_MAX); - if (levels == 1) { - mip_sizes[0] = {static_cast(size), 0, 0, 0, 0, 0}; - mip_padded[0] = {pitch, height}; - } } if (size == 0 || (!volume && size > UINT64_MAX / view.image_layers)) { EXIT("render-target memory footprint is invalid\n"); diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 6c2cceffe..a2f4cf8bc 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -8328,6 +8328,8 @@ public: TargetCase{1440, 720, 1, 1472, 0x40b000, Prospero::TileMode::kLinear}, // PPSA01416: linear RGBA16F chains place the smallest mip first. TargetCase{128, 128, 1, 128, 0x2be00, Prospero::TileMode::kLinear, 7, true}, + // PPSA03541: the single texel still occupies a padded 128x64 block. + TargetCase{1, 1, 1, 128, 0x10000, Prospero::TileMode::kRenderTarget, 1, true}, }; constexpr uint64_t allocation_size = 0x410000; @@ -8409,6 +8411,12 @@ public: rendering.num_color_attachments == 1, "color attachment lost its dimensions or padded guest layout"); + if (width == 1 && height == 1) { + Require(name, "single-texel tiled layout", + color.desc.info.mip_layout[0] == ImageMipInfo{0, 0x10000, 128, 64}, + "the render target lost the SDK's padded block height"); + } + if (target.levels == 7) { constexpr std::array offsets{0xbe00u, 0x3e00u, 0x1e00u, 0xe00u, 0x600u, 0x200u, 0u}; @@ -8422,7 +8430,7 @@ public: } } - if (target.tile == Prospero::TileMode::kLinear) { + { vk::ClearValue clear{}; clear.color.float32 = std::array{1.0f, 0.0f, 1.0f, 1.0f}; TextureCacheTestAccess::ClearImage( @@ -8437,7 +8445,9 @@ public: (((width - 1u) & 3u) << 30u), ((width - 1u) >> 2u) | ((height - 1u) << 14u), DstSel(4, 5, 6, 7) | ((target.levels - 1) << 16u) | - (static_cast(Prospero::ImageType::kColor2D) << 28u), + (static_cast(target.tile) << 20u) | + (static_cast(is_1d ? Prospero::ImageType::kColor1D + : Prospero::ImageType::kColor2D) << 28u), 0, 0x00700000u | ((target.levels - 1) << 4u), 0, 0}}; ShaderRecompiler::IR::DescriptorValue value{}; value.dword_count = 8; @@ -8445,27 +8455,28 @@ public: ShaderRecompiler::IR::ImageResource resource{}; resource.resource_class = ShaderRecompiler::IR::ImageResourceClass::Sampled; resource.numeric_class = Prospero::TextureNumericClass::Float; - resource.dimension = ShaderRecompiler::Decoder::ImageDimension::Dim2D; + resource.dimension = is_1d ? ShaderRecompiler::Decoder::ImageDimension::Dim1D + : ShaderRecompiler::Decoder::ImageDimension::Dim2D; resource.read = true; const auto sampled = RenderExecutorTestAccess::ResolveTexture(executor, resource, value); - Require(name, "linear target sampled alias", + Require(name, "target sampled alias", sampled.image_id == color.image_id && sampled.desc.info.pitch == target.pitch && sampled.desc.info.data.size == target.size && sampled.desc.info.mip_layout == color.desc.info.mip_layout && texture_cache.FindTexture(sampled.image_id, sampled.desc) != nullptr, - "sampling the linear target created a second image"); + "sampling the target changed its padded layout or created a second image"); const auto expected = target.float16 ? std::vector{0x00003c00u, 0x3c003c00u} : std::vector{0xffff00ffu}; for (uint32_t mip = 0; mip < target.levels; ++mip) { - Require(name, "linear target sampled contents", + Require(name, "target sampled contents", ReadCachedTexel(name, context, sampled.image_id, {static_cast((width >> mip) - 1), static_cast((height >> mip) - 1), 0}, {1, 1, 1}, 0, mip) == expected, - "the sampled linear target lost its GPU-written final texel"); + "the sampled target lost its GPU-written final texel"); } }