[FFmpeg-cvslog] hwcontext_vulkan: support more than one plane per DMABUF layer

Lynne git at videolan.org
Thu Mar 12 21:04:18 EET 2020


ffmpeg | branch: master | Lynne <dev at lynne.ee> | Thu Mar 12 18:59:12 2020 +0000| [6353b9e4abd8e3e0c9ae743701f38510939fe6f9] | committer: Lynne

hwcontext_vulkan: support more than one plane per DMABUF layer

Requires the dmabuf modifiers extension.
Allows for importing of compressed images with a second plane.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=6353b9e4abd8e3e0c9ae743701f38510939fe6f9
---

 libavutil/hwcontext_vulkan.c | 44 ++++++++++++++++++++++++++------------------
 1 file changed, 26 insertions(+), 18 deletions(-)

diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index 626b3ab5b7..f3aa1f0d8c 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -1658,24 +1658,20 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f
     int err = 0;
     VkResult ret;
     AVVkFrame *f;
+    int bind_counts = 0;
     AVHWDeviceContext *ctx = hwfc->device_ctx;
     AVVulkanDeviceContext *hwctx = ctx->hwctx;
     VulkanDevicePriv *p = ctx->internal->priv;
     const AVPixFmtDescriptor *fmt_desc = av_pix_fmt_desc_get(hwfc->sw_format);
     const int has_modifiers = p->extensions & EXT_DRM_MODIFIER_FLAGS;
-    VkSubresourceLayout plane_data[AV_NUM_DATA_POINTERS];
-    VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS];
+    VkSubresourceLayout plane_data[AV_NUM_DATA_POINTERS] = { 0 };
+    VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { 0 };
+    VkBindImagePlaneMemoryInfo plane_info[AV_NUM_DATA_POINTERS] = { 0 };
     VkExternalMemoryHandleTypeFlagBits htype = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
 
     VK_LOAD_PFN(hwctx->inst, vkGetMemoryFdPropertiesKHR);
 
     for (int i = 0; i < desc->nb_layers; i++) {
-        if (desc->layers[i].nb_planes > 1) {
-            av_log(ctx, AV_LOG_ERROR, "Cannot import DMABUFS with more than 1 "
-                                      "plane per layer!\n");
-            return AVERROR(EINVAL);
-        }
-
         if (drm_to_vulkan_fmt(desc->layers[i].format) == VK_FORMAT_UNDEFINED) {
             av_log(ctx, AV_LOG_ERROR, "Unsupported DMABUF layer format %#08x!\n",
                    desc->layers[i].format);
@@ -1729,10 +1725,13 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f
                 VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
 
     for (int i = 0; i < desc->nb_layers; i++) {
+        const int planes = desc->layers[i].nb_planes;
+        const int signal_p = has_modifiers && (planes > 1);
+
         VkImageDrmFormatModifierExplicitCreateInfoEXT drm_info = {
             .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
             .drmFormatModifier = desc->objects[0].format_modifier,
-            .drmFormatModifierPlaneCount = desc->layers[i].nb_planes,
+            .drmFormatModifierPlaneCount = planes,
             .pPlaneLayouts = (const VkSubresourceLayout *)&plane_data,
         };
 
@@ -1759,7 +1758,7 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f
             .extent.depth  = 1,
             .mipLevels     = 1,
             .arrayLayers   = 1,
-            .flags         = VK_IMAGE_CREATE_ALIAS_BIT,
+            .flags         = VK_IMAGE_CREATE_ALIAS_BIT | signal_p ? VK_IMAGE_CREATE_DISJOINT_BIT : 0x0,
             .tiling        = f->tiling,
             .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, /* specs say so */
             .usage         = DEFAULT_USAGE_FLAGS,
@@ -1767,7 +1766,7 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f
             .samples       = VK_SAMPLE_COUNT_1_BIT,
         };
 
-        for (int j = 0; j < desc->layers[i].nb_planes; j++) {
+        for (int j = 0; j < planes; j++) {
             plane_data[j].offset     = desc->layers[i].planes[j].offset;
             plane_data[j].rowPitch   = desc->layers[i].planes[j].pitch;
             plane_data[j].size       = 0; /* The specs say so for all 3 */
@@ -1801,16 +1800,25 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f
         f->layout[i] = image_create_info.initialLayout;
         f->access[i] = 0x0;
 
-        /* TODO: Fix to support more than 1 plane per layer */
-        bind_info[i].sType  = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
-        bind_info[i].pNext  = NULL;
-        bind_info[i].image  = f->img[i];
-        bind_info[i].memory = f->mem[desc->layers[i].planes[0].object_index];
-        bind_info[i].memoryOffset = desc->layers[i].planes[0].offset;
+        for (int j = 0; j < planes; j++) {
+            VkImageAspectFlagBits aspect = j == 0 ? VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT :
+                                           j == 1 ? VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT :
+                                                    VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT;
+
+            plane_info[bind_counts].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO;
+            plane_info[bind_counts].planeAspect = aspect;
+
+            bind_info[bind_counts].sType  = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
+            bind_info[bind_counts].pNext  = signal_p ? &plane_info[bind_counts] : NULL;
+            bind_info[bind_counts].image  = f->img[i];
+            bind_info[bind_counts].memory = f->mem[desc->layers[i].planes[j].object_index];
+            bind_info[bind_counts].memoryOffset = desc->layers[i].planes[j].offset;
+            bind_counts++;
+        }
     }
 
     /* Bind the allocated memory to the images */
-    ret = vkBindImageMemory2(hwctx->act_dev, desc->nb_layers, bind_info);
+    ret = vkBindImageMemory2(hwctx->act_dev, bind_counts, bind_info);
     if (ret != VK_SUCCESS) {
         av_log(ctx, AV_LOG_ERROR, "Failed to bind memory: %s\n",
                vk_ret2str(ret));



More information about the ffmpeg-cvslog mailing list