renderer: decode R8, R8G8 and R16_UINT color register clears (#1893)

DecodePackedColorClear had no case for R8_UNORM/UINT, R8G8_UNORM/UINT and
R16_UINT, so a CMASK fast clear of such a render target was dropped and the
target kept its old contents. UFC 6 (PPSA23566) fast-clears an R8_UINT
region map this way every frame and then writes only part of it; a capture
showed the map never cleared. DWORD fills of these formats are decoded only
when every pixel in the word holds the same value.

Co-authored-by: 4wgycvn84p-afk <346802885+4wgycvn84p-afk@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
4wgycvn84p-afk
2026-10-25 18:47:45 +01:00
committed by GitHub
parent 99044c7c49
commit b2c9ec7609
2 changed files with 46 additions and 1 deletions
+25
View File
@@ -12274,6 +12274,8 @@ public:
PackedCase{vk::Format::eR16G16Unorm, 0x0000ffffu, {1.0f, 0.0f}},
PackedCase{vk::Format::eR16G16Unorm, 0x80000001u,
{1.0f / 65535.0f, 32768.0f / 65535.0f}},
PackedCase{vk::Format::eR8Unorm, 0xffffff80u, {128.0f / 255.0f}},
PackedCase{vk::Format::eR8G8Unorm, 0xffff40ffu, {1.0f, 64.0f / 255.0f}},
};
for (const auto &test : packed_cases) {
vk::ClearColorValue clear{};
@@ -12300,6 +12302,29 @@ public:
DecodeColorDwordFill(format, 0x3c003c00u, clear),
"alternating R16 pixels were treated as a uniform clear");
}
struct UintCase {
vk::Format format;
uint64_t word;
std::array<uint32_t, 4> channels;
};
for (const auto &test : {UintCase{vk::Format::eR8Uint, 0xffffff05u, {5u}},
UintCase{vk::Format::eR8G8Uint, 0xffff0a05u, {5u, 10u}},
UintCase{vk::Format::eR16Uint, 0xffff1234u, {0x1234u}}}) {
Require(name, "packed unsigned color clear",
DecodePackedColorClear(test.format, test.word, clear) &&
std::bit_cast<std::array<uint32_t, 4>>(clear.uint32) == test.channels,
"narrow unsigned clear lost a channel or kept bits of the next one");
}
Require(name, "R8 DWORD fill",
!DecodeColorDwordFill(vk::Format::eR8Uint, 0x01020304u, clear) &&
DecodeColorDwordFill(vk::Format::eR8Uint, 0x07070707u, clear) &&
clear.uint32[0] == 7u,
"differing R8 pixels were treated as a uniform clear");
Require(name, "RG8 DWORD fill",
!DecodeColorDwordFill(vk::Format::eR8G8Unorm, 0x00ff00feu, clear) &&
DecodeColorDwordFill(vk::Format::eR8G8Unorm, 0x00ff00ffu, clear) &&
clear.float32[0] == 1.0f && clear.float32[1] == 0.0f,
"alternating RG8 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,