panvk: Enable YCbCr support for v10+

Signed-off-by: Rebecca Mckeever <rebecca.mckeever@collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32563>
This commit is contained in:
Rebecca Mckeever 2024-11-27 19:19:59 -08:00 committed by Marge Bot
parent a9759dd0e4
commit e8c6e22e14
6 changed files with 215 additions and 27 deletions

View file

@ -450,7 +450,7 @@ Vulkan 1.1 -- all DONE: anv, lvp, nvk, panvk/v10+, radv, tu, vn
VK_KHR_maintenance3 DONE (anv, dzn, hasvk, lvp, nvk, panvk, radv, tu, v3dv, vn)
VK_KHR_multiview DONE (anv, dzn, hasvk, lvp, nvk, panvk/v10+, radv, tu, v3dv, vn)
VK_KHR_relaxed_block_layout DONE (anv, dzn, hasvk, lvp, nvk, panvk, radv, tu, v3dv, vn)
VK_KHR_sampler_ycbcr_conversion DONE (anv, hasvk, lvp, nvk, radv, tu, v3dv, vn)
VK_KHR_sampler_ycbcr_conversion DONE (anv, hasvk, lvp, nvk, panvk/v10+, radv, tu, v3dv, vn)
VK_KHR_shader_draw_parameters DONE (anv, dzn, hasvk, lvp, nvk, radv, tu, vn, panvk)
VK_KHR_storage_buffer_storage_class DONE (anv, dzn, hasvk, lvp, nvk, panvk, radv, tu, v3dv, vn)
VK_KHR_variable_pointers DONE (anv, hasvk, lvp, nvk, panvk, radv, tu, v3dv, vn)
@ -507,7 +507,7 @@ Vulkan 1.3 -- all DONE: anv, lvp, nvk, radv, tu, vn, v3dv
VK_EXT_texel_buffer_alignment DONE (anv, hasvk, lvp, nvk, pvr, radv, tu, v3dv, vn)
VK_EXT_texture_compression_astc_hdr DONE (vn)
VK_EXT_tooling_info DONE (anv, hasvk, nvk, panvk, pvr, radv, tu, v3dv, vn)
VK_EXT_ycbcr_2plane_444_formats DONE (anv, lvp, nvk, vn)
VK_EXT_ycbcr_2plane_444_formats DONE (anv, lvp, nvk, panvk/v10+, vn)
Vulkan 1.4 -- all DONE: anv, lvp, nvk, radv/gfx8+, tu/a7xx+
@ -655,7 +655,7 @@ Khronos extensions that are not part of any Vulkan version:
VK_EXT_transform_feedback DONE (anv, hasvk, lvp, nvk, radv, tu, vn)
VK_EXT_vertex_attribute_divisor DONE (anv, dzn, hasvk, lvp, nvk, radv, tu, v3dv, vn)
VK_EXT_vertex_input_dynamic_state DONE (anv, lvp, nvk, radv, tu, vn)
VK_EXT_ycbcr_image_arrays DONE (anv, hasvk, lvp, nvk, radv)
VK_EXT_ycbcr_image_arrays DONE (anv, hasvk, lvp, nvk, panvk/v10+, radv)
VK_ANDROID_external_memory_android_hardware_buffer DONE (anv, radv, tu, vn)
VK_ANDROID_native_buffer DONE (anv, radv, tu, v3dv, vn)
VK_GOOGLE_decorate_string DONE (anv, hasvk, lvp, nvk, panvk, radv, tu)

View file

@ -4,3 +4,6 @@ storageInputOutput16 on panvk
VK_KHR_depth_stencil_resolve on panvk
VK_KHR_separate_depth_stencil_layouts on panvk
VK_EXT_separate_stencil_usage on panvk
samplerYcbcrConversion on panvk/v10+
ycbcr2plane444Formats on panvk/v10+
ycbcrImageArrays on panvk/v10+

View file

@ -45,6 +45,32 @@
#include "vk_object.h"
#include "vk_util.h"
static bool
can_be_aliased_to_yuv_plane(const struct panvk_image *image)
{
if (!(image->vk.create_flags & VK_IMAGE_CREATE_ALIAS_BIT))
return false;
VkFormat format = image->vk.format;
if (vk_format_is_depth_or_stencil(format) ||
vk_format_is_alpha(format) ||
vk_format_get_blockwidth(format) != 1 ||
vk_format_get_blockheight(format) != 1)
return false;
unsigned block_size = vk_format_get_blocksize(format);
switch (block_size) {
case 1:
case 2:
case 4:
return true;
}
return false;
}
static bool
panvk_image_can_use_mod(struct panvk_image *image, uint64_t mod)
{
@ -102,6 +128,15 @@ panvk_image_can_use_mod(struct panvk_image *image, uint64_t mod)
}
if (mod == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
/* Multiplanar YUV with U-interleaving isn't supported by the HW. We
* also need to make sure images that can be aliased to planes of
* multi-planar images remain compatible with the aliased images, so
* don't allow U-interleaving for those either.
*/
if (vk_format_get_plane_count(image->vk.format) > 1 ||
can_be_aliased_to_yuv_plane(image))
return false;
/* If we're dealing with a compressed format that requires non-compressed
* views we can't use U_INTERLEAVED tiling because the tiling is different
* between compressed and non-compressed formats. If we wanted to support
@ -218,10 +253,12 @@ panvk_image_init_layouts(struct panvk_image *image,
image->plane_count = 2;
for (uint8_t plane = 0; plane < image->plane_count; plane++) {
VkFormat format =
(image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT) ?
((plane == 0) ? VK_FORMAT_D32_SFLOAT : VK_FORMAT_S8_UINT) :
image->vk.format;
VkFormat format;
if (image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT)
format = plane == 0 ? VK_FORMAT_D32_SFLOAT : VK_FORMAT_S8_UINT;
else
format = vk_format_get_plane_format(image->vk.format, plane);
struct pan_image_explicit_layout plane_layout;
if (explicit_info)
@ -233,8 +270,10 @@ panvk_image_init_layouts(struct panvk_image *image,
image->planes[plane].layout = (struct pan_image_layout){
.format = vk_format_to_pipe_format(format),
.dim = panvk_image_type_to_mali_tex_dim(image->vk.image_type),
.width = image->vk.extent.width,
.height = image->vk.extent.height,
.width = vk_format_get_plane_width(image->vk.format, plane,
image->vk.extent.width),
.height = vk_format_get_plane_height(image->vk.format, plane,
image->vk.extent.height),
.depth = image->vk.extent.depth,
.array_size = image->vk.array_layers,
.nr_samples = image->vk.samples,

View file

@ -50,12 +50,16 @@ panvk_meta_copy_get_image_properties(struct panvk_image *img)
{
uint64_t mod = img->vk.drm_format_mod;
enum pipe_format pfmt = vk_format_to_pipe_format(img->vk.format);
unsigned blk_sz = util_format_get_blocksize(pfmt);
struct vk_meta_copy_image_properties props;
memset(&props, 0, sizeof(props));
const struct vk_format_ycbcr_info *ycbcr_info =
vk_format_get_ycbcr_info(img->vk.format);
if (drm_is_afbc(mod)) {
if (!vk_format_is_depth_or_stencil(img->vk.format)) {
if (ycbcr_info) {
for (uint32_t p = 0; p < ycbcr_info->n_planes; p++)
props.plane[p].view_format = ycbcr_info->planes[p].format;
} else if (!vk_format_is_depth_or_stencil(img->vk.format)) {
props.color.view_format = img->vk.format;
} else {
switch (img->vk.format) {
@ -112,7 +116,17 @@ panvk_meta_copy_get_image_properties(struct panvk_image *img)
assert(!"Invalid ZS format");
break;
}
} else if (ycbcr_info) {
for (uint32_t p = 0; p < ycbcr_info->n_planes; p++) {
unsigned blk_sz =
vk_format_get_blocksize(ycbcr_info->planes[p].format);
props.plane[p].view_format =
panvk_meta_get_uint_format_for_blk_size(blk_sz);
}
} else {
unsigned blk_sz = util_format_get_blocksize(pfmt);
props.color.view_format = panvk_meta_get_uint_format_for_blk_size(blk_sz);
}

View file

@ -209,6 +209,7 @@ get_device_extensions(const struct panvk_physical_device *device,
.KHR_push_descriptor = true,
.KHR_relaxed_block_layout = true,
.KHR_sampler_mirror_clamp_to_edge = true,
.KHR_sampler_ycbcr_conversion = arch >= 10,
.KHR_separate_depth_stencil_layouts = true,
.KHR_shader_draw_parameters = true,
.KHR_shader_expect_assume = true,
@ -250,6 +251,8 @@ get_device_extensions(const struct panvk_physical_device *device,
.EXT_shader_module_identifier = true,
.EXT_subgroup_size_control = arch >= 10, /* requires vk1.1 */
.EXT_tooling_info = true,
.EXT_ycbcr_2plane_444_formats = arch >= 10,
.EXT_ycbcr_image_arrays = arch >= 10,
.GOOGLE_decorate_string = true,
.GOOGLE_hlsl_functionality1 = true,
.GOOGLE_user_type = true,
@ -298,7 +301,7 @@ get_features(const struct panvk_physical_device *device,
.variablePointersStorageBuffer = true,
.variablePointers = true,
.protectedMemory = false,
.samplerYcbcrConversion = false,
.samplerYcbcrConversion = arch >= 10,
.shaderDrawParameters = true,
/* Vulkan 1.2 */
@ -421,6 +424,12 @@ get_features(const struct panvk_physical_device *device,
/* VK_EXT_shader_module_identifier */
.shaderModuleIdentifier = true,
/* VK_EXT_ycbcr_2plane_444_formats */
.ycbcr2plane444Formats = arch >= 10,
/* VK_EXT_ycbcr_image_arrays */
.ycbcrImageArrays = arch >= 10,
};
}
@ -1179,8 +1188,8 @@ format_is_supported(struct panvk_physical_device *physical_device,
}
static VkFormatFeatureFlags
get_image_format_features(struct panvk_physical_device *physical_device,
VkFormat format)
get_image_plane_format_features(struct panvk_physical_device *physical_device,
VkFormat format)
{
VkFormatFeatureFlags features = 0;
enum pipe_format pfmt = vk_format_to_pipe_format(format);
@ -1193,9 +1202,7 @@ get_image_format_features(struct panvk_physical_device *physical_device,
if (fmt.bind & PAN_BIND_SAMPLER_VIEW) {
features |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT |
VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
if (arch >= 10)
features |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT;
@ -1231,6 +1238,74 @@ get_image_format_features(struct panvk_physical_device *physical_device,
return features;
}
static VkFormatFeatureFlags
get_image_format_features(struct panvk_physical_device *physical_device,
VkFormat format)
{
const struct vk_format_ycbcr_info *ycbcr_info =
vk_format_get_ycbcr_info(format);
const unsigned arch = pan_arch(physical_device->kmod.props.gpu_prod_id);
/* TODO: Bifrost YCbCr support */
if (ycbcr_info && arch <= 7)
return 0;
if (ycbcr_info == NULL)
return get_image_plane_format_features(physical_device, format);
if (unsupported_yuv_format(vk_format_to_pipe_format(format)))
return 0;
/* For multi-plane, we get the feature flags of each plane separately,
* then take their intersection as the overall format feature flags
*/
VkFormatFeatureFlags features = ~0u;
bool cosited_chroma = false;
for (uint8_t plane = 0; plane < ycbcr_info->n_planes; plane++) {
const struct vk_format_ycbcr_plane *plane_info =
&ycbcr_info->planes[plane];
features &=
get_image_plane_format_features(physical_device, plane_info->format);
if (plane_info->denominator_scales[0] > 1 ||
plane_info->denominator_scales[1] > 1)
cosited_chroma = true;
}
if (features == 0)
return 0;
/* Uh... We really should be able to sample from YCbCr */
assert(features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
assert(features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT);
/* Siting is handled in the YCbCr lowering pass. */
features |= VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
if (cosited_chroma)
features |= VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT;
/* These aren't allowed for YCbCr formats */
features &= ~(VK_FORMAT_FEATURE_BLIT_SRC_BIT |
VK_FORMAT_FEATURE_BLIT_DST_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT |
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT);
/* This is supported on all YCbCr formats */
features |=
VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT;
if (ycbcr_info->n_planes > 1) {
/* DISJOINT_BIT implies that each plane has its own separate binding,
* while SEPARATE_RECONSTRUCTION_FILTER_BIT implies that luma and chroma
* each have their own, separate filters, so these two bits make sense
* for multi-planar formats only.
*/
features |= VK_FORMAT_FEATURE_DISJOINT_BIT |
VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT;
}
return features;
}
static VkFormatFeatureFlags
get_buffer_format_features(struct panvk_physical_device *physical_device,
VkFormat format)
@ -1316,15 +1391,12 @@ get_image_format_properties(struct panvk_physical_device *physical_device,
VkImageUsageFlags stencil_usage =
stencil_usage_info ? stencil_usage_info->stencilUsage : info->usage;
VkImageUsageFlags all_usage = info->usage | stencil_usage;
const struct vk_format_ycbcr_info *ycbcr_info =
vk_format_get_ycbcr_info(info->format);
switch (info->tiling) {
case VK_IMAGE_TILING_LINEAR:
format_feature_flags =
get_image_format_features(physical_device, info->format);
break;
case VK_IMAGE_TILING_OPTIMAL:
format_feature_flags =
get_image_format_features(physical_device, info->format);
break;
case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT: {
const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *mod_info =
@ -1340,18 +1412,35 @@ get_image_format_properties(struct panvk_physical_device *physical_device,
*/
if (util_format_is_depth_or_stencil(format))
goto unsupported;
format_feature_flags =
get_image_format_features(physical_device, info->format);
break;
}
default:
unreachable("bad VkPhysicalDeviceImageFormatInfo2");
}
/* For the purposes of these checks, we don't care about all the extra
* YCbCr features and we just want the intersection of features available
* to all planes of the given format.
*/
if (ycbcr_info == NULL) {
format_feature_flags =
get_image_format_features(physical_device, info->format);
} else {
format_feature_flags = ~0u;
assert(ycbcr_info->n_planes > 0);
for (uint8_t plane = 0; plane < ycbcr_info->n_planes; plane++) {
const VkFormat plane_format = ycbcr_info->planes[plane].format;
format_feature_flags &=
get_image_format_features(physical_device, plane_format);
}
}
if (format_feature_flags == 0)
goto unsupported;
if (ycbcr_info && info->type != VK_IMAGE_TYPE_2D)
goto unsupported;
switch (info->type) {
default:
unreachable("bad vkimage type");
@ -1378,8 +1467,11 @@ get_image_format_properties(struct panvk_physical_device *physical_device,
break;
}
if (ycbcr_info)
maxMipLevels = 1;
if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
info->type == VK_IMAGE_TYPE_2D &&
info->type == VK_IMAGE_TYPE_2D && ycbcr_info == NULL &&
(format_feature_flags &
(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
@ -1612,6 +1704,43 @@ panvk_GetPhysicalDeviceImageFormatProperties2(
}
}
const struct vk_format_ycbcr_info *ycbcr_info =
vk_format_get_ycbcr_info(base_info->format);
const unsigned plane_count =
vk_format_get_plane_count(base_info->format);
/* From the Vulkan 1.3.259 spec, VkImageCreateInfo:
*
* VUID-VkImageCreateInfo-imageCreateFormatFeatures-02260
*
* "If format is a multi-planar format, and if imageCreateFormatFeatures
* (as defined in Image Creation Limits) does not contain
* VK_FORMAT_FEATURE_DISJOINT_BIT, then flags must not contain
* VK_IMAGE_CREATE_DISJOINT_BIT"
*
* This is satisfied trivially because we support DISJOINT on all
* multi-plane formats. Also,
*
* VUID-VkImageCreateInfo-format-01577
*
* "If format is not a multi-planar format, and flags does not include
* VK_IMAGE_CREATE_ALIAS_BIT, flags must not contain
* VK_IMAGE_CREATE_DISJOINT_BIT"
*/
if (plane_count == 1 &&
!(base_info->flags & VK_IMAGE_CREATE_ALIAS_BIT) &&
(base_info->flags & VK_IMAGE_CREATE_DISJOINT_BIT))
goto fail;
if (ycbcr_info &&
((base_info->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) ||
(base_info->flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT)))
goto fail;
if ((base_info->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) &&
(base_info->usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT))
goto fail;
if (ycbcr_props)
ycbcr_props->combinedImageSamplerDescriptorCount = 1;

View file

@ -279,7 +279,10 @@ panvk_per_arch(CreateImageView)(VkDevice _device,
.dim = panvk_view_type_to_mali_tex_dim(view->vk.view_type),
.nr_samples = image->vk.samples,
.first_level = view->vk.base_mip_level,
.last_level = view->vk.base_mip_level + view->vk.level_count - 1,
/* MIPmapping in YUV formats is not supported by the HW. */
.last_level = vk_format_get_ycbcr_info(view->vk.format)
? view->vk.base_mip_level
: view->vk.base_mip_level + view->vk.level_count - 1,
.first_layer = view->vk.base_array_layer,
.last_layer = view->vk.base_array_layer + view->vk.layer_count - 1,
};