From 5eaf8218def9a3dcd115857a2c7ea5b9172b896f Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Tue, 30 Mar 2021 22:20:53 -0500 Subject: [PATCH] vulkan/formats: Add YCbCr format information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alejandro PiƱeiro Part-of: --- src/vulkan/util/vk_format.c | 122 ++++++++++++++++++++++++++++++++++++ src/vulkan/util/vk_format.h | 24 +++++++ 2 files changed, 146 insertions(+) diff --git a/src/vulkan/util/vk_format.c b/src/vulkan/util/vk_format.c index eab742f6943..2b4049f32cf 100644 --- a/src/vulkan/util/vk_format.c +++ b/src/vulkan/util/vk_format.c @@ -24,6 +24,10 @@ #include "vk_format.h" +#include "vk_enum_defines.h" +#include "vk_enum_to_str.h" +#include "vk_util.h" + /* Note that for packed formats, VK_FORMAT_ lists channels from high to low * bits occupied by the channel, while MESA_FORMAT_* and PIPE_FORMAT_* are * low-to-high. @@ -431,3 +435,121 @@ vk_component_mapping_to_pipe_swizzle(VkComponentMapping mapping, } } } + +#define fmt_unsupported(__vk_fmt) \ + [VK_ENUM_OFFSET(__vk_fmt)] = { \ + .n_planes = 0, \ + } + +#define y_plane(__plane_fmt, __ycbcr_swizzle, dhs, dvs) \ + { .format = __plane_fmt, \ + .has_chroma = false, \ + .denominator_scales = { dhs, dvs, }, \ + .ycbcr_swizzle = __ycbcr_swizzle, \ + } + +#define c_plane(__plane_fmt, __ycbcr_swizzle, dhs, dvs) \ + { .format = __plane_fmt, \ + .has_chroma = true, \ + .denominator_scales = { dhs, dvs, }, \ + .ycbcr_swizzle = __ycbcr_swizzle, \ + } + +#define ycbcr_fmt(__vk_fmt, __n_planes, ...) \ + [VK_ENUM_OFFSET(__vk_fmt)] = { \ + .n_planes = __n_planes, \ + .planes = { \ + __VA_ARGS__, \ + }, \ + } + +#define YCBCR_SWIZ(x, y, z, w) { \ + VK_COMPONENT_SWIZZLE_##x, \ + VK_COMPONENT_SWIZZLE_##y, \ + VK_COMPONENT_SWIZZLE_##z, \ + VK_COMPONENT_SWIZZLE_##w, \ + } + +static const struct vk_format_ycbcr_info ycbcr_infos[] = { + ycbcr_fmt(VK_FORMAT_G8B8G8R8_422_UNORM, 1, + y_plane(VK_FORMAT_G8B8G8R8_422_UNORM, YCBCR_SWIZ(B, G, R, ZERO), 1, 1)), + ycbcr_fmt(VK_FORMAT_B8G8R8G8_422_UNORM, 1, + y_plane(VK_FORMAT_B8G8R8G8_422_UNORM, YCBCR_SWIZ(B, G, R, ZERO), 1, 1)), + ycbcr_fmt(VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, 3, + y_plane(VK_FORMAT_R8_UNORM, YCBCR_SWIZ(G, ZERO, ZERO, ZERO), 1, 1), + c_plane(VK_FORMAT_R8_UNORM, YCBCR_SWIZ(B, ZERO, ZERO, ZERO), 2, 2), + c_plane(VK_FORMAT_R8_UNORM, YCBCR_SWIZ(R, ZERO, ZERO, ZERO), 2, 2)), + ycbcr_fmt(VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, 2, + y_plane(VK_FORMAT_R8_UNORM, YCBCR_SWIZ(G, ZERO, ZERO, ZERO), 1, 1), + c_plane(VK_FORMAT_R8G8_UNORM, YCBCR_SWIZ(B, R, ZERO, ZERO), 2, 2)), + ycbcr_fmt(VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM, 3, + y_plane(VK_FORMAT_R8_UNORM, YCBCR_SWIZ(G, ZERO, ZERO, ZERO), 1, 1), + c_plane(VK_FORMAT_R8_UNORM, YCBCR_SWIZ(B, ZERO, ZERO, ZERO), 2, 1), + c_plane(VK_FORMAT_R8_UNORM, YCBCR_SWIZ(R, ZERO, ZERO, ZERO), 2, 1)), + ycbcr_fmt(VK_FORMAT_G8_B8R8_2PLANE_422_UNORM, 2, + y_plane(VK_FORMAT_R8_UNORM, YCBCR_SWIZ(G, ZERO, ZERO, ZERO), 1, 1), + c_plane(VK_FORMAT_R8G8_UNORM, YCBCR_SWIZ(B, R, ZERO, ZERO), 2, 1)), + ycbcr_fmt(VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, 3, + y_plane(VK_FORMAT_R8_UNORM, YCBCR_SWIZ(G, ZERO, ZERO, ZERO), 1, 1), + c_plane(VK_FORMAT_R8_UNORM, YCBCR_SWIZ(B, ZERO, ZERO, ZERO), 1, 1), + c_plane(VK_FORMAT_R8_UNORM, YCBCR_SWIZ(R, ZERO, ZERO, ZERO), 1, 1)), + + fmt_unsupported(VK_FORMAT_R10X6_UNORM_PACK16), + fmt_unsupported(VK_FORMAT_R10X6G10X6_UNORM_2PACK16), + fmt_unsupported(VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16), + fmt_unsupported(VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16), + fmt_unsupported(VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16), + fmt_unsupported(VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16), + fmt_unsupported(VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16), + fmt_unsupported(VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16), + fmt_unsupported(VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16), + fmt_unsupported(VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16), + fmt_unsupported(VK_FORMAT_R12X4_UNORM_PACK16), + fmt_unsupported(VK_FORMAT_R12X4G12X4_UNORM_2PACK16), + fmt_unsupported(VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16), + fmt_unsupported(VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16), + fmt_unsupported(VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16), + fmt_unsupported(VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16), + fmt_unsupported(VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16), + fmt_unsupported(VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16), + fmt_unsupported(VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16), + fmt_unsupported(VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16), + fmt_unsupported(VK_FORMAT_G16B16G16R16_422_UNORM), + fmt_unsupported(VK_FORMAT_B16G16R16G16_422_UNORM), + + ycbcr_fmt(VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, 3, + y_plane(VK_FORMAT_R16_UNORM, YCBCR_SWIZ(G, ZERO, ZERO, ZERO), 1, 1), + c_plane(VK_FORMAT_R16_UNORM, YCBCR_SWIZ(B, ZERO, ZERO, ZERO), 2, 2), + c_plane(VK_FORMAT_R16_UNORM, YCBCR_SWIZ(R, ZERO, ZERO, ZERO), 2, 2)), + ycbcr_fmt(VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, 2, + y_plane(VK_FORMAT_R16_UNORM, YCBCR_SWIZ(G, ZERO, ZERO, ZERO), 1, 1), + c_plane(VK_FORMAT_R16G16_UNORM, YCBCR_SWIZ(B, R, ZERO, ZERO), 2, 2)), + ycbcr_fmt(VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, 3, + y_plane(VK_FORMAT_R16_UNORM, YCBCR_SWIZ(G, ZERO, ZERO, ZERO), 1, 1), + c_plane(VK_FORMAT_R16_UNORM, YCBCR_SWIZ(B, ZERO, ZERO, ZERO), 2, 1), + c_plane(VK_FORMAT_R16_UNORM, YCBCR_SWIZ(R, ZERO, ZERO, ZERO), 2, 1)), + ycbcr_fmt(VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, 2, + y_plane(VK_FORMAT_R16_UNORM, YCBCR_SWIZ(G, ZERO, ZERO, ZERO), 1, 1), + c_plane(VK_FORMAT_R16G16_UNORM, YCBCR_SWIZ(B, R, ZERO, ZERO), 2, 1)), + ycbcr_fmt(VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, 3, + y_plane(VK_FORMAT_R16_UNORM, YCBCR_SWIZ(G, ZERO, ZERO, ZERO), 1, 1), + c_plane(VK_FORMAT_R16_UNORM, YCBCR_SWIZ(B, ZERO, ZERO, ZERO), 1, 1), + c_plane(VK_FORMAT_R16_UNORM, YCBCR_SWIZ(R, ZERO, ZERO, ZERO), 1, 1)), +}; + +const struct vk_format_ycbcr_info * +vk_format_get_ycbcr_info(VkFormat format) +{ + uint32_t enum_offset = VK_ENUM_OFFSET(format); + uint32_t ext_number = VK_ENUM_EXTENSION(format); + if (ext_number != _VK_KHR_sampler_ycbcr_conversion_number) + return NULL; + + if (enum_offset >= ARRAY_SIZE(ycbcr_infos)) + return NULL; + + if (ycbcr_infos[enum_offset].n_planes == 0) + return NULL; + + return &ycbcr_infos[enum_offset]; +} diff --git a/src/vulkan/util/vk_format.h b/src/vulkan/util/vk_format.h index 48994bd7b18..1b9d79fd3eb 100644 --- a/src/vulkan/util/vk_format.h +++ b/src/vulkan/util/vk_format.h @@ -210,6 +210,30 @@ vk_format_get_plane_format(VkFormat format, unsigned plane_id); VkFormat vk_format_get_aspect_format(VkFormat format, const VkImageAspectFlags aspect); +struct vk_format_ycbcr_plane { + /* RGBA format for this plane */ + VkFormat format; + + /* Whether this plane contains chroma channels */ + bool has_chroma; + + /* For downscaling of YUV planes */ + uint8_t denominator_scales[2]; + + /* How to map sampled ycbcr planes to a single 4 component element. + * + * We use uint8_t for compactness but it's actually VkComponentSwizzle. + */ + uint8_t ycbcr_swizzle[4]; +}; + +struct vk_format_ycbcr_info { + uint8_t n_planes; + struct vk_format_ycbcr_plane planes[3]; +}; + +const struct vk_format_ycbcr_info *vk_format_get_ycbcr_info(VkFormat format); + #ifdef __cplusplus } #endif