mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-01 08:52:11 +01:00
[dxvk] Add helper to compute clear values for compressed formats
This commit is contained in:
parent
778b04f39a
commit
cde8661bc1
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user