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,

Reply via email to