From 37d5cb84e8ab724e575c5819518f761ba88886c7 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 29 Sep 2024 08:07:05 +0200 Subject: [PATCH] vulkan: check if current buffer has finished execution before picking another 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 --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 6317ab7d0e..f6d6ff6cb1 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2253,7 +2253,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); @@ -3190,7 +3190,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); @@ -4098,7 +4098,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 7f9008618e..1dc168e645 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) \ \