Module: Mesa Branch: main Commit: 5deb4760956f86369222cebef40a63a88ff9f5b8 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=5deb4760956f86369222cebef40a63a88ff9f5b8
Author: Dave Airlie <[email protected]> Date: Mon May 29 16:08:06 2023 +1000 radv: align video images internal width/height inside the driver. Due to how the decoders work, they will write garbage data into the padding, and later using the image for sampling with linear images will use the garbage to create broken results. Let the user specify the image size and align it up in the driver, so sampling of the image later has the correct w/h. cc: mesa-stable Reviewed-by: Lynne <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23227> --- src/amd/vulkan/radv_android.c | 2 +- src/amd/vulkan/radv_device_memory.c | 2 +- src/amd/vulkan/radv_image.c | 18 +++++++++++++++++- src/amd/vulkan/radv_private.h | 1 + 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/amd/vulkan/radv_android.c b/src/amd/vulkan/radv_android.c index 9785f5294ab..0a6e284fdc8 100644 --- a/src/amd/vulkan/radv_android.c +++ b/src/amd/vulkan/radv_android.c @@ -675,7 +675,7 @@ radv_import_ahb_memory(struct radv_device *device, struct radv_device_memory *me struct radv_image_create_info create_info = {.no_metadata_planes = true, .bo_metadata = &metadata}; - result = radv_image_create_layout(device, create_info, NULL, mem->image); + result = radv_image_create_layout(device, create_info, NULL, NULL, mem->image); if (result != VK_SUCCESS) { device->ws->buffer_destroy(device->ws, mem->bo); mem->bo = NULL; diff --git a/src/amd/vulkan/radv_device_memory.c b/src/amd/vulkan/radv_device_memory.c index 9a9c3964ac5..9aad1ed2c17 100644 --- a/src/amd/vulkan/radv_device_memory.c +++ b/src/amd/vulkan/radv_device_memory.c @@ -187,7 +187,7 @@ radv_alloc_memory(struct radv_device *device, const VkMemoryAllocateInfo *pAlloc /* This gives a basic ability to import radeonsi images * that don't have DCC. This is not guaranteed by any * spec and can be removed after we support modifiers. */ - result = radv_image_create_layout(device, create_info, NULL, mem->image); + result = radv_image_create_layout(device, create_info, NULL, NULL, mem->image); if (result != VK_SUCCESS) { device->ws->buffer_destroy(device->ws, mem->bo); goto fail; diff --git a/src/amd/vulkan/radv_image.c b/src/amd/vulkan/radv_image.c index ce6c1b2d987..93965eacdc9 100644 --- a/src/amd/vulkan/radv_image.c +++ b/src/amd/vulkan/radv_image.c @@ -1747,6 +1747,7 @@ radv_get_ac_surf_info(struct radv_device *device, const struct radv_image *image VkResult radv_image_create_layout(struct radv_device *device, struct radv_image_create_info create_info, const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *mod_info, + const struct VkVideoProfileListInfoKHR *profile_list, struct radv_image *image) { /* Clear the pCreateInfo pointer so we catch issues in the delayed case when we test in the @@ -1762,6 +1763,19 @@ radv_image_create_layout(struct radv_device *device, struct radv_image_create_in radv_image_reset_layout(device->physical_device, image); + /* + * Due to how the decoder works, the user can't supply an oversized image, because if it attempts + * to sample it later with a linear filter, it will get garbage after the height it wants, + * so we let the user specify the width/height unaligned, and align them preallocation. + */ + if (image->vk.usage & (VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR)) { + assert(profile_list); + uint32_t width_align, height_align; + vk_video_get_profile_alignments(profile_list, &width_align, &height_align); + image_info.width = align(image_info.width, width_align); + image_info.height = align(image_info.height, height_align); + } + unsigned plane_count = radv_get_internal_plane_count(device->physical_device, image->vk.format); for (unsigned plane = 0; plane < plane_count; ++plane) { struct ac_surf_info info = image_info; @@ -1943,6 +1957,8 @@ radv_image_create(VkDevice _device, const struct radv_image_create_info *create_ const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *explicit_mod = vk_find_struct_const(pCreateInfo->pNext, IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT); assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO); + const struct VkVideoProfileListInfoKHR *profile_list = + vk_find_struct_const(pCreateInfo->pNext, VIDEO_PROFILE_LIST_INFO_KHR); unsigned plane_count = radv_get_internal_plane_count(device->physical_device, format); @@ -2003,7 +2019,7 @@ radv_image_create(VkDevice _device, const struct radv_image_create_info *create_ return VK_SUCCESS; } - VkResult result = radv_image_create_layout(device, *create_info, explicit_mod, image); + VkResult result = radv_image_create_layout(device, *create_info, explicit_mod, profile_list, image); if (result != VK_SUCCESS) { radv_destroy_image(device, alloc, image); return result; diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index 88068fc4a05..17232f3a401 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -2852,6 +2852,7 @@ struct radv_image_create_info { VkResult radv_image_create_layout(struct radv_device *device, struct radv_image_create_info create_info, const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *mod_info, + const struct VkVideoProfileListInfoKHR *profile_list, struct radv_image *image); VkResult radv_image_create(VkDevice _device, const struct radv_image_create_info *info,
