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:
nmzik
2026-10-26 07:40:55 +01:00
parent 17a0f53d39
commit f90a8b1589
2 changed files with 43 additions and 10 deletions
@@ -378,6 +378,9 @@ inline constexpr std::array<VideoOutFormatPolicy, 8> VIDEO_OUT_FORMAT_POLICIES {
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);
};
const auto unorm16 = [](uint64_t value) {
return static_cast<float>(value & 0xffffu) / 65535.0f;
};
const auto float16 = [](uint32_t value) {
const auto sign = (value & 0x8000u) << 16u;
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);
[[fallthrough]];
case vk::Format::eR16Sfloat: next.float32[0] = float16(packed); break;
case vk::Format::eR16G16Unorm:
next.float32[1] = static_cast<float>(packed >> 16u) / 65535.0f;
case vk::Format::eR16G16B16A16Unorm:
next.float32[2] = unorm16(clear_words >> 32u);
next.float32[3] = unorm16(clear_words >> 48u);
[[fallthrough]];
case vk::Format::eR16Unorm:
next.float32[0] = static_cast<float>(packed & 0xffffu) / 65535.0f;
case vk::Format::eR16G16Unorm:
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;
// 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:
next.float32[1] = std::bit_cast<float>(static_cast<uint32_t>(clear_words >> 32u));
[[fallthrough]];
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::eR32Sint: next.int32[0] = static_cast<int32_t>(packed); break;
case vk::Format::eR32G32Uint:
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)
// 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.