graphics: decode register clears of RGBA16 UNORM, UINT and SINT and RG32 UINT and SINT targets

Co-authored-by: Senaxx <michelbeld@gmail.com>
Co-authored-by: Jetsku <59046009+Jetsku@users.noreply.github.com>
This commit is contained in:
committed 2026-10-26 07:43:11 +01:00
1 parent 17a0f53d39
commit f90a8b1589
2 files changed
+43 -10

No files matched your search

@@ -378,6 +378,9 @@ inline constexpr std::array<VideoOutFormatPolicy, 8> VIDEO_OUT_FORMAT_POLICIES {
const auto encoded = static_cast<float>(value & 0xffu) / 255.0f; const auto encoded = static_cast<float>(value & 0xffu) / 255.0f;
return encoded <= 0.04045f ? encoded / 12.92f : std::pow((encoded + 0.055f) / 1.055f, 2.4f); return encoded <= 0.04045f ? encoded / 12.92f : std::pow((encoded + 0.055f) / 1.055f, 2.4f);
}; };
const auto unorm16 = [](uint64_t value) {
return static_cast<float>(value & 0xffffu) / 65535.0f;
};
const auto float16 = [](uint32_t value) { const auto float16 = [](uint32_t value) {
const auto sign = (value & 0x8000u) << 16u; const auto sign = (value & 0x8000u) << 16u;
const auto exponent = (value >> 10u) & 0x1fu; const auto exponent = (value >> 10u) & 0x1fu;
@@ -403,19 +406,35 @@ inline constexpr std::array<VideoOutFormatPolicy, 8> VIDEO_OUT_FORMAT_POLICIES {
next.float32[1] = float16(packed >> 16u); next.float32[1] = float16(packed >> 16u);
[[fallthrough]]; [[fallthrough]];
case vk::Format::eR16Sfloat: next.float32[0] = float16(packed); break; case vk::Format::eR16Sfloat: next.float32[0] = float16(packed); break;
case vk::Format::eR16G16Unorm: case vk::Format::eR16G16B16A16Unorm:
next.float32[1] = static_cast<float>(packed >> 16u) / 65535.0f; next.float32[2] = unorm16(clear_words >> 32u);
next.float32[3] = unorm16(clear_words >> 48u);
[[fallthrough]]; [[fallthrough]];
case vk::Format::eR16Unorm: case vk::Format::eR16G16Unorm:
next.float32[0] = static_cast<float>(packed & 0xffffu) / 65535.0f; next.float32[1] = unorm16(packed >> 16u);
[[fallthrough]];
case vk::Format::eR16Unorm: next.float32[0] = unorm16(packed); break;
case vk::Format::eR16G16B16A16Uint:
for (uint32_t i = 0; i < 4; i++) {
next.uint32[i] = static_cast<uint16_t>(clear_words >> (16u * i));
}
break; break;
// Each clear register stores one raw 32-bit float channel. case vk::Format::eR16G16B16A16Sint:
for (uint32_t i = 0; i < 4; i++) {
next.int32[i] = static_cast<int16_t>(clear_words >> (16u * i));
}
break;
// Each clear register stores one raw 32-bit channel.
case vk::Format::eR32G32Sfloat: case vk::Format::eR32G32Sfloat:
next.float32[1] = std::bit_cast<float>(static_cast<uint32_t>(clear_words >> 32u)); next.float32[1] = std::bit_cast<float>(static_cast<uint32_t>(clear_words >> 32u));
[[fallthrough]]; [[fallthrough]];
case vk::Format::eR32Sfloat: next.float32[0] = std::bit_cast<float>(packed); break; case vk::Format::eR32Sfloat: next.float32[0] = std::bit_cast<float>(packed); break;
case vk::Format::eR32Uint: next.uint32[0] = packed; break; case vk::Format::eR32G32Uint:
case vk::Format::eR32Sint: next.int32[0] = static_cast<int32_t>(packed); break; case vk::Format::eR32G32Sint:
next.uint32[1] = static_cast<uint32_t>(clear_words >> 32u);
[[fallthrough]];
case vk::Format::eR32Uint:
case vk::Format::eR32Sint: next.uint32[0] = packed; break;
// Narrow targets hold their channels in the low bits of the first word. UFC 6 (PPSA23566) // Narrow targets hold their channels in the low bits of the first word. UFC 6 (PPSA23566)
// fast-clears an R8_UINT map through CMASK every frame and then writes only part of it; // fast-clears an R8_UINT map through CMASK every frame and then writes only part of it;
// without these the clear was dropped and old contents piled up. // without these the clear was dropped and old contents piled up.
+17 -3
View File
@@ -12506,6 +12506,8 @@ public:
PackedCase{vk::Format::eR16G16Unorm, 0x0000ffffu, {1.0f, 0.0f}}, PackedCase{vk::Format::eR16G16Unorm, 0x0000ffffu, {1.0f, 0.0f}},
PackedCase{vk::Format::eR16G16Unorm, 0x80000001u, PackedCase{vk::Format::eR16G16Unorm, 0x80000001u,
{1.0f / 65535.0f, 32768.0f / 65535.0f}}, {1.0f / 65535.0f, 32768.0f / 65535.0f}},
PackedCase{vk::Format::eR16G16B16A16Unorm, 0x000180000000ffffull,
{1.0f, 0.0f, 32768.0f / 65535.0f, 1.0f / 65535.0f}},
PackedCase{vk::Format::eR8Unorm, 0xffffff80u, {128.0f / 255.0f}}, PackedCase{vk::Format::eR8Unorm, 0xffffff80u, {128.0f / 255.0f}},
PackedCase{vk::Format::eR8G8Unorm, 0xffff40ffu, {1.0f, 64.0f / 255.0f}}, PackedCase{vk::Format::eR8G8Unorm, 0xffff40ffu, {1.0f, 64.0f / 255.0f}},
}; };
@@ -12541,11 +12543,19 @@ public:
}; };
for (const auto &test : {UintCase{vk::Format::eR8Uint, 0xffffff05u, {5u}}, for (const auto &test : {UintCase{vk::Format::eR8Uint, 0xffffff05u, {5u}},
UintCase{vk::Format::eR8G8Uint, 0xffff0a05u, {5u, 10u}}, UintCase{vk::Format::eR8G8Uint, 0xffff0a05u, {5u, 10u}},
UintCase{vk::Format::eR16Uint, 0xffff1234u, {0x1234u}}}) { UintCase{vk::Format::eR16Uint, 0xffff1234u, {0x1234u}},
Require(name, "packed unsigned color clear", UintCase{vk::Format::eR16G16B16A16Uint, 0x4444333322221111ull,
{0x1111u, 0x2222u, 0x3333u, 0x4444u}},
UintCase{vk::Format::eR16G16B16A16Sint, 0x7fff0001ffff8000ull,
{0xffff8000u, 0xffffffffu, 1u, 0x7fffu}},
UintCase{vk::Format::eR32G32Uint, 0x89abcdef01234567ull,
{0x01234567u, 0x89abcdefu}},
UintCase{vk::Format::eR32G32Sint, 0x80000000ffffffffull,
{0xffffffffu, 0x80000000u}}}) {
Require(name, "packed integer color clear",
DecodePackedColorClear(test.format, test.word, clear) && DecodePackedColorClear(test.format, test.word, clear) &&
std::bit_cast<std::array<uint32_t, 4>>(clear.uint32) == test.channels, 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"); "integer clear lost a channel, its sign or bits of the next one");
} }
Require(name, "R8 DWORD fill", Require(name, "R8 DWORD fill",
!DecodeColorDwordFill(vk::Format::eR8Uint, 0x01020304u, clear) && !DecodeColorDwordFill(vk::Format::eR8Uint, 0x01020304u, clear) &&
@@ -12561,6 +12571,10 @@ public:
DecodeColorDwordFill(vk::Format::eR32G32Sfloat, 0x3f800000u, clear) && DecodeColorDwordFill(vk::Format::eR32G32Sfloat, 0x3f800000u, clear) &&
clear.float32[0] == 1.0f && clear.float32[1] == 1.0f, clear.float32[0] == 1.0f && clear.float32[1] == 1.0f,
"a repeated DWORD fill was decoded as a two-register clear"); "a repeated DWORD fill was decoded as a two-register clear");
Require(name, "RGBA16 DWORD fill",
DecodeColorDwordFill(vk::Format::eR16G16B16A16Uint, 0x22221111u, clear) &&
clear.uint32[2] == 0x1111u && clear.uint32[3] == 0x2222u,
"a DWORD fill did not repeat across the 64-bit pixel");
constexpr uintptr_t base = 0x0000000204100000ull; constexpr uintptr_t base = 0x0000000204100000ull;
constexpr uint64_t allocation_size = 0x1000000; constexpr uint64_t allocation_size = 0x1000000;
constexpr uint64_t allocation_alignment = 0x10000; constexpr uint64_t allocation_alignment = 0x10000;