[FFmpeg-cvslog] hwcontext_vulkan: initialize semaphores of DMABUF imports

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


ffmpeg | branch: master | Lynne <dev at lynne.ee> | Thu Mar 12 18:01:07 2020 +0000| [501bd57bdbc488db93c95d40682ef0b4f01ccec5] | committer: Lynne

hwcontext_vulkan: initialize semaphores of DMABUF imports

There was a recent change in Intel's driver that triggered a driver-internal
error if the semaphore given to the command buffer wasn't initialized.
Given that the specifications require the semaphore to be initialized,
this is within spec. Unlike what's causing it in the first place, which is
that there are no ways to extract/import dma sync objects from DMABUFs,
so we must leave our semaphores bare.

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

 libavutil/hwcontext_vulkan.c | 51 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 38 insertions(+), 13 deletions(-)

diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index 51fdbd2489..6c2372f7fb 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -1139,12 +1139,19 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f,
     return 0;
 }
 
-static int prepare_frame(AVHWFramesContext *hwfc, AVVkFrame *frame)
+enum PrepMode {
+    PREP_MODE_WRITE,
+    PREP_MODE_RO_SHADER,
+};
+
+static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx,
+                         AVVkFrame *frame, enum PrepMode pmode)
 {
     VkResult ret;
+    VkImageLayout new_layout;
+    VkAccessFlags new_access;
     AVHWDeviceContext *ctx = hwfc->device_ctx;
     AVVulkanDeviceContext *hwctx = ctx->hwctx;
-    VulkanFramesPriv *s = hwfc->internal->priv;
     const int planes = av_pix_fmt_count_planes(hwfc->sw_format);
 
     VkImageMemoryBarrier img_bar[AV_NUM_DATA_POINTERS] = { 0 };
@@ -1157,13 +1164,24 @@ static int prepare_frame(AVHWFramesContext *hwfc, AVVkFrame *frame)
     VkSubmitInfo s_info = {
         .sType                = VK_STRUCTURE_TYPE_SUBMIT_INFO,
         .commandBufferCount   = 1,
-        .pCommandBuffers      = &s->cmd.buf,
+        .pCommandBuffers      = &ectx->buf,
 
         .pSignalSemaphores    = frame->sem,
         .signalSemaphoreCount = planes,
     };
 
-    ret = vkBeginCommandBuffer(s->cmd.buf, &cmd_start);
+    switch (pmode) {
+    case PREP_MODE_WRITE:
+        new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+        new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
+        break;
+    case PREP_MODE_RO_SHADER:
+        new_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+        new_access = VK_ACCESS_TRANSFER_READ_BIT;
+        break;
+    }
+
+    ret = vkBeginCommandBuffer(ectx->buf, &cmd_start);
     if (ret != VK_SUCCESS)
         return AVERROR_EXTERNAL;
 
@@ -1173,9 +1191,9 @@ static int prepare_frame(AVHWFramesContext *hwfc, AVVkFrame *frame)
     for (int i = 0; i < planes; i++) {
         img_bar[i].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
         img_bar[i].srcAccessMask = 0x0;
-        img_bar[i].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+        img_bar[i].dstAccessMask = new_access;
         img_bar[i].oldLayout = frame->layout[i];
-        img_bar[i].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+        img_bar[i].newLayout = new_layout;
         img_bar[i].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
         img_bar[i].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
         img_bar[i].image = frame->img[i];
@@ -1187,20 +1205,20 @@ static int prepare_frame(AVHWFramesContext *hwfc, AVVkFrame *frame)
         frame->access[i] = img_bar[i].dstAccessMask;
     }
 
-    vkCmdPipelineBarrier(s->cmd.buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+    vkCmdPipelineBarrier(ectx->buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
                          VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
                          0, NULL, 0, NULL, planes, img_bar);
 
-    ret = vkEndCommandBuffer(s->cmd.buf);
+    ret = vkEndCommandBuffer(ectx->buf);
     if (ret != VK_SUCCESS)
         return AVERROR_EXTERNAL;
 
-    ret = vkQueueSubmit(s->cmd.queue, 1, &s_info, s->cmd.fence);
+    ret = vkQueueSubmit(ectx->queue, 1, &s_info, ectx->fence);
     if (ret != VK_SUCCESS) {
         return AVERROR_EXTERNAL;
     } else {
-        vkWaitForFences(hwctx->act_dev, 1, &s->cmd.fence, VK_TRUE, UINT64_MAX);
-        vkResetFences(hwctx->act_dev, 1, &s->cmd.fence);
+        vkWaitForFences(hwctx->act_dev, 1, &ectx->fence, VK_TRUE, UINT64_MAX);
+        vkResetFences(hwctx->act_dev, 1, &ectx->fence);
     }
 
     return 0;
@@ -1371,7 +1389,7 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, int size)
     if (err)
         goto fail;
 
-    err = prepare_frame(hwfc, f);
+    err = prepare_frame(hwfc, &p->cmd, f, PREP_MODE_WRITE);
     if (err)
         goto fail;
 
@@ -1775,7 +1793,7 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f
         /* We'd import a semaphore onto the one we created using
          * vkImportSemaphoreFdKHR but unfortunately neither DRM nor VAAPI
          * offer us anything we could import and sync with, so instead
-         * leave the semaphore unsignalled and enjoy the validation spam. */
+         * just signal the semaphore we created. */
 
         f->layout[i] = image_create_info.initialLayout;
         f->access[i] = 0x0;
@@ -1796,6 +1814,13 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f
         return AVERROR_EXTERNAL;
     }
 
+    /* NOTE: This is completely uneccesary and unneeded once we can import
+     * semaphores from DRM. Otherwise we have to activate the semaphores.
+     * We're reusing the exec context that's also used for uploads/downloads. */
+    err = prepare_frame(hwfc, &p->cmd, f, PREP_MODE_RO_SHADER);
+    if (err)
+        goto fail;
+
     *frame = f;
 
     return 0;



More information about the ffmpeg-cvslog mailing list