diff mbox series

[FFmpeg-devel,5/5] vulkan: check if current buffer has finished execution before picking another

Message ID 20240929094256.396352-5-dev@lynne.ee
State New
Headers show
Series [FFmpeg-devel,1/5] vulkan: merge FFVkSPIRVShader and FFVkPipeline into FFVkShader | expand

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Lynne Sept. 29, 2024, 9:42 a.m. UTC
This saves resources, as dependencies are freed/reclaimed with a lower latency,
and provies a speedup.
---
 libavcodec/vulkan_decode.c      |  4 ++--
 libavcodec/vulkan_encode.c      |  2 +-
 libavfilter/vf_nlmeans_vulkan.c |  2 +-
 libavfilter/vulkan_filter.c     |  6 +++---
 libavutil/hwcontext_vulkan.c    |  6 +++---
 libavutil/vulkan.c              | 15 +++++++++++----
 libavutil/vulkan.h              |  2 +-
 libavutil/vulkan_functions.h    |  1 +
 8 files changed, 23 insertions(+), 15 deletions(-)
diff mbox series

Patch

diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c
index a8b906a9dd..7d7295e05e 100644
--- a/libavcodec/vulkan_decode.c
+++ b/libavcodec/vulkan_decode.c
@@ -293,7 +293,7 @@  void ff_vk_decode_flush(AVCodecContext *avctx)
     };
 
     VkCommandBuffer cmd_buf;
-    FFVkExecContext *exec = ff_vk_exec_get(&dec->exec_pool);
+    FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &dec->exec_pool);
     int had_submission = exec->had_submission;
     ff_vk_exec_start(&ctx->s, exec);
     cmd_buf = exec->buf;
@@ -345,7 +345,7 @@  int ff_vk_decode_frame(AVCodecContext *avctx,
     size_t data_size = FFALIGN(vp->slices_size,
                                ctx->caps.minBitstreamBufferSizeAlignment);
 
-    FFVkExecContext *exec = ff_vk_exec_get(&dec->exec_pool);
+    FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &dec->exec_pool);
 
     /* The current decoding reference has to be bound as an inactive reference */
     VkVideoReferenceSlotInfoKHR *cur_vk_ref;
diff --git a/libavcodec/vulkan_encode.c b/libavcodec/vulkan_encode.c
index d187b7cdd3..6d1743c7d7 100644
--- a/libavcodec/vulkan_encode.c
+++ b/libavcodec/vulkan_encode.c
@@ -339,7 +339,7 @@  static int vulkan_encode_issue(AVCodecContext *avctx,
                                          size_align);
 
     /* Start command buffer recording */
-    exec = vp->exec = ff_vk_exec_get(&ctx->enc_pool);
+    exec = vp->exec = ff_vk_exec_get(&ctx->s, &ctx->enc_pool);
     ff_vk_exec_start(&ctx->s, exec);
     cmd_buf = exec->buf;
 
diff --git a/libavfilter/vf_nlmeans_vulkan.c b/libavfilter/vf_nlmeans_vulkan.c
index 05c752925e..b413194035 100644
--- a/libavfilter/vf_nlmeans_vulkan.c
+++ b/libavfilter/vf_nlmeans_vulkan.c
@@ -836,7 +836,7 @@  static int nlmeans_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
     }
 
     /* Execution context */
-    exec = ff_vk_exec_get(&s->e);
+    exec = ff_vk_exec_get(&s->vkctx, &s->e);
     ff_vk_exec_start(vkctx, exec);
 
     /* Dependencies */
diff --git a/libavfilter/vulkan_filter.c b/libavfilter/vulkan_filter.c
index 5cee4572e6..8d9b416d6a 100644
--- a/libavfilter/vulkan_filter.c
+++ b/libavfilter/vulkan_filter.c
@@ -249,7 +249,7 @@  int ff_vk_filter_process_simple(FFVulkanContext *vkctx, FFVkExecPool *e,
     int nb_img_bar = 0;
 
     /* Update descriptors and init the exec context */
-    FFVkExecContext *exec = ff_vk_exec_get(e);
+    FFVkExecContext *exec = ff_vk_exec_get(vkctx, e);
     ff_vk_exec_start(vkctx, exec);
 
     RET(ff_vk_exec_add_dep_frame(vkctx, exec, out_f,
@@ -321,7 +321,7 @@  int ff_vk_filter_process_2pass(FFVulkanContext *vkctx, FFVkExecPool *e,
     int nb_img_bar = 0;
 
     /* Update descriptors and init the exec context */
-    FFVkExecContext *exec = ff_vk_exec_get(e);
+    FFVkExecContext *exec = ff_vk_exec_get(vkctx, e);
     ff_vk_exec_start(vkctx, exec);
 
     RET(ff_vk_exec_add_dep_frame(vkctx, exec, in,
@@ -409,7 +409,7 @@  int ff_vk_filter_process_Nin(FFVulkanContext *vkctx, FFVkExecPool *e,
     int nb_img_bar = 0;
 
     /* Update descriptors and init the exec context */
-    FFVkExecContext *exec = ff_vk_exec_get(e);
+    FFVkExecContext *exec = ff_vk_exec_get(vkctx, e);
     ff_vk_exec_start(vkctx, exec);
 
     /* Add deps and create temporary imageviews */
diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index 3a3aff75c0..d6500de677 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -2254,7 +2254,7 @@  static int prepare_frame(AVHWFramesContext *hwfc, FFVkExecPool *ectx,
     };
 
     VkCommandBuffer cmd_buf;
-    FFVkExecContext *exec = ff_vk_exec_get(ectx);
+    FFVkExecContext *exec = ff_vk_exec_get(&p->vkctx, ectx);
     cmd_buf = exec->buf;
     ff_vk_exec_start(&p->vkctx, exec);
 
@@ -3191,7 +3191,7 @@  static int vulkan_map_from_drm_frame_sync(AVHWFramesContext *hwfc, AVFrame *dst,
             }
         }
 
-        exec = ff_vk_exec_get(&fp->compute_exec);
+        exec = ff_vk_exec_get(&p->vkctx, &fp->compute_exec);
         cmd_buf = exec->buf;
 
         ff_vk_exec_start(&p->vkctx, exec);
@@ -4099,7 +4099,7 @@  static int vulkan_transfer_frame(AVHWFramesContext *hwfc,
         }
     }
 
-    exec = ff_vk_exec_get(&fp->upload_exec);
+    exec = ff_vk_exec_get(&p->vkctx, &fp->upload_exec);
     cmd_buf = exec->buf;
 
     ff_vk_exec_start(&p->vkctx, exec);
diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c
index ab2519bf35..849199ab4f 100644
--- a/libavutil/vulkan.c
+++ b/libavutil/vulkan.c
@@ -482,11 +482,18 @@  VkResult ff_vk_exec_get_query(FFVulkanContext *s, FFVkExecContext *e,
                                    pool->qd_size, qf);
 }
 
-FFVkExecContext *ff_vk_exec_get(FFVkExecPool *pool)
+FFVkExecContext *ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
 {
-    uint32_t idx = pool->idx++;
-    idx %= pool->pool_size;
-    return &pool->contexts[idx];
+    FFVulkanFunctions *vk = &s->vkfn;
+    FFVkExecContext *e = &pool->contexts[pool->idx];
+
+    /* Check if last submission has already finished.
+     * If so, don't waste resources and reuse the same buffer. */
+    if (vk->GetFenceStatus(s->hwctx->act_dev, e->fence) == VK_SUCCESS)
+        return e;
+
+    pool->idx = (pool->idx + 1) % pool->pool_size;
+    return &pool->contexts[pool->idx];
 }
 
 void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h
index 47684e600d..8d60fae670 100644
--- a/libavutil/vulkan.h
+++ b/libavutil/vulkan.h
@@ -387,7 +387,7 @@  void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool);
 /**
  * Retrieve an execution pool. Threadsafe.
  */
-FFVkExecContext *ff_vk_exec_get(FFVkExecPool *pool);
+FFVkExecContext *ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool);
 
 /**
  * Performs nb_queries queries and returns their results and statuses.
diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h
index 91dd8b91e0..90e4d0004d 100644
--- a/libavutil/vulkan_functions.h
+++ b/libavutil/vulkan_functions.h
@@ -110,6 +110,7 @@  typedef enum FFVulkanExtensions {
     /* Fences */                                                                         \
     MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateFence)                             \
     MACRO(1, 1, FF_VK_EXT_NO_FLAG,              WaitForFences)                           \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetFenceStatus)                                        \
     MACRO(1, 1, FF_VK_EXT_NO_FLAG,              ResetFences)                             \
     MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyFence)                            \
                                                                                          \