1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-31 23:52:20 +01:00

[dxvk] Add helper to compute clear values for compressed formats

This commit is contained in:
Philip Rebohle 2024-11-03 10:53:39 +01:00 committed by Philip Rebohle
parent 778b04f39a
commit cde8661bc1

View File

@ -386,5 +386,103 @@ namespace dxvk::util {
bool isDualSourceBlendFactor(
VkBlendFactor factor);
/**
* \brief Computes unsigned normalized value
*
* Doesn't necessarily do perfect rounding.
* \param [in] float Float value
* \param [in] bits Bit count
* \returns Normalized value
*/
inline uint32_t computeUnorm(float f, uint32_t bits) {
f = std::max(f, 0.0f);
f = std::min(f, 1.0f);
return uint32_t((f * float((1u << bits) - 1u)) + 0.5f);
}
/**
* \brief Computes signed normalized value
*
* Doesn't necessarily do perfect rounding.
* \param [in] float Float value
* \param [in] bits Bit count
* \returns Normalized value
*/
inline uint32_t computeSnorm(float f, uint32_t bits) {
f = std::max(f, -1.0f);
f = std::min(f, 1.0f);
return int32_t((f * float((1u << (bits - 1u)) - 1u)) + (f < 0.0f ? -0.5f : 0.5f));
}
/**
* \brief Computes clear payload for compressed image blocks
*
* Ignores whether the format is sRGB or not. If this is relevant,
* the input color must be converted into the correct space first.
* Does not support BC6H or BC7 formats.
* \param [in] format Image format
* \param [in] color Clear color, as floats
* \returns Block data as unsigned integers
*/
inline VkClearColorValue encodeClearBlockValue(
VkFormat format,
const VkClearColorValue& color) {
VkClearColorValue result = { };
switch (format) {
case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: {
// Encode clear color as color0, table will be all zeroes
result.uint32[0] = (computeUnorm(color.float32[2], 5) << 0)
| (computeUnorm(color.float32[1], 6) << 5)
| (computeUnorm(color.float32[0], 5) << 11);
} return result;
case VK_FORMAT_BC2_SRGB_BLOCK:
case VK_FORMAT_BC2_UNORM_BLOCK: {
// Alpha is encoded in the first four bytes as four-bit
// values. The color portion is identical to BC1.
uint32_t alpha = 0x11111111u * computeUnorm(color.float32[3], 4);
result.uint32[0] = alpha;
result.uint32[1] = alpha;
result.uint32[2] = (computeUnorm(color.float32[2], 5) << 0)
| (computeUnorm(color.float32[1], 6) << 5)
| (computeUnorm(color.float32[0], 5) << 11);
} return result;
case VK_FORMAT_BC3_UNORM_BLOCK:
case VK_FORMAT_BC3_SRGB_BLOCK: {
// Encode alpha as alpha0, color portion identical to BC1
result.uint32[0] = computeUnorm(color.float32[3], 8);
result.uint32[2] = (computeUnorm(color.float32[2], 5) << 0)
| (computeUnorm(color.float32[1], 6) << 5)
| (computeUnorm(color.float32[0], 5) << 11);
} return result;
case VK_FORMAT_BC4_SNORM_BLOCK: {
result.uint32[0] = computeSnorm(color.float32[0], 8);
} return result;
case VK_FORMAT_BC4_UNORM_BLOCK: {
result.uint32[0] = computeUnorm(color.float32[0], 8);
} return result;
case VK_FORMAT_BC5_SNORM_BLOCK: {
result.uint32[0] = computeSnorm(color.float32[0], 8);
result.uint32[2] = computeSnorm(color.float32[1], 8);
} return result;
case VK_FORMAT_BC5_UNORM_BLOCK: {
result.uint32[0] = computeUnorm(color.float32[0], 8);
result.uint32[2] = computeUnorm(color.float32[1], 8);
} return result;
default:
return color;
}
}
}