util/format, vulkan: Add PIPE_FORMAT_X6R10X6G10X6B10X6A10_UNORM

The format has 4 x 16-bit words with 10-bit unorm values in bits [15:6]
and 6 padding bits in [5:0]. Since this requires 8 channel slots but the
format system only supports 4, use layout "other" with hand-written
pack/unpack conversion functions.

Signed-off-by: Christian Gmeiner <cgmeiner@igalia.com>
Reviewed-by: Lars-Ivar Hesselberg Simonsen <lars-ivar.simonsen@arm.com>
Acked-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Reviewed-by: Emma Anholt <emma@anholt.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40653>
This commit is contained in:
Christian Gmeiner 2026-03-26 22:07:37 +01:00 committed by Marge Bot
parent 81b8113a9f
commit 9f172ba4da
5 changed files with 142 additions and 0 deletions

View file

@ -2192,6 +2192,15 @@
channels: [UN8]
swizzles: [X, 0, 0, 1]
# 10-bit channels stored in 16-bit containers (upper 10 bits used,
# lower 6 bits are padding).
- name: X6R10X6G10X6B10X6A10_UNORM
layout: other
colorspace: RGB
block: {width: 1, height: 1, depth: 1}
channels: [UN16, UN16, UN16, UN16]
swizzles: [X, Y, Z, W]
# Formats for plane 0/plane 1 of P010
- name: X6R10_UNORM
layout: plain

View file

@ -352,3 +352,98 @@ util_format_r8g8bx_snorm_fetch_rgba(void *restrict in_dst, const uint8_t *restri
dst[2] = r8g8bx_derive(r, g) * (1.0f/0xff); /* b */
dst[3] = 1.0f; /* a */
}
/*
* PIPE_FORMAT_X6R10X6G10X6B10X6A10_UNORM
*
* 4 x 16-bit words, each with a 10-bit unorm value in the upper bits [15:6]
* and 6 padding bits in the lower bits [5:0].
*/
void
util_format_x6r10x6g10x6b10x6a10_unorm_unpack_rgba_float(void *restrict dst_row,
const uint8_t *restrict src_row,
unsigned width)
{
float *dst = dst_row;
const uint16_t *src = (const uint16_t *)src_row;
for (unsigned x = 0; x < width; x += 1) {
dst[0] = (src[0] >> 6) * (1.0f / 0x3ff); /* r */
dst[1] = (src[1] >> 6) * (1.0f / 0x3ff); /* g */
dst[2] = (src[2] >> 6) * (1.0f / 0x3ff); /* b */
dst[3] = (src[3] >> 6) * (1.0f / 0x3ff); /* a */
src += 4;
dst += 4;
}
}
void
util_format_x6r10x6g10x6b10x6a10_unorm_pack_rgba_float(uint8_t *restrict dst_row, unsigned dst_stride,
const float *restrict src_row, unsigned src_stride,
unsigned width, unsigned height)
{
for (unsigned y = 0; y < height; y += 1) {
const float *src = src_row;
uint16_t *dst = (uint16_t *)dst_row;
for (unsigned x = 0; x < width; x += 1) {
dst[0] = (uint16_t)(CLAMP(src[0], 0.0f, 1.0f) * 0x3ff + 0.5f) << 6; /* r */
dst[1] = (uint16_t)(CLAMP(src[1], 0.0f, 1.0f) * 0x3ff + 0.5f) << 6; /* g */
dst[2] = (uint16_t)(CLAMP(src[2], 0.0f, 1.0f) * 0x3ff + 0.5f) << 6; /* b */
dst[3] = (uint16_t)(CLAMP(src[3], 0.0f, 1.0f) * 0x3ff + 0.5f) << 6; /* a */
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
void
util_format_x6r10x6g10x6b10x6a10_unorm_fetch_rgba(void *restrict in_dst, const uint8_t *restrict src,
UNUSED unsigned i, UNUSED unsigned j)
{
float *dst = in_dst;
const uint16_t *s = (const uint16_t *)src;
dst[0] = (s[0] >> 6) * (1.0f / 0x3ff); /* r */
dst[1] = (s[1] >> 6) * (1.0f / 0x3ff); /* g */
dst[2] = (s[2] >> 6) * (1.0f / 0x3ff); /* b */
dst[3] = (s[3] >> 6) * (1.0f / 0x3ff); /* a */
}
void
util_format_x6r10x6g10x6b10x6a10_unorm_unpack_rgba_8unorm(uint8_t *restrict dst_row,
const uint8_t *restrict src_row,
unsigned width)
{
uint8_t *dst = dst_row;
const uint16_t *src = (const uint16_t *)src_row;
for (unsigned x = 0; x < width; x += 1) {
dst[0] = (uint8_t)((src[0] >> 6) * 0xff / 0x3ff); /* r */
dst[1] = (uint8_t)((src[1] >> 6) * 0xff / 0x3ff); /* g */
dst[2] = (uint8_t)((src[2] >> 6) * 0xff / 0x3ff); /* b */
dst[3] = (uint8_t)((src[3] >> 6) * 0xff / 0x3ff); /* a */
src += 4;
dst += 4;
}
}
void
util_format_x6r10x6g10x6b10x6a10_unorm_pack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride,
const uint8_t *restrict src_row, unsigned src_stride,
unsigned width, unsigned height)
{
for (unsigned y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint16_t *dst = (uint16_t *)dst_row;
for (unsigned x = 0; x < width; x += 1) {
dst[0] = (uint16_t)(src[0] * 0x3ff / 0xff) << 6;
dst[1] = (uint16_t)(src[1] * 0x3ff / 0xff) << 6;
dst[2] = (uint16_t)(src[2] * 0x3ff / 0xff) << 6;
dst[3] = (uint16_t)(src[3] * 0x3ff / 0xff) << 6;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}

View file

@ -108,4 +108,29 @@ util_format_r8g8bx_snorm_pack_rgba_8unorm(uint8_t *restrict dst_row, unsigned ds
const uint8_t *restrict src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_x6r10x6g10x6b10x6a10_unorm_unpack_rgba_float(void *restrict dst_row,
const uint8_t *restrict src_row,
unsigned width);
void
util_format_x6r10x6g10x6b10x6a10_unorm_pack_rgba_float(uint8_t *restrict dst_row, unsigned dst_stride,
const float *restrict src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_x6r10x6g10x6b10x6a10_unorm_fetch_rgba(void *restrict dst, const uint8_t *restrict src,
unsigned i, unsigned j);
void
util_format_x6r10x6g10x6b10x6a10_unorm_unpack_rgba_8unorm(uint8_t *restrict dst_row,
const uint8_t *restrict src_row,
unsigned width);
void
util_format_x6r10x6g10x6b10x6a10_unorm_pack_rgba_8unorm(uint8_t *restrict dst_row, unsigned dst_stride,
const uint8_t *restrict src_row, unsigned src_stride,
unsigned width, unsigned height);
#endif /* U_FORMAT_OTHER_H_ */

View file

@ -1077,6 +1077,16 @@ util_format_test_cases[] =
{PIPE_FORMAT_B2G3R3_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x03), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_B2G3R3_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x1c), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_B2G3R3_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xe0), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_X6R10X6G10X6B10X6A10_UNORM, PACKED_4x16(0xffc0, 0xffc0, 0xffc0, 0xffc0), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_X6R10X6G10X6B10X6A10_UNORM, PACKED_4x16(0xffc0, 0xffc0, 0xffc0, 0xffc0), PACKED_4x16(0xffc0, 0x0000, 0x0000, 0x0000), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_X6R10X6G10X6B10X6A10_UNORM, PACKED_4x16(0xffc0, 0xffc0, 0xffc0, 0xffc0), PACKED_4x16(0x0000, 0xffc0, 0x0000, 0x0000), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_X6R10X6G10X6B10X6A10_UNORM, PACKED_4x16(0xffc0, 0xffc0, 0xffc0, 0xffc0), PACKED_4x16(0x0000, 0x0000, 0xffc0, 0x0000), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_X6R10X6G10X6B10X6A10_UNORM, PACKED_4x16(0xffc0, 0xffc0, 0xffc0, 0xffc0), PACKED_4x16(0x0000, 0x0000, 0x0000, 0xffc0), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_X6R10X6G10X6B10X6A10_UNORM, PACKED_4x16(0xffc0, 0xffc0, 0xffc0, 0xffc0), PACKED_4x16(0xffc0, 0xffc0, 0xffc0, 0xffc0), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
{PIPE_FORMAT_X6R10X6G10X6B10X6A10_UNORM, PACKED_4x16(0xffc0, 0xffc0, 0xffc0, 0xffc0), PACKED_4x16(0x0040, 0x0000, 0x0000, 0x0000), UNPACKED_1x1(1.0/1023.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_X6R10X6G10X6B10X6A10_UNORM, PACKED_4x16(0xffc0, 0xffc0, 0xffc0, 0xffc0), PACKED_4x16(0x8000, 0x0000, 0x0000, 0x0000), UNPACKED_1x1(512.0/1023.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_X6R10X6G10X6B10X6A10_UNORM, PACKED_4x16(0xffc0, 0xffc0, 0xffc0, 0xffc0), PACKED_4x16(0x0040, 0x8000, 0x5540, 0xffc0), UNPACKED_1x1(1.0/1023.0, 512.0/1023.0, 341.0/1023.0, 1.0)},
};

View file

@ -268,6 +268,8 @@ vk_format_to_pipe_format(VkFormat vkformat)
return PIPE_FORMAT_X4R12_UNORM;
case VK_FORMAT_R10X6G10X6_UNORM_2PACK16:
return PIPE_FORMAT_X6R10X6G10_UNORM;
case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
return PIPE_FORMAT_X6R10X6G10X6B10X6A10_UNORM;
case VK_FORMAT_R12X4G12X4_UNORM_2PACK16:
return PIPE_FORMAT_X4R12X4G12_UNORM;
case VK_FORMAT_G8B8G8R8_422_UNORM:
@ -464,6 +466,7 @@ static const VkFormat formats[PIPE_FORMAT_COUNT] = {
[PIPE_FORMAT_X6R10_UNORM] = VK_FORMAT_R10X6_UNORM_PACK16,
[PIPE_FORMAT_X4R12_UNORM] = VK_FORMAT_R12X4_UNORM_PACK16,
[PIPE_FORMAT_X6R10X6G10_UNORM] = VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
[PIPE_FORMAT_X6R10X6G10X6B10X6A10_UNORM] = VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
[PIPE_FORMAT_X4R12X4G12_UNORM] = VK_FORMAT_R12X4G12X4_UNORM_2PACK16,
[PIPE_FORMAT_G8B8_G8R8_UNORM] = VK_FORMAT_G8B8G8R8_422_UNORM,
[PIPE_FORMAT_B8G8_R8G8_UNORM] = VK_FORMAT_B8G8R8G8_422_UNORM,