History

vulkan_decode: use a single execution pool

Originally, the decoder had a single execution pool, with one execution context per thread. Execution pools were always intended to be thread-safe, as long as there were enough execution contexts in the pool to satisfy all threads. Due to synchronization issues, the threading part was removed at some point, and, for decoding, each thread had its own execution pool. Having a single execution pool per context is hacky, not to mention wasteful. Most importantly, we *cannot* associate single shaders across multiple execution pools for a single application. This means that we cannot use shaders to either apply film grain, or use this framework for software-defined decoders. The recent commits added threading capabilities back to the execution pool, and the number of contexts in each pool was increased. This was done with the assumption that the execution pool was singular, which it was not. This led to increased parallelism and number of frames in flight, which is taxing on memory. This commit finally restores proper threading behaviour. The validation layer has isses that are reported and addressed in the earlier commit.

Lynne committed 1 year ago

Commit 7239be01 parent 4ca2b862 files · +16 −33Browse files

Unified · Split

2 files
  1. libavcodec/vulkan_decode.c +15 −32
  2. libavcodec/vulkan_decode.h +1 −1
libavcodec/vulkan_decode.c+15−32
@@ -83,25 +83,6 @@ int ff_vk_update_thread_context(AVCodecContext *dst, const AVCodecContext *src) · 82 unmodified lines
83 FFVulkanDecodeContext *src_ctx = src->internal->hwaccel_priv_data;83 FFVulkanDecodeContext *src_ctx = src->internal->hwaccel_priv_data;
84 FFVulkanDecodeContext *dst_ctx = dst->internal->hwaccel_priv_data;84 FFVulkanDecodeContext *dst_ctx = dst->internal->hwaccel_priv_data;
85 85
86 if (!dst_ctx->exec_pool.cmd_bufs) {
87 FFVulkanDecodeShared *ctx = src_ctx->shared_ctx;
88
89 const VkVideoProfileInfoKHR *profile = get_video_profile(ctx, dst->codec_id);
90 if (!profile) {
91 av_log(dst, AV_LOG_ERROR, "Video profile missing from frames context!\n");
92 return AVERROR(EINVAL);
93 }
94
95 err = ff_vk_exec_pool_init(&ctx->s, &ctx->qf,
96 &dst_ctx->exec_pool,
97 src_ctx->exec_pool.pool_size,
98 src_ctx->exec_pool.nb_queries,
99 VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR, 0,
100 profile);
101 if (err < 0)
102 return err;
103 }
104
105 av_refstruct_replace(&dst_ctx->shared_ctx, src_ctx->shared_ctx);86 av_refstruct_replace(&dst_ctx->shared_ctx, src_ctx->shared_ctx);
106 87
107 if (src_ctx->session_params) {88 if (src_ctx->session_params) {
@@ -293,8 +274,11 @@ void ff_vk_decode_flush(AVCodecContext *avctx) · 185 unmodified lines
293 };274 };
294 275
295 VkCommandBuffer cmd_buf;276 VkCommandBuffer cmd_buf;
296 FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &dec->exec_pool);277 FFVkExecContext *exec;
297 int had_submission = exec->had_submission;278 int had_submission;
279
280 exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
281 had_submission = exec->had_submission;
298 ff_vk_exec_start(&ctx->s, exec);282 ff_vk_exec_start(&ctx->s, exec);
299 cmd_buf = exec->buf;283 cmd_buf = exec->buf;
300 284
@@ -345,7 +329,7 @@ int ff_vk_decode_frame(AVCodecContext *avctx, · 44 unmodified lines
345 size_t data_size = FFALIGN(vp->slices_size,329 size_t data_size = FFALIGN(vp->slices_size,
346 ctx->caps.minBitstreamBufferSizeAlignment);330 ctx->caps.minBitstreamBufferSizeAlignment);
347 331
348 FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &dec->exec_pool);332 FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
349 333
350 /* The current decoding reference has to be bound as an inactive reference */334 /* The current decoding reference has to be bound as an inactive reference */
351 VkVideoReferenceSlotInfoKHR *cur_vk_ref;335 VkVideoReferenceSlotInfoKHR *cur_vk_ref;
@@ -354,7 +338,7 @@ int ff_vk_decode_frame(AVCodecContext *avctx, · 2 unmodified lines
354 cur_vk_ref[0].slotIndex = -1;338 cur_vk_ref[0].slotIndex = -1;
355 decode_start.referenceSlotCount++;339 decode_start.referenceSlotCount++;
356 340
357 if (dec->exec_pool.nb_queries && exec->had_submission) {341 if (ctx->exec_pool.nb_queries && exec->had_submission) {
358 uint32_t *result;342 uint32_t *result;
359 ret = ff_vk_exec_get_query(&ctx->s, exec, (void **)&result,343 ret = ff_vk_exec_get_query(&ctx->s, exec, (void **)&result,
360 VK_QUERY_RESULT_WAIT_BIT);344 VK_QUERY_RESULT_WAIT_BIT);
@@ -525,14 +509,14 @@ int ff_vk_decode_frame(AVCodecContext *avctx, · 164 unmodified lines
525 vk->CmdBeginVideoCodingKHR(cmd_buf, &decode_start);509 vk->CmdBeginVideoCodingKHR(cmd_buf, &decode_start);
526 510
527 /* Start status query */511 /* Start status query */
528 if (dec->exec_pool.nb_queries)512 if (ctx->exec_pool.nb_queries)
529 vk->CmdBeginQuery(cmd_buf, dec->exec_pool.query_pool, exec->query_idx + 0, 0);513 vk->CmdBeginQuery(cmd_buf, ctx->exec_pool.query_pool, exec->query_idx + 0, 0);
530 514
531 vk->CmdDecodeVideoKHR(cmd_buf, &vp->decode_info);515 vk->CmdDecodeVideoKHR(cmd_buf, &vp->decode_info);
532 516
533 /* End status query */517 /* End status query */
534 if (dec->exec_pool.nb_queries)518 if (ctx->exec_pool.nb_queries)
535 vk->CmdEndQuery(cmd_buf, dec->exec_pool.query_pool, exec->query_idx + 0);519 vk->CmdEndQuery(cmd_buf, ctx->exec_pool.query_pool, exec->query_idx + 0);
536 520
537 vk->CmdEndVideoCodingKHR(cmd_buf, &decode_end);521 vk->CmdEndVideoCodingKHR(cmd_buf, &decode_end);
538 522
@@ -577,6 +561,9 @@ static void free_common(AVRefStructOpaque unused, void *obj) · 38 unmodified lines
577 FFVulkanContext *s = &ctx->s;561 FFVulkanContext *s = &ctx->s;
578 FFVulkanFunctions *vk = &ctx->s.vkfn;562 FFVulkanFunctions *vk = &ctx->s.vkfn;
579 563
564 /* Wait on and free execution pool */
565 ff_vk_exec_pool_free(&ctx->s, &ctx->exec_pool);
566
580 /* This also frees all references from this pool */567 /* This also frees all references from this pool */
581 av_frame_free(&ctx->common.layered_frame);568 av_frame_free(&ctx->common.layered_frame);
582 569
@@ -1066,10 +1053,6 @@ int ff_vk_decode_create_params(AVBufferRef **par_ref, void *logctx, FFVulkanDeco · 483 unmodified lines
1066int ff_vk_decode_uninit(AVCodecContext *avctx)1053int ff_vk_decode_uninit(AVCodecContext *avctx)
1067{1054{
1068 FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;1055 FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
1069 FFVulkanDecodeShared *ctx = dec->shared_ctx;
1070
1071 /* Wait on and free execution pool */
1072 ff_vk_exec_pool_free(&ctx->s, &dec->exec_pool);
1073 1056
1074 av_freep(&dec->hevc_headers);1057 av_freep(&dec->hevc_headers);
1075 av_buffer_unref(&dec->session_params);1058 av_buffer_unref(&dec->session_params);
@@ -1159,7 +1142,7 @@ int ff_vk_decode_init(AVCodecContext *avctx) · 83 unmodified lines
1159 /* Create decode exec context for this specific main thread.1142 /* Create decode exec context for this specific main thread.
1160 * 2 async contexts per thread was experimentally determined to be optimal1143 * 2 async contexts per thread was experimentally determined to be optimal
1161 * for a majority of streams. */1144 * for a majority of streams. */
1162 err = ff_vk_exec_pool_init(s, &ctx->qf, &dec->exec_pool,1145 err = ff_vk_exec_pool_init(s, &ctx->qf, &ctx->exec_pool,
1163 FFMAX(2*ctx->qf.nb_queues, avctx->thread_count),1146 FFMAX(2*ctx->qf.nb_queues, avctx->thread_count),
1164 nb_q, VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR, 0,1147 nb_q, VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR, 0,
1165 profile);1148 profile);
libavcodec/vulkan_decode.h+1−1
@@ -47,6 +47,7 @@ typedef struct FFVulkanDecodeShared { · 46 unmodified lines
47 FFVulkanContext s;47 FFVulkanContext s;
48 FFVkVideoCommon common;48 FFVkVideoCommon common;
49 FFVkQueueFamilyCtx qf;49 FFVkQueueFamilyCtx qf;
50 FFVkExecPool exec_pool;
50 51
51 AVBufferPool *buf_pool;52 AVBufferPool *buf_pool;
52 53
@@ -59,7 +60,6 @@ typedef struct FFVulkanDecodeShared { · 6 unmodified lines
59typedef struct FFVulkanDecodeContext {60typedef struct FFVulkanDecodeContext {
60 FFVulkanDecodeShared *shared_ctx;61 FFVulkanDecodeShared *shared_ctx;
61 AVBufferRef *session_params;62 AVBufferRef *session_params;
62 FFVkExecPool exec_pool;
63 63
64 int dedicated_dpb; /* Oddity #1 - separate DPB images */64 int dedicated_dpb; /* Oddity #1 - separate DPB images */
65 int external_fg; /* Oddity #2 - hardware can't apply film grain */65 int external_fg; /* Oddity #2 - hardware can't apply film grain */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t