From 3c9da9c3f4ce2a1ae0e0bc9abbfcfa4f3b334922 Mon Sep 17 00:00:00 2001 From: Ali Almohaya Date: Tue, 13 Oct 2026 04:40:42 +0200 Subject: [PATCH] graphics: decode both channels of RG32 float metadata clears --- src/graphics/host_gpu/renderer/image/imageInfo.h | 9 +++++---- tests/ShaderRecompilerComputeTests.cpp | 14 +++++++++++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/graphics/host_gpu/renderer/image/imageInfo.h b/src/graphics/host_gpu/renderer/image/imageInfo.h index 03f5c91b..a5dcc345 100644 --- a/src/graphics/host_gpu/renderer/image/imageInfo.h +++ b/src/graphics/host_gpu/renderer/image/imageInfo.h @@ -454,9 +454,10 @@ inline constexpr std::array VIDEO_OUT_FORMAT_POLICIES { case vk::Format::eR16Unorm: next.float32[0] = static_cast(packed & 0xffffu) / 65535.0f; break; - // A single-plane float target carries its clear as raw float bits, the same encoding the - // depth decoder below uses. Without this the clear is discarded and the target keeps stale - // contents. + // Each clear register stores one raw 32-bit float channel. + case vk::Format::eR32G32Sfloat: + next.float32[1] = std::bit_cast(static_cast(clear_words >> 32u)); + [[fallthrough]]; case vk::Format::eR32Sfloat: next.float32[0] = std::bit_cast(packed); break; case vk::Format::eR32Uint: next.uint32[0] = packed; break; case vk::Format::eR32Sint: next.int32[0] = static_cast(packed); break; @@ -517,7 +518,7 @@ inline constexpr std::array VIDEO_OUT_FORMAT_POLICIES { clear = vk::ClearColorValue {}; return true; } - return DecodePackedColorClear(format, packed, clear); + return DecodePackedColorClear(format, uint64_t {packed} | (uint64_t {packed} << 32u), clear); } [[nodiscard]] inline bool DecodePackedStencilClear(uint32_t packed, uint8_t& clear) { diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index be579763..7a773efb 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -10869,6 +10869,9 @@ public: std::array channels; }; const std::array packed_cases{ + PackedCase{vk::Format::eR32G32Sfloat, 0xbf8000003f800000ull, {1.0f, -1.0f}}, + PackedCase{vk::Format::eR32G32Sfloat, 0x7f80000080000000ull, + {-0.0f, std::numeric_limits::infinity()}}, PackedCase{vk::Format::eB10G11R11UfloatPack32, 0u, {}}, PackedCase{vk::Format::eB10G11R11UfloatPack32, 0x801c03c0u, {1.0f, 0.5f, 2.0f}}, PackedCase{vk::Format::eB10G11R11UfloatPack32, 1u | (0x7bfu << 11u) | (1u << 22u), @@ -10918,6 +10921,10 @@ public: DecodeColorDwordFill(format, 0x3c003c00u, clear), "alternating R16 pixels were treated as a uniform clear"); } + Require(name, "RG32 DWORD fill", + DecodeColorDwordFill(vk::Format::eR32G32Sfloat, 0x3f800000u, clear) && + clear.float32[0] == 1.0f && clear.float32[1] == 1.0f, + "a repeated DWORD fill was decoded as a two-register clear"); constexpr uintptr_t base = 0x0000000204100000ull; constexpr uint64_t allocation_size = 0x400000; constexpr uint64_t allocation_alignment = 0x10000; @@ -10947,6 +10954,10 @@ public: .layout = Prospero::ChannelLayout::k11_11_10, .eliminate_fast_clear = true}, FillCase{.fill = 0, .texel = {0x801c03c0u, 0}, .cmask = true, .layout = Prospero::ChannelLayout::k11_11_10, .eliminate_fast_clear = true}, + FillCase{.fill = 0, .texel = {0, 0}, .cmask = true, + .layout = Prospero::ChannelLayout::k32_32, .eliminate_fast_clear = true}, + FillCase{.fill = 0, .texel = {0x3f800000u, 0xbf800000u}, .cmask = true, + .layout = Prospero::ChannelLayout::k32_32, .eliminate_fast_clear = true}, FillCase{0x40404040u, {0, 0x3c000000u}, false, false, true}, FillCase{.fill = 0x20202020u, .texel = {0x7bff7bffu}, .layout = Prospero::ChannelLayout::k16, .clear_word = 0x7bff7bffu}, @@ -11159,7 +11170,8 @@ public: texture_cache.FindTexture(color.image_id, sampled) != nullptr, "FCE failed to retain the sampled allocation"); const std::vector stale = layout == Prospero::ChannelLayout::k11_11_10 - ? std::vector{0x780003c0u} : std::vector{0x00003c00u, 0x3c003c00u}; + ? std::vector{0x780003c0u} : layout == Prospero::ChannelLayout::k32_32 + ? std::vector{0x3f800000u, 0u} : std::vector{0x00003c00u, 0x3c003c00u}; Require(name, "FCE before graphics shader or target binding", ReadCachedTexel(name, context, color.image_id, {}, {1, 1, 1}, 1) == expected && ReadCachedTexel(name, context, color.image_id, {511, 255, 0},