This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 318e2e3943cef34a353b17985495719f28ce0bb1
Author:     Lynne <[email protected]>
AuthorDate: Sun Jul 26 16:03:13 2026 +0800
Commit:     Lynne <[email protected]>
CommitDate: Wed Aug 5 16:04:37 2026 +0900

    vulkan: manage buffer pools and host mappings with AVRefStruct
    
    This converts all buffers/buffer pools into refstructs/refstruct pools,
    saving allocs and making them easier to work with.
---
 libavcodec/apv_encode_vulkan.c       | 78 +++++++++++++++---------------
 libavcodec/ffv1enc_vulkan.c          | 93 ++++++++++++++++--------------------
 libavcodec/proresenc_kostya_vulkan.c | 63 ++++++++++++------------
 libavcodec/vulkan_apv.c              | 41 +++++++---------
 libavcodec/vulkan_decode.c           | 24 ++++------
 libavcodec/vulkan_decode.h           | 10 +---
 libavcodec/vulkan_dpx.c              |  9 ++--
 libavcodec/vulkan_encode.c           | 30 +++++++-----
 libavcodec/vulkan_encode.h           |  6 +--
 libavcodec/vulkan_ffv1.c             | 53 ++++++++++----------
 libavcodec/vulkan_prores.c           | 23 ++++-----
 libavcodec/vulkan_prores_raw.c       | 23 ++++-----
 libavfilter/vf_blackdetect_vulkan.c  | 14 +++---
 libavfilter/vf_nlmeans_vulkan.c      | 36 +++++---------
 libavfilter/vf_scdet_vulkan.c        | 14 +++---
 libavutil/hwcontext_vulkan.c         | 30 +++++-------
 libavutil/vulkan.c                   | 66 +++++++------------------
 libavutil/vulkan.h                   |  6 +--
 18 files changed, 267 insertions(+), 352 deletions(-)

diff --git a/libavcodec/apv_encode_vulkan.c b/libavcodec/apv_encode_vulkan.c
index 076d151d77..918228309c 100644
--- a/libavcodec/apv_encode_vulkan.c
+++ b/libavcodec/apv_encode_vulkan.c
@@ -78,10 +78,10 @@ typedef struct CompactPushData {
 } CompactPushData;
 
 typedef struct VulkanEncodeAPVFrameData {
-    AVBufferRef *coeffs_ref;
-    AVBufferRef *bytestream_ref;
-    AVBufferRef *compacted_ref;
-    AVBufferRef *sizes_ref;
+    FFVkBuffer *coeffs_ref;
+    FFVkBuffer *bytestream_ref;
+    FFVkBuffer *compacted_ref;
+    FFVkBuffer *sizes_ref;
 
     int64_t pts;
     int64_t duration;
@@ -102,11 +102,11 @@ typedef struct VulkanEncodeAPVContext {
     FFVulkanShader shd_compact;
 
     /* Per-frame buffer pools */
-    AVBufferPool *coeffs_pool;
-    AVBufferPool *bytestream_pool;
-    AVBufferPool *gathered_pool;
-    AVBufferPool *compacted_pool;
-    AVBufferPool *sizes_pool;
+    AVRefStructPool *coeffs_pool;
+    AVRefStructPool *bytestream_pool;
+    AVRefStructPool *gathered_pool;
+    AVRefStructPool *compacted_pool;
+    AVRefStructPool *sizes_pool;
 
     /* DCT/quantize push constants -- encoder-constant, built once at init. */
     DCTPushData dct_push;
@@ -404,8 +404,8 @@ static int submit_frame(AVCodecContext *avctx, 
FFVkExecContext *exec,
 
     FFVkBuffer *coeffs_buf;
     FFVkBuffer *bytestream_buf;
-    AVBufferRef *gathered_ref = NULL;
-    FFVkBuffer *gathered_buf;
+
+    FFVkBuffer *gathered_buf = NULL;
     FFVkBuffer *compacted_buf;
     FFVkBuffer *sizes_buf;
 
@@ -414,7 +414,7 @@ static int submit_frame(AVCodecContext *avctx, 
FFVkExecContext *exec,
                                 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
                                 NULL, ev->coeffs_size,
                                 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
-    coeffs_buf = (FFVkBuffer *)fd->coeffs_ref->data;
+    coeffs_buf = fd->coeffs_ref;
 
     /* The entropy shader writes the bitstream here, sparsely -- one
      * worst-case-sized slot per tile-component. Device-local, so those GPU
@@ -425,19 +425,18 @@ static int submit_frame(AVCodecContext *avctx, 
FFVkExecContext *exec,
                                 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
                                 NULL, ev->bytestream_size,
                                 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
-    bytestream_buf = (FFVkBuffer *)fd->bytestream_ref->data;
+    bytestream_buf = fd->bytestream_ref;
 
     /* The compaction shader gathers the sparse slots into here, contiguous.
      * Device-local: shader stores over the bus are unreliably slow on some
      * drivers, so the transfer to the host is left to the copy engine. */
     RET(ff_vk_get_pooled_buffer(&ev->s, &ev->gathered_pool,
-                                &gathered_ref,
+                                &gathered_buf,
                                 VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
                                 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
                                 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
                                 NULL, ev->bytestream_size,
                                 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
-    gathered_buf = (FFVkBuffer *)gathered_ref->data;
 
     /* Copy-engine destination the CPU assembles the packet from.
      * Host-visible + host-cached so the readback is a fast cached copy. */
@@ -449,7 +448,7 @@ static int submit_frame(AVCodecContext *avctx, 
FFVkExecContext *exec,
                                 NULL, ev->bytestream_size,
                                 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
                                 VK_MEMORY_PROPERTY_HOST_CACHED_BIT));
-    compacted_buf = (FFVkBuffer *)fd->compacted_ref->data;
+    compacted_buf = fd->compacted_ref;
 
     RET(ff_vk_get_pooled_buffer(&ev->s, &ev->sizes_pool, &fd->sizes_ref,
                                 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
@@ -457,16 +456,14 @@ static int submit_frame(AVCodecContext *avctx, 
FFVkExecContext *exec,
                                 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
                                 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
                                 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT));
-    sizes_buf = (FFVkBuffer *)fd->sizes_ref->data;
+    sizes_buf = fd->sizes_ref;
 
     ff_vk_exec_start(&ev->s, exec);
 
-    ff_vk_exec_add_dep_buf(&ev->s, exec, &fd->coeffs_ref, 1, 1);
-    ff_vk_exec_add_dep_buf(&ev->s, exec, &fd->bytestream_ref, 1, 1);
-    ff_vk_exec_add_dep_buf(&ev->s, exec, &gathered_ref, 1, 0);
-    gathered_ref = NULL; /* Ownership passed */
-    ff_vk_exec_add_dep_buf(&ev->s, exec, &fd->compacted_ref, 1, 1);
-    ff_vk_exec_add_dep_buf(&ev->s, exec, &fd->sizes_ref, 1, 1);
+    ff_vk_exec_add_dep_refstruct(&ev->s, exec, fd->coeffs_ref);
+    ff_vk_exec_add_dep_refstruct(&ev->s, exec, fd->bytestream_ref);
+    ff_vk_exec_add_dep_refstruct(&ev->s, exec, fd->compacted_ref);
+    ff_vk_exec_add_dep_refstruct(&ev->s, exec, fd->sizes_ref);
 
     RET(ff_vk_exec_add_dep_frame(&ev->s, exec, frame,
                                  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
@@ -620,14 +617,15 @@ static int submit_frame(AVCodecContext *avctx, 
FFVkExecContext *exec,
                           1, &(VkBufferCopy) { .size = ev->bytestream_size });
     }
 
+    ff_vk_exec_move_dep_refstruct(&ev->s, exec, &gathered_buf);
     err = ff_vk_exec_submit(&ev->s, exec);
     if (err < 0)
-        return err;
+        goto fail;
 
     return 0;
 
 fail:
-    av_buffer_unref(&gathered_ref);
+    av_refstruct_unref(&gathered_buf);
     ff_vk_exec_discard_deps(&ev->s, exec);
     return err;
 }
@@ -639,8 +637,8 @@ static int build_packet(AVCodecContext *avctx, 
FFVkExecContext *exec,
     VulkanEncodeAPVContext *ev = avctx->priv_data;
     FFVulkanFunctions *vk = &ev->s.vkfn;
     VulkanEncodeAPVFrameData *fd = exec->opaque;
-    FFVkBuffer *compacted_buf = (FFVkBuffer *)fd->compacted_ref->data;
-    FFVkBuffer *sizes_buf     = (FFVkBuffer *)fd->sizes_ref->data;
+    FFVkBuffer *compacted_buf = fd->compacted_ref;
+    FFVkBuffer *sizes_buf     = fd->sizes_ref;
     APVRawFrame *raw_frame = NULL;
 
     /* Wait for the GPU encode to finish */
@@ -780,10 +778,10 @@ static int build_packet(AVCodecContext *avctx, 
FFVkExecContext *exec,
     av_log(avctx, AV_LOG_VERBOSE, "Encoded APV frame: %i bytes (%.2f MiB)\n",
            pkt->size, pkt->size / (1024.0 * 1024.0));
 
-    av_buffer_unref(&fd->coeffs_ref);
-    av_buffer_unref(&fd->bytestream_ref);
-    av_buffer_unref(&fd->compacted_ref);
-    av_buffer_unref(&fd->sizes_ref);
+    av_refstruct_unref(&fd->coeffs_ref);
+    av_refstruct_unref(&fd->bytestream_ref);
+    av_refstruct_unref(&fd->compacted_ref);
+    av_refstruct_unref(&fd->sizes_ref);
 
     return 0;
 }
@@ -852,20 +850,20 @@ static av_cold int vulkan_encode_apv_close(AVCodecContext 
*avctx)
     if (ev->exec_ctx_info) {
         for (int i = 0; i < ev->async_depth; i++) {
             VulkanEncodeAPVFrameData *fd = &ev->exec_ctx_info[i];
-            av_buffer_unref(&fd->coeffs_ref);
-            av_buffer_unref(&fd->bytestream_ref);
-            av_buffer_unref(&fd->compacted_ref);
-            av_buffer_unref(&fd->sizes_ref);
+            av_refstruct_unref(&fd->coeffs_ref);
+            av_refstruct_unref(&fd->bytestream_ref);
+            av_refstruct_unref(&fd->compacted_ref);
+            av_refstruct_unref(&fd->sizes_ref);
             av_buffer_unref(&fd->frame_opaque_ref);
         }
         av_freep(&ev->exec_ctx_info);
     }
 
-    av_buffer_pool_uninit(&ev->coeffs_pool);
-    av_buffer_pool_uninit(&ev->bytestream_pool);
-    av_buffer_pool_uninit(&ev->gathered_pool);
-    av_buffer_pool_uninit(&ev->compacted_pool);
-    av_buffer_pool_uninit(&ev->sizes_pool);
+    av_refstruct_pool_uninit(&ev->coeffs_pool);
+    av_refstruct_pool_uninit(&ev->bytestream_pool);
+    av_refstruct_pool_uninit(&ev->gathered_pool);
+    av_refstruct_pool_uninit(&ev->compacted_pool);
+    av_refstruct_pool_uninit(&ev->sizes_pool);
 
     ff_cbs_fragment_free(&ev->au);
     ff_cbs_close(&ev->cbc);
diff --git a/libavcodec/ffv1enc_vulkan.c b/libavcodec/ffv1enc_vulkan.c
index 34a18fcb57..2dd6e8c0cf 100644
--- a/libavcodec/ffv1enc_vulkan.c
+++ b/libavcodec/ffv1enc_vulkan.c
@@ -41,8 +41,8 @@
 
 typedef struct VulkanEncodeFFv1FrameData {
     /* Output data */
-    AVBufferRef *out_data_ref;
-    AVBufferRef *compacted_data_ref;
+    FFVkBuffer *out_data_ref;
+    FFVkBuffer *compacted_data_ref;
 
     /* Copied from the source */
     int64_t pts;
@@ -81,20 +81,20 @@ typedef struct VulkanEncodeFFv1Context {
     FFVkBuffer results_buf;
 
     /* Slice data buffer pool */
-    AVBufferPool *slice_data_pool;
-    AVBufferRef *keyframe_slice_data_ref;
+    AVRefStructPool *slice_data_pool;
+    FFVkBuffer *keyframe_slice_data_ref;
 
     /* Remap data pool */
-    AVBufferPool *remap_data_pool;
+    AVRefStructPool *remap_data_pool;
 
     /* Output data buffer */
-    AVBufferPool *out_data_pool;
+    AVRefStructPool *out_data_pool;
 
     /* Gathered (contiguous) device-local buffer pool */
-    AVBufferPool *gathered_data_pool;
+    AVRefStructPool *gathered_data_pool;
 
     /* Host-visible readback buffer pool */
-    AVBufferPool *compacted_data_pool;
+    AVRefStructPool *compacted_data_pool;
 
     /* Intermediate frame pool */
     AVBufferRef *intermediate_frames_ref;
@@ -289,22 +289,19 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext 
*avctx,
     VulkanEncodeFFv1FrameData *fd = exec->opaque;
 
     /* Slice data */
-    AVBufferRef *slice_data_ref;
     FFVkBuffer *slice_data_buf;
     uint32_t plane_state_size;
     uint32_t slice_state_size;
     uint32_t slice_data_size;
 
     /* Remap data */
-    AVBufferRef *remap_data_ref = NULL;
     FFVkBuffer *remap_data_buf = NULL;
     uint32_t remap_data_size = 0;
 
     /* Output data */
     size_t maxsize;
     FFVkBuffer *out_data_buf;
-    AVBufferRef *gathered_ref = NULL;
-    FFVkBuffer *gathered_buf;
+    FFVkBuffer *gathered_buf = NULL;
     FFVkBuffer *compacted_buf;
 
     int has_inter = avctx->gop_size > 1;
@@ -318,7 +315,7 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext 
*avctx,
     /* Frame state */
     f->cur_enc_frame = pict;
     if (avctx->gop_size == 0 || f->picture_number % avctx->gop_size == 0) {
-        av_buffer_unref(&fv->keyframe_slice_data_ref);
+        av_refstruct_unref(&fv->keyframe_slice_data_ref);
         f->key_frame = fd->key_frame = 1;
         f->gob_count++;
     } else {
@@ -341,19 +338,19 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext 
*avctx,
     slice_state_size = FFALIGN(slice_state_size, 8);
 
     /* Allocate slice data buffer */
-    slice_data_ref = fv->keyframe_slice_data_ref;
-    if (!slice_data_ref) {
+    slice_data_buf = fv->keyframe_slice_data_ref ?
+                     av_refstruct_ref(fv->keyframe_slice_data_ref) : NULL;
+    if (!slice_data_buf) {
         RET(ff_vk_get_pooled_buffer(&fv->s, &fv->slice_data_pool,
-                                    &slice_data_ref,
+                                    &slice_data_buf,
                                     VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
                                     NULL, slice_state_size*f->slice_count,
                                     VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
 
         /* Only save it if we're going to use it again */
         if (has_inter)
-            fv->keyframe_slice_data_ref = slice_data_ref;
+            fv->keyframe_slice_data_ref = av_refstruct_ref(slice_data_buf);
     }
-    slice_data_buf = (FFVkBuffer *)slice_data_ref->data;
 
     if (f->remap_mode) {
         if (fv->is_float32) {
@@ -365,11 +362,10 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext 
*avctx,
         }
 
         RET(ff_vk_get_pooled_buffer(&fv->s, &fv->remap_data_pool,
-                                    &remap_data_ref,
+                                    &remap_data_buf,
                                     VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
                                     NULL, remap_data_size*f->slice_count,
                                     VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
-        remap_data_buf = (FFVkBuffer *)remap_data_ref->data;
     }
 
     /* Output buffer size */
@@ -383,17 +379,16 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext 
*avctx,
                                 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
                                 NULL, maxsize,
                                 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
-    out_data_buf = (FFVkBuffer *)fd->out_data_ref->data;
+    out_data_buf = fd->out_data_ref;
 
     /* Device-local gather destination */
     RET(ff_vk_get_pooled_buffer(&fv->s, &fv->gathered_data_pool,
-                                &gathered_ref,
+                                &gathered_buf,
                                 VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
                                 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
                                 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
                                 NULL, maxsize,
                                 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
-    gathered_buf = (FFVkBuffer *)gathered_ref->data;
 
     /* Contiguous output, read back by the CPU. */
     RET(ff_vk_get_pooled_buffer(&fv->s, &fv->compacted_data_pool,
@@ -402,7 +397,7 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext 
*avctx,
                                 NULL, maxsize,
                                 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
                                 fv->s.host_cached_flag));
-    compacted_buf = (FFVkBuffer *)fd->compacted_data_ref->data;
+    compacted_buf = fd->compacted_data_ref;
 
     /* Image views */
     AVFrame *src = (AVFrame *)pict;
@@ -467,15 +462,8 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext 
*avctx,
                                 f->remap_mode ? FF_VK_REP_UINT
                                               : FF_VK_REP_NATIVE));
 
-    ff_vk_exec_add_dep_buf(&fv->s, exec, &slice_data_ref, 1, has_inter);
-    ff_vk_exec_add_dep_buf(&fv->s, exec, &fd->out_data_ref, 1, 1);
-    ff_vk_exec_add_dep_buf(&fv->s, exec, &gathered_ref, 1, 0);
-    gathered_ref = NULL; /* Ownership passed */
-    ff_vk_exec_add_dep_buf(&fv->s, exec, &fd->compacted_data_ref, 1, 1);
-    if (f->remap_mode) {
-        ff_vk_exec_add_dep_buf(&fv->s, exec, &remap_data_ref, 1, 0);
-        remap_data_ref = NULL;
-    }
+    ff_vk_exec_add_dep_refstruct(&fv->s, exec, fd->out_data_ref);
+    ff_vk_exec_add_dep_refstruct(&fv->s, exec, fd->compacted_data_ref);
 
     RET(ff_vk_exec_add_dep_frame(&fv->s, exec, src,
                                  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
@@ -758,20 +746,24 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext 
*avctx,
                       1, &(VkBufferCopy) { .size = maxsize });
 
     /* Submit */
+    ff_vk_exec_move_dep_refstruct(&fv->s, exec, &slice_data_buf);
+    ff_vk_exec_move_dep_refstruct(&fv->s, exec, &gathered_buf);
+    if (remap_data_buf)
+        ff_vk_exec_move_dep_refstruct(&fv->s, exec, &remap_data_buf);
     err = ff_vk_exec_submit(&fv->s, exec);
     if (err < 0)
-        return err;
+        goto fail;
 
     f->picture_number++;
 
-    /* This, if needed, was referenced by the execution context
-     * as it was declared as a dependency. */
     av_frame_free(&tmp);
     return 0;
 
 fail:
     av_frame_free(&tmp);
-    av_buffer_unref(&gathered_ref);
+    av_refstruct_unref(&slice_data_buf);
+    av_refstruct_unref(&remap_data_buf);
+    av_refstruct_unref(&gathered_buf);
     ff_vk_exec_discard_deps(&fv->s, exec);
 
     return err;
@@ -780,8 +772,7 @@ fail:
 /* Return the gathered-output buffer to its pool when the packet is freed. */
 static void ffv1_vk_packet_free(void *opaque, uint8_t *data)
 {
-    AVBufferRef *buf_ref = opaque;
-    av_buffer_unref(&buf_ref);
+    av_refstruct_unref(&opaque);
 }
 
 static int get_packet(AVCodecContext *avctx, FFVkExecContext *exec,
@@ -792,7 +783,7 @@ static int get_packet(AVCodecContext *avctx, 
FFVkExecContext *exec,
     FFVulkanFunctions *vk = &fv->s.vkfn;
     VulkanEncodeFFv1FrameData *fd = exec->opaque;
 
-    FFVkBuffer *compacted_buf = (FFVkBuffer *)fd->compacted_data_ref->data;
+    FFVkBuffer *compacted_buf = fd->compacted_data_ref;
 
     /* Make sure the encode + gather submission is done */
     ff_vk_exec_wait(&fv->s, exec);
@@ -837,8 +828,8 @@ static int get_packet(AVCodecContext *avctx, 
FFVkExecContext *exec,
     pkt->buf = av_buffer_create(compacted_buf->mapped_mem, compacted_buf->size,
                                 ffv1_vk_packet_free, fd->compacted_data_ref, 
0);
     if (!pkt->buf) {
-        av_buffer_unref(&fd->out_data_ref);
-        av_buffer_unref(&fd->compacted_data_ref);
+        av_refstruct_unref(&fd->out_data_ref);
+        av_refstruct_unref(&fd->compacted_data_ref);
         return AVERROR(ENOMEM);
     }
     fd->compacted_data_ref = NULL; /* ownership passed to pkt->buf */
@@ -855,7 +846,7 @@ static int get_packet(AVCodecContext *avctx, 
FFVkExecContext *exec,
         fd->frame_opaque_ref = NULL;
     }
 
-    av_buffer_unref(&fd->out_data_ref);
+    av_refstruct_unref(&fd->out_data_ref);
 
     return 0;
 }
@@ -1592,8 +1583,8 @@ static av_cold int 
vulkan_encode_ffv1_close(AVCodecContext *avctx)
     if (fv->exec_ctx_info) {
         for (int i = 0; i < fv->async_depth; i++) {
             VulkanEncodeFFv1FrameData *fd = &fv->exec_ctx_info[i];
-            av_buffer_unref(&fd->out_data_ref);
-            av_buffer_unref(&fd->compacted_data_ref);
+            av_refstruct_unref(&fd->out_data_ref);
+            av_refstruct_unref(&fd->compacted_data_ref);
             av_buffer_unref(&fd->frame_opaque_ref);
         }
     }
@@ -1601,13 +1592,13 @@ static av_cold int 
vulkan_encode_ffv1_close(AVCodecContext *avctx)
 
     av_buffer_unref(&fv->intermediate_frames_ref);
 
-    av_buffer_pool_uninit(&fv->out_data_pool);
-    av_buffer_pool_uninit(&fv->gathered_data_pool);
-    av_buffer_pool_uninit(&fv->compacted_data_pool);
+    av_refstruct_pool_uninit(&fv->out_data_pool);
+    av_refstruct_pool_uninit(&fv->gathered_data_pool);
+    av_refstruct_pool_uninit(&fv->compacted_data_pool);
 
-    av_buffer_unref(&fv->keyframe_slice_data_ref);
-    av_buffer_pool_uninit(&fv->slice_data_pool);
-    av_buffer_pool_uninit(&fv->remap_data_pool);
+    av_refstruct_unref(&fv->keyframe_slice_data_ref);
+    av_refstruct_pool_uninit(&fv->slice_data_pool);
+    av_refstruct_pool_uninit(&fv->remap_data_pool);
 
     ff_vk_free_buf(&fv->s, &fv->results_buf);
 
diff --git a/libavcodec/proresenc_kostya_vulkan.c 
b/libavcodec/proresenc_kostya_vulkan.c
index 2cbb039deb..97a107b8ea 100644
--- a/libavcodec/proresenc_kostya_vulkan.c
+++ b/libavcodec/proresenc_kostya_vulkan.c
@@ -77,10 +77,10 @@ typedef struct SliceScore {
 
 typedef struct VulkanEncodeProresFrameData {
     /* Intermediate buffers */
-    AVBufferRef *out_data_ref[2];
-    AVBufferRef *slice_data_ref[2];
-    AVBufferRef *slice_score_ref[2];
-    AVBufferRef *frame_size_ref[2];
+    FFVkBuffer *out_data_ref[2];
+    FFVkBuffer *slice_data_ref[2];
+    FFVkBuffer *slice_score_ref[2];
+    FFVkBuffer *frame_size_ref[2];
 
     /* Copied from the source */
     int64_t pts;
@@ -103,10 +103,10 @@ typedef struct ProresVulkanContext {
     FFVkExecPool e;
     AVVulkanDeviceQueueFamily *transfer_qf;
     FFVkExecPool transfer_exec_pool;
-    AVBufferPool *pkt_buf_pool;
-    AVBufferPool *slice_data_buf_pool;
-    AVBufferPool *slice_score_buf_pool;
-    AVBufferPool *frame_size_buf_pool;
+    AVRefStructPool *pkt_buf_pool;
+    AVRefStructPool *slice_data_buf_pool;
+    AVRefStructPool *slice_score_buf_pool;
+    AVRefStructPool *frame_size_buf_pool;
 
     FFVulkanShader alpha_data_shd;
     FFVulkanShader slice_data_shd[2];
@@ -399,8 +399,8 @@ static int vulkan_encode_prores_submit_frame(AVCodecContext 
*avctx, FFVkExecCont
                                                 : 
(VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
                                                    
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
                                                    
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)));
-    pkt_vk_buf = (FFVkBuffer*)pd->out_data_ref[picture_idx]->data;
-    ff_vk_exec_add_dep_buf(vkctx, exec, &pd->out_data_ref[picture_idx], 1, 1);
+    pkt_vk_buf = pd->out_data_ref[picture_idx];
+    ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->out_data_ref[picture_idx]);
 
     /* Allocate buffer for writing slice data */
     RET(ff_vk_get_pooled_buffer(vkctx, &pv->slice_data_buf_pool, 
&pd->slice_data_ref[picture_idx],
@@ -408,8 +408,8 @@ static int vulkan_encode_prores_submit_frame(AVCodecContext 
*avctx, FFVkExecCont
                                 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, 
NULL,
                                 ctx->slices_per_picture * sizeof(SliceData),
                                 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
-    slice_data_buf = (FFVkBuffer*)pd->slice_data_ref[picture_idx]->data;
-    ff_vk_exec_add_dep_buf(vkctx, exec, &pd->slice_data_ref[picture_idx], 1, 
1);
+    slice_data_buf = pd->slice_data_ref[picture_idx];
+    ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->slice_data_ref[picture_idx]);
 
     /* Allocate buffer for writing slice scores */
     RET(ff_vk_get_pooled_buffer(vkctx, &pv->slice_score_buf_pool, 
&pd->slice_score_ref[picture_idx],
@@ -417,8 +417,8 @@ static int vulkan_encode_prores_submit_frame(AVCodecContext 
*avctx, FFVkExecCont
                                 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, 
NULL,
                                 ctx->slices_per_picture * sizeof(SliceScore),
                                 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
-    slice_score_buf = (FFVkBuffer*)pd->slice_score_ref[picture_idx]->data;
-    ff_vk_exec_add_dep_buf(vkctx, exec, &pd->slice_score_ref[picture_idx], 1, 
1);
+    slice_score_buf = pd->slice_score_ref[picture_idx];
+    ff_vk_exec_add_dep_refstruct(vkctx, exec, 
pd->slice_score_ref[picture_idx]);
 
     /* Allocate buffer for writing frame size */
     RET(ff_vk_get_pooled_buffer(vkctx, &pv->frame_size_buf_pool, 
&pd->frame_size_ref[picture_idx],
@@ -428,8 +428,8 @@ static int vulkan_encode_prores_submit_frame(AVCodecContext 
*avctx, FFVkExecCont
                                 VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
                                 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
                                 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT));
-    frame_size_buf = (FFVkBuffer*)pd->frame_size_ref[picture_idx]->data;
-    ff_vk_exec_add_dep_buf(vkctx, exec, &pd->frame_size_ref[picture_idx], 1, 
1);
+    frame_size_buf = pd->frame_size_ref[picture_idx];
+    ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->frame_size_ref[picture_idx]);
 
     /* Generate barriers and image views for frame images. */
     RET(ff_vk_exec_add_dep_frame(vkctx, exec, frame,
@@ -645,8 +645,7 @@ static int get_packet(AVCodecContext *avctx, 
FFVkExecContext *exec, AVPacket *pk
     int transfer_slices = vkctx->extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY;
     FFVkBuffer *out_data_buf, *frame_size_buf;
     VkMappedMemoryRange invalidate_data;
-    AVBufferRef *mapped_ref;
-    FFVkBuffer *mapped_buf;
+    FFVkBuffer *mapped_buf = NULL;
 
     /* Allocate packet */
     RET(ff_get_encode_buffer(avctx, pkt, pkt_size + FF_INPUT_BUFFER_MIN_SIZE, 
0));
@@ -674,17 +673,16 @@ static int get_packet(AVCodecContext *avctx, 
FFVkExecContext *exec, AVPacket *pk
 
     /* Roll transfer execution context */
     if (transfer_slices) {
-        RET(ff_vk_host_map_buffer(vkctx, &mapped_ref, pkt->data, pkt->size,
+        RET(ff_vk_host_map_buffer(vkctx, &mapped_buf, pkt->data, pkt->size,
                                   pkt->buf, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
-        mapped_buf = (FFVkBuffer *)mapped_ref->data;
         transfer_exec = ff_vk_exec_get(vkctx, &pv->transfer_exec_pool);
         ff_vk_exec_start(vkctx, transfer_exec);
     }
 
     for (picture_idx = 0; picture_idx < ctx->pictures_per_frame; 
picture_idx++) {
         /* Fetch buffers for the current picture. */
-        out_data_buf = (FFVkBuffer *)pd->out_data_ref[picture_idx]->data;
-        frame_size_buf = (FFVkBuffer *)pd->frame_size_ref[picture_idx]->data;
+        out_data_buf = pd->out_data_ref[picture_idx];
+        frame_size_buf = pd->frame_size_ref[picture_idx];
 
         /* Invalidate slice/output data if needed */
         invalidate_data = (VkMappedMemoryRange) {
@@ -713,8 +711,7 @@ static int get_packet(AVCodecContext *avctx, 
FFVkExecContext *exec, AVPacket *pk
 
         if (transfer_slices) {
             /* Perform host mapped transfer of slice data */
-            ff_vk_exec_add_dep_buf(vkctx, transfer_exec, 
&pd->out_data_ref[picture_idx], 1, 0);
-            ff_vk_exec_add_dep_buf(vkctx, transfer_exec, &mapped_ref, 1, 0);
+            ff_vk_exec_move_dep_refstruct(vkctx, transfer_exec, 
&pd->out_data_ref[picture_idx]);
             vk->CmdCopyBuffer(transfer_exec->buf, out_data_buf->buf, 
mapped_buf->buf, 1, & (VkBufferCopy) {
                 .srcOffset = 0,
                 .dstOffset = mapped_buf->virtual_offset + slice_sizes - 
pkt->data,
@@ -727,7 +724,7 @@ static int get_packet(AVCodecContext *avctx, 
FFVkExecContext *exec, AVPacket *pk
                 vk->InvalidateMappedMemoryRanges(vkctx->hwctx->act_dev, 1, 
&invalidate_data);
             }
             memcpy(slice_sizes, out_data_buf->mapped_mem, buf - slice_sizes);
-            av_buffer_unref(&pd->out_data_ref[picture_idx]);
+            av_refstruct_unref(&pd->out_data_ref[picture_idx]);
         }
 
         /* Write picture size with header */
@@ -735,9 +732,9 @@ static int get_packet(AVCodecContext *avctx, 
FFVkExecContext *exec, AVPacket *pk
         bytestream_put_be32(&picture_size_pos, picture_size);
 
         /* Slice output buffers no longer needed */
-        av_buffer_unref(&pd->slice_data_ref[picture_idx]);
-        av_buffer_unref(&pd->slice_score_ref[picture_idx]);
-        av_buffer_unref(&pd->frame_size_ref[picture_idx]);
+        av_refstruct_unref(&pd->slice_data_ref[picture_idx]);
+        av_refstruct_unref(&pd->slice_score_ref[picture_idx]);
+        av_refstruct_unref(&pd->frame_size_ref[picture_idx]);
     }
 
     /* Write frame size in header */
@@ -750,11 +747,13 @@ static int get_packet(AVCodecContext *avctx, 
FFVkExecContext *exec, AVPacket *pk
 
     /* Wait for slice transfer */
     if (transfer_slices) {
+        ff_vk_exec_move_dep_refstruct(vkctx, transfer_exec, &mapped_buf);
         RET(ff_vk_exec_submit(vkctx, transfer_exec));
         ff_vk_exec_wait(vkctx, transfer_exec);
     }
 
 fail:
+    av_refstruct_unref(&mapped_buf);
     return err;
 }
 
@@ -841,10 +840,10 @@ static av_cold int encode_close(AVCodecContext *avctx)
 
     ff_vk_free_buf(vkctx, &pv->prores_data_tables_buf);
 
-    av_buffer_pool_uninit(&pv->pkt_buf_pool);
-    av_buffer_pool_uninit(&pv->slice_data_buf_pool);
-    av_buffer_pool_uninit(&pv->slice_score_buf_pool);
-    av_buffer_pool_uninit(&pv->frame_size_buf_pool);
+    av_refstruct_pool_uninit(&pv->pkt_buf_pool);
+    av_refstruct_pool_uninit(&pv->slice_data_buf_pool);
+    av_refstruct_pool_uninit(&pv->slice_score_buf_pool);
+    av_refstruct_pool_uninit(&pv->frame_size_buf_pool);
 
     ff_vk_uninit(vkctx);
 
diff --git a/libavcodec/vulkan_apv.c b/libavcodec/vulkan_apv.c
index 39546b2c9c..cd1320d2d0 100644
--- a/libavcodec/vulkan_apv.c
+++ b/libavcodec/vulkan_apv.c
@@ -38,7 +38,7 @@ const FFVulkanDecodeDescriptor ff_vk_dec_apv_desc = {
 typedef struct APVVulkanDecodePicture {
     FFVulkanDecodePicture vp;
 
-    AVBufferRef *frame_data_buf;
+    FFVkBuffer *frame_data_buf;
     uint32_t    *frame_data;
     int          tile_num;
 } APVVulkanDecodePicture;
@@ -47,11 +47,11 @@ typedef struct APVVulkanDecodeContext {
     FFVulkanShader decode;
     FFVulkanShader idct;
 
-    AVBufferPool *frame_data_pool;
+    AVRefStructPool *frame_data_pool;
 
     /* Flat per-frame coefficient buffer: entropy writes it, the iDCT reads it,
      * instead of bouncing coefficients through the output image. */
-    AVBufferPool *coeff_pool;
+    AVRefStructPool *coeff_pool;
     size_t        coeff_size;
 } APVVulkanDecodeContext;
 
@@ -100,7 +100,7 @@ static int vk_apv_start_frame(AVCodecContext          
*avctx,
         return err;
 
     /* Frame data */
-    FFVkBuffer *frame_data = (FFVkBuffer *)apvvp->frame_data_buf->data;
+    FFVkBuffer *frame_data = apvvp->frame_data_buf;
     uint8_t *fd = frame_data->mapped_mem;
 
     fd += 2*4*APV_MAX_TILE_COUNT*APV_MAX_NUM_COMP; /* Tile offsets go first */
@@ -135,8 +135,8 @@ static int vk_apv_decode_slice(AVCodecContext *avctx,
     APVVulkanDecodePicture *apvvp = apv->hwaccel_picture_private;
     FFVulkanDecodePicture *vp = &apvvp->vp;
 
-    FFVkBuffer *frame_data = (FFVkBuffer *)apvvp->frame_data_buf->data;
-    FFVkBuffer *slices_buf = vp->slices_buf ? (FFVkBuffer 
*)vp->slices_buf->data : NULL;
+    FFVkBuffer *frame_data = apvvp->frame_data_buf;
+    FFVkBuffer *slices_buf = vp->slices_buf;
 
     if (slices_buf && slices_buf->host_ref) {
         AV_WN32(frame_data->mapped_mem + (2*apvvp->tile_num + 
0)*sizeof(uint32_t),
@@ -174,8 +174,9 @@ static int vk_apv_end_frame(AVCodecContext *avctx)
     APVVulkanDecodePicture *apvvp = apv->hwaccel_picture_private;
     FFVulkanDecodePicture *vp = &apvvp->vp;
 
-    FFVkBuffer *slices_buf = (FFVkBuffer *)vp->slices_buf->data;
-    FFVkBuffer *frame_data_buf = (FFVkBuffer *)apvvp->frame_data_buf->data;
+    FFVkBuffer *slices_buf = vp->slices_buf;
+    FFVkBuffer *frame_data_buf = apvvp->frame_data_buf;
+    FFVkBuffer *coeff_buf = NULL;
 
     AVHWFramesContext *hwfc = (AVHWFramesContext *)avctx->hw_frames_ctx->data;
     enum AVPixelFormat sw_format = hwfc->sw_format;
@@ -203,10 +204,8 @@ static int vk_apv_end_frame(AVCodecContext *avctx)
     RET(ff_vk_create_imageviews(&ctx->s, exec, views, apv->output_frame,
                                 FF_VK_REP_NATIVE));
 
-    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0));
-    vp->slices_buf = NULL;
-    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &apvvp->frame_data_buf, 1, 0));
-    apvvp->frame_data_buf = NULL;
+    ff_vk_exec_move_dep_refstruct(&ctx->s, exec, &vp->slices_buf);
+    ff_vk_exec_move_dep_refstruct(&ctx->s, exec, &apvvp->frame_data_buf);
 
     AVVkFrame *vkf = (AVVkFrame *)apv->output_frame->data[0];
     vkf->layout[0] = VK_IMAGE_LAYOUT_UNDEFINED;
@@ -252,17 +251,13 @@ static int vk_apv_end_frame(AVCodecContext *avctx)
     nb_img_bar = 0;
 
     /* Zero-filled first, since entropy writes only the nonzero coefficients. 
*/
-    AVBufferRef *coeff_ref;
-    err = ff_vk_get_pooled_buffer(&ctx->s, &apvvk->coeff_pool, &coeff_ref,
+    err = ff_vk_get_pooled_buffer(&ctx->s, &apvvk->coeff_pool, &coeff_buf,
                                   VK_BUFFER_USAGE_TRANSFER_DST_BIT |
                                   VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
                                   NULL, apvvk->coeff_size,
                                   VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
     if (err < 0)
         return err;
-    FFVkBuffer *coeff_buf = (FFVkBuffer *)coeff_ref->data;
-    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &coeff_ref, 1, 0));
-
     vk->CmdFillBuffer(exec->buf, coeff_buf->buf, 0, VK_WHOLE_SIZE, 0);
 
     buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
@@ -371,12 +366,12 @@ static int vk_apv_end_frame(AVCodecContext *avctx)
     }
     vk->CmdDispatch(exec->buf, idct_cx, idct_by, desc->nb_components);
 
+    ff_vk_exec_move_dep_refstruct(&ctx->s, exec, &coeff_buf);
     err = ff_vk_exec_submit(&ctx->s, exec);
-    if (err < 0)
-        return err;
 
 fail:
-    return 0;
+    av_refstruct_unref(&coeff_buf);
+    return err < 0 ? err : 0;
 }
 
 static int init_decode_shader(AVCodecContext *avctx, FFVulkanContext *s,
@@ -483,8 +478,8 @@ static void vk_decode_apv_uninit(FFVulkanDecodeShared *ctx)
     ff_vk_shader_free(&ctx->s, &apvvk->decode);
     ff_vk_shader_free(&ctx->s, &apvvk->idct);
 
-    av_buffer_pool_uninit(&apvvk->frame_data_pool);
-    av_buffer_pool_uninit(&apvvk->coeff_pool);
+    av_refstruct_pool_uninit(&apvvk->frame_data_pool);
+    av_refstruct_pool_uninit(&apvvk->coeff_pool);
 
     av_freep(&apvvk);
 }
@@ -542,7 +537,7 @@ static void vk_apv_free_frame_priv(AVRefStructOpaque 
_hwctx, void *data)
 
     ff_vk_decode_free_frame(dev_ctx, vp);
 
-    av_buffer_unref(&apvvp->frame_data_buf);
+    av_refstruct_unref(&apvvp->frame_data_buf);
 }
 
 const FFHWAccel ff_apv_vulkan_hwaccel = {
diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c
index fb49e60e4d..970bf46c93 100644
--- a/libavcodec/vulkan_decode.c
+++ b/libavcodec/vulkan_decode.c
@@ -284,10 +284,9 @@ int ff_vk_decode_add_slice(AVCodecContext *avctx, 
FFVulkanDecodePicture *vp,
         slice_off[nb] = vp->slices_size;
     }
 
-    vkbuf = vp->slices_buf ? (FFVkBuffer *)vp->slices_buf->data : NULL;
+    vkbuf = vp->slices_buf;
     if (!vkbuf || vkbuf->size < new_size) {
         int err;
-        AVBufferRef *new_ref;
         FFVkBuffer *new_buf;
 
         /* No point in requesting anything smaller. */
@@ -306,7 +305,7 @@ int ff_vk_decode_add_slice(AVCodecContext *avctx, 
FFVulkanDecodePicture *vp,
             buf_pnext = (void *)ff_vk_find_struct(ctx->s.hwfc->create_pnext,
                                                   
VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
 
-        err = ff_vk_get_pooled_buffer(&ctx->s, &ctx->buf_pool, &new_ref,
+        err = ff_vk_get_pooled_buffer(&ctx->s, &ctx->buf_pool, &new_buf,
                                       DECODER_IS_SDR(avctx->codec_id) ?
                                       (VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
                                        
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) :
@@ -318,15 +317,13 @@ int ff_vk_decode_add_slice(AVCodecContext *avctx, 
FFVulkanDecodePicture *vp,
         if (err < 0)
             return err;
 
-        new_buf = (FFVkBuffer *)new_ref->data;
-
         /* Copy data from the old buffer */
         if (vkbuf) {
             memcpy(new_buf->mapped_mem, vkbuf->mapped_mem, vp->slices_size);
-            av_buffer_unref(&vp->slices_buf);
+            av_refstruct_unref(&vp->slices_buf);
         }
 
-        vp->slices_buf = new_ref;
+        vp->slices_buf = new_buf;
         vkbuf = new_buf;
     }
     slices = vkbuf->mapped_mem;
@@ -484,7 +481,7 @@ int ff_vk_decode_frame(AVCodecContext *avctx,
     cur_vk_ref[0].slotIndex = -1;
     decode_start.referenceSlotCount++;
 
-    sd_buf = (FFVkBuffer *)vp->slices_buf->data;
+    sd_buf = vp->slices_buf;
 
     /* Flush if needed */
     if (!(sd_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
@@ -514,11 +511,8 @@ int ff_vk_decode_frame(AVCodecContext *avctx,
         return err;
     cmd_buf = exec->buf;
 
-    /* Slices */
-    err = ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0);
-    if (err < 0)
-        return err;
-    vp->slices_buf = NULL; /* Owned by the exec buffer from now on */
+    /* Slices; owned by the execution from now on */
+    ff_vk_exec_move_dep_refstruct(&ctx->s, exec, &vp->slices_buf);
 
     /* Parameters */
     err = ff_vk_exec_add_dep_buf(&ctx->s, exec, &dec->session_params, 1, 1);
@@ -662,7 +656,7 @@ void ff_vk_decode_free_frame(AVHWDeviceContext *dev_ctx, 
FFVulkanDecodePicture *
         vp->wait_semaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
 
     /* Free slices data */
-    av_buffer_unref(&vp->slices_buf);
+    av_refstruct_unref(&vp->slices_buf);
 
     /* Destroy image view (out) */
     for (int i = 0; i < AV_NUM_DATA_POINTERS; i++) {
@@ -688,7 +682,7 @@ static void free_common(AVRefStructOpaque unused, void *obj)
     /* This also frees all references from this pool */
     av_frame_free(&ctx->common.layered_frame);
 
-    av_buffer_pool_uninit(&ctx->buf_pool);
+    av_refstruct_pool_uninit(&ctx->buf_pool);
 
     ff_vk_video_common_uninit(s, &ctx->common);
 
diff --git a/libavcodec/vulkan_decode.h b/libavcodec/vulkan_decode.h
index fe5ebcc07f..5c3837cb90 100644
--- a/libavcodec/vulkan_decode.h
+++ b/libavcodec/vulkan_decode.h
@@ -41,7 +41,7 @@ typedef struct FFVulkanDecodeShared {
     AVVulkanDeviceQueueFamily *qf;
     FFVkExecPool exec_pool;
 
-    AVBufferPool *buf_pool;
+    AVRefStructPool *buf_pool;
 
     VkVideoCapabilitiesKHR caps;
     VkVideoDecodeCapabilitiesKHR dec_caps;
@@ -96,7 +96,7 @@ typedef struct FFVulkanDecodePicture {
     VkVideoDecodeInfoKHR            decode_info;
 
     /* Slice data */
-    AVBufferRef                    *slices_buf;
+    FFVkBuffer                     *slices_buf;
     size_t                          slices_size;
 
     /* Vulkan functions needed for destruction, as no other context is 
guaranteed to exist */
@@ -155,12 +155,6 @@ int ff_vk_decode_frame(AVCodecContext *avctx,
  */
 void ff_vk_decode_free_frame(AVHWDeviceContext *dev_ctx, FFVulkanDecodePicture 
*vp);
 
-/**
- * Get an FFVkBuffer suitable for decoding from.
- */
-int ff_vk_get_decode_buffer(FFVulkanDecodeContext *ctx, AVBufferRef **buf,
-                            void *create_pNext, size_t size);
-
 /**
  * Create VkVideoSessionParametersKHR wrapped in an AVBufferRef.
  */
diff --git a/libavcodec/vulkan_dpx.c b/libavcodec/vulkan_dpx.c
index 706d34d299..a10ca42c0a 100644
--- a/libavcodec/vulkan_dpx.c
+++ b/libavcodec/vulkan_dpx.c
@@ -42,7 +42,7 @@ typedef struct DPXVulkanDecodePicture {
 
 typedef struct DPXVulkanDecodeContext {
     FFVulkanShader shader;
-    AVBufferPool *frame_data_pool;
+    AVRefStructPool *frame_data_pool;
 } DPXVulkanDecodeContext;
 
 typedef struct DecodePushData {
@@ -112,7 +112,7 @@ static int vk_dpx_end_frame(AVCodecContext *avctx)
     int unpack = (avctx->bits_per_raw_sample == 12 && !dpx->packing) ||
                  avctx->bits_per_raw_sample == 10;
 
-    FFVkBuffer *slices_buf = (FFVkBuffer *)vp->slices_buf->data;
+    FFVkBuffer *slices_buf = vp->slices_buf;
 
     VkImageMemoryBarrier2 img_bar[8];
     int nb_img_bar = 0;
@@ -131,8 +131,7 @@ static int vk_dpx_end_frame(AVCodecContext *avctx)
     RET(ff_vk_create_imageviews(&ctx->s, exec, views, dpx->frame,
                                 FF_VK_REP_NATIVE));
 
-    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0));
-    vp->slices_buf = NULL;
+    ff_vk_exec_move_dep_refstruct(&ctx->s, exec, &vp->slices_buf);
 
     AVVkFrame *vkf = (AVVkFrame *)dpx->frame->data[0];
     for (int i = 0; i < 4; i++) {
@@ -274,7 +273,7 @@ static void vk_decode_dpx_uninit(FFVulkanDecodeShared *ctx)
 
     ff_vk_shader_free(&ctx->s, &fv->shader);
 
-    av_buffer_pool_uninit(&fv->frame_data_pool);
+    av_refstruct_pool_uninit(&fv->frame_data_pool);
 
     av_freep(&fv);
 }
diff --git a/libavcodec/vulkan_encode.c b/libavcodec/vulkan_encode.c
index 1e69c73242..3a2cf101f4 100644
--- a/libavcodec/vulkan_encode.c
+++ b/libavcodec/vulkan_encode.c
@@ -68,7 +68,7 @@ av_cold void ff_vulkan_encode_uninit(FFVulkanEncodeContext 
*ctx)
     for (FFHWBaseEncodePicture *pic = ctx->base.pic_start; pic; pic = 
pic->next)
         vulkan_encode_free_pic(ctx, pic);
 
-    av_buffer_pool_uninit(&ctx->buf_pool);
+    av_refstruct_pool_uninit(&ctx->buf_pool);
 
     ff_hw_base_encode_close(&ctx->base);
 
@@ -201,7 +201,7 @@ static int vulkan_encode_issue(AVCodecContext *avctx,
     if (err < 0)
         return err;
 
-    sd_buf = (FFVkBuffer *)vp->pkt_buf->data;
+    sd_buf = vp->pkt_buf;
 
     /* Setup rate control */
     err = init_pic_rc(avctx, base_pic, &rc_info, &rc_layer);
@@ -358,9 +358,7 @@ static int vulkan_encode_issue(AVCodecContext *avctx,
     cmd_buf = exec->buf;
 
     /* Output packet buffer */
-    err = ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->pkt_buf, 1, 1);
-    if (err < 0)
-        goto fail;
+    ff_vk_exec_add_dep_refstruct(&ctx->s, exec, vp->pkt_buf);
 
     /* Source image */
     err = ff_vk_exec_add_dep_frame(&ctx->s, exec, src,
@@ -458,6 +456,11 @@ fail:
     return err;
 }
 
+static void pkt_buf_free(void *opaque, uint8_t *data)
+{
+    av_refstruct_unref(&opaque);
+}
+
 static void vulkan_encode_wait(AVCodecContext *avctx,
                                FFHWBaseEncodePicture *base_pic)
 {
@@ -482,7 +485,7 @@ static int vulkan_encode_output(AVCodecContext *avctx,
     FFHWBaseEncodeContext *base_ctx = &ctx->base;
     AVPacket *pkt_ptr = pkt;
 
-    FFVkBuffer *sd_buf = (FFVkBuffer *)vp->pkt_buf->data;
+    FFVkBuffer *sd_buf = vp->pkt_buf;
     uint32_t *query_data;
 
     vulkan_encode_wait(avctx, base_pic);
@@ -551,7 +554,7 @@ static int vulkan_encode_output(AVCodecContext *avctx,
         }
     } else {
         if (ctx->prev_buf_ref) {
-            FFVkBuffer *prev_sd_buf = (FFVkBuffer *)ctx->prev_buf_ref->data;
+            FFVkBuffer *prev_sd_buf = ctx->prev_buf_ref;
             size_t prev_size = ctx->prev_buf_size;
             size_t size = (vp->slices_offset + query_data[0] + query_data[1]);
 
@@ -562,17 +565,20 @@ static int vulkan_encode_output(AVCodecContext *avctx,
             memcpy(pkt->data, prev_sd_buf->mapped_mem, prev_size);
             memcpy(pkt->data + prev_size, sd_buf->mapped_mem, size);
 
-            av_buffer_unref(&ctx->prev_buf_ref);
-            av_buffer_unref(&vp->pkt_buf);
+            av_refstruct_unref(&ctx->prev_buf_ref);
+            av_refstruct_unref(&vp->pkt_buf);
         } else {
             pkt->data = sd_buf->mapped_mem;
             pkt->size = vp->slices_offset + /* base offset */
                         query_data[0]       /* secondary offset */ +
                         query_data[1]       /* size */;
 
-            /* Move reference */
-            pkt->buf = vp->pkt_buf;
-            vp->pkt_buf = NULL;
+            /* Hand the pooled buffer to the packet with no copy */
+            pkt->buf = av_buffer_create(sd_buf->mapped_mem, pkt->size,
+                                        pkt_buf_free, vp->pkt_buf, 0);
+            if (!pkt->buf)
+                return AVERROR(ENOMEM);
+            vp->pkt_buf = NULL; /* ownership passed to pkt->buf */
         }
     }
 
diff --git a/libavcodec/vulkan_encode.h b/libavcodec/vulkan_encode.h
index 23c35898c1..f55ba2640b 100644
--- a/libavcodec/vulkan_encode.h
+++ b/libavcodec/vulkan_encode.h
@@ -55,7 +55,7 @@ typedef struct FFVulkanEncodePicture {
     void                  *codec_rc_layer;
 
     FFVkExecContext       *exec;
-    AVBufferRef           *pkt_buf;
+    FFVkBuffer            *pkt_buf;
     int                    slices_offset;
 
     int non_independent_frame;
@@ -179,7 +179,7 @@ typedef struct FFVulkanEncodeContext {
      * and set here. */
     VkVideoSessionParametersKHR session_params;
 
-    AVBufferPool *buf_pool;
+    AVRefStructPool *buf_pool;
 
     VkFormat pic_format;
 
@@ -197,7 +197,7 @@ typedef struct FFVulkanEncodeContext {
 
     FFHWBaseEncodePicture *slots[32];
 
-    AVBufferRef *prev_buf_ref;
+    FFVkBuffer *prev_buf_ref;
     size_t prev_buf_size;
 } FFVulkanEncodeContext;
 
diff --git a/libavcodec/vulkan_ffv1.c b/libavcodec/vulkan_ffv1.c
index c21ddc66ac..b482df1e47 100644
--- a/libavcodec/vulkan_ffv1.c
+++ b/libavcodec/vulkan_ffv1.c
@@ -68,13 +68,13 @@ const FFVulkanDecodeDescriptor ff_vk_dec_ffv1_desc = {
 typedef struct FFv1VulkanDecodePicture {
     FFVulkanDecodePicture vp;
 
-    AVBufferRef *slice_state;
+    FFVkBuffer *slice_state;
     uint32_t plane_state_size;
     uint32_t slice_state_size;
     uint32_t slice_data_size;
 
-    AVBufferRef *slice_fltmap_buf;
-    AVBufferRef *slice_feedback_buf;
+    FFVkBuffer *slice_fltmap_buf;
+    FFVkBuffer *slice_feedback_buf;
     uint32_t    *slice_offset;
     int          slice_num;
     int          crc_checked;
@@ -89,9 +89,9 @@ typedef struct FFv1VulkanDecodeContext {
 
     FFVkBuffer consts_buf;
 
-    AVBufferPool *slice_state_pool;
-    AVBufferPool *slice_fltmap_pool;
-    AVBufferPool *slice_feedback_pool;
+    AVRefStructPool *slice_state_pool;
+    AVRefStructPool *slice_fltmap_pool;
+    AVRefStructPool *slice_feedback_pool;
 } FFv1VulkanDecodeContext;
 
 static int vk_ffv1_start_frame(AVCodecContext          *avctx,
@@ -165,9 +165,7 @@ static int vk_ffv1_start_frame(AVCodecContext          
*avctx,
         if (!fpl || !fpl->slice_state)
             return AVERROR_INVALIDDATA;
 
-        fp->slice_state = av_buffer_ref(fpl->slice_state);
-        if (!fp->slice_state)
-            return AVERROR(ENOMEM);
+        fp->slice_state = av_refstruct_ref(fpl->slice_state);
     }
 
     /* Allocate slice offsets/status buffer */
@@ -217,8 +215,8 @@ static int vk_ffv1_decode_slice(AVCodecContext *avctx,
     FFv1VulkanDecodePicture *fp = f->hwaccel_picture_private;
     FFVulkanDecodePicture *vp = &fp->vp;
 
-    FFVkBuffer *slice_offset = (FFVkBuffer *)fp->slice_feedback_buf->data;
-    FFVkBuffer *slices_buf = vp->slices_buf ? (FFVkBuffer 
*)vp->slices_buf->data : NULL;
+    FFVkBuffer *slice_offset = fp->slice_feedback_buf;
+    FFVkBuffer *slices_buf = vp->slices_buf;
 
     if (slices_buf && slices_buf->host_ref) {
         AV_WN32(slice_offset->mapped_mem + (2*fp->slice_num + 
0)*sizeof(uint32_t),
@@ -263,12 +261,12 @@ static int vk_ffv1_end_frame(AVCodecContext *avctx)
     FFv1VulkanDecodePicture *fp = f->hwaccel_picture_private;
     FFVulkanDecodePicture *vp = &fp->vp;
 
-    FFVkBuffer *slices_buf = (FFVkBuffer *)vp->slices_buf->data;
-    FFVkBuffer *slice_state = (FFVkBuffer *)fp->slice_state->data;
-    FFVkBuffer *slice_feedback = (FFVkBuffer *)fp->slice_feedback_buf->data;
+    FFVkBuffer *slices_buf = vp->slices_buf;
+    FFVkBuffer *slice_state = fp->slice_state;
+    FFVkBuffer *slice_feedback = fp->slice_feedback_buf;
     FFVkBuffer *fltmap_buf = NULL;
     if (fp->slice_fltmap_buf)
-        fltmap_buf = (FFVkBuffer *)fp->slice_fltmap_buf->data;
+        fltmap_buf = fp->slice_fltmap_buf;
 
     VkImageView output_views[AV_NUM_DATA_POINTERS];
     VkImageView rct_image_views[AV_NUM_DATA_POINTERS];
@@ -314,15 +312,12 @@ static int vk_ffv1_end_frame(AVCodecContext *avctx)
                                         VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
     }
 
-    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &fp->slice_state, 1, 1));
-    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &fp->slice_feedback_buf, 1, 1));
-    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0));
-    vp->slices_buf = NULL;
+    ff_vk_exec_add_dep_refstruct(&ctx->s, exec, fp->slice_state);
+    ff_vk_exec_add_dep_refstruct(&ctx->s, exec, fp->slice_feedback_buf);
+    ff_vk_exec_move_dep_refstruct(&ctx->s, exec, &vp->slices_buf);
 
-    if (fp->slice_fltmap_buf) {
-        RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &fp->slice_fltmap_buf, 1, 
0));
-        fp->slice_fltmap_buf = NULL;
-    }
+    if (fp->slice_fltmap_buf)
+        ff_vk_exec_move_dep_refstruct(&ctx->s, exec, &fp->slice_fltmap_buf);
 
     AVVkFrame *vkf = (AVVkFrame *)f->picture.f->data[0];
     for (int i = 0; i < ff_vk_count_images(vkf); i++) {
@@ -835,9 +830,9 @@ static void vk_decode_ffv1_uninit(FFVulkanDecodeShared *ctx)
 
     ff_vk_free_buf(&ctx->s, &fv->consts_buf);
 
-    av_buffer_pool_uninit(&fv->slice_state_pool);
-    av_buffer_pool_uninit(&fv->slice_fltmap_pool);
-    av_buffer_pool_uninit(&fv->slice_feedback_pool);
+    av_refstruct_pool_uninit(&fv->slice_state_pool);
+    av_refstruct_pool_uninit(&fv->slice_fltmap_pool);
+    av_refstruct_pool_uninit(&fv->slice_feedback_pool);
 
     av_freep(&fv);
 }
@@ -949,7 +944,7 @@ static void vk_ffv1_free_frame_priv(AVRefStructOpaque 
_hwctx, void *data)
 
     /* No feedback to read if setup failed or the decode was never submitted */
     if (fp->slice_feedback_buf && vp->sem) {
-        FFVkBuffer *slice_feedback = (FFVkBuffer 
*)fp->slice_feedback_buf->data;
+        FFVkBuffer *slice_feedback = fp->slice_feedback_buf;
         uint8_t *ssp = slice_feedback->mapped_mem + 
2*fp->slice_num*sizeof(uint32_t);
 
         /* Invalidate slice/output data if needed */
@@ -982,8 +977,8 @@ static void vk_ffv1_free_frame_priv(AVRefStructOpaque 
_hwctx, void *data)
                    slice_error_cnt, max_overread, crc_mismatch_cnt);
     }
 
-    av_buffer_unref(&fp->slice_state);
-    av_buffer_unref(&fp->slice_feedback_buf);
+    av_refstruct_unref(&fp->slice_state);
+    av_refstruct_unref(&fp->slice_feedback_buf);
 }
 
 const FFHWAccel ff_ffv1_vulkan_hwaccel = {
diff --git a/libavcodec/vulkan_prores.c b/libavcodec/vulkan_prores.c
index 77bd99acc9..6040dcc5f1 100644
--- a/libavcodec/vulkan_prores.c
+++ b/libavcodec/vulkan_prores.c
@@ -36,7 +36,7 @@ const FFVulkanDecodeDescriptor ff_vk_dec_prores_desc = {
 typedef struct ProresVulkanDecodePicture {
     FFVulkanDecodePicture vp;
 
-    AVBufferRef *metadata_buf;
+    FFVkBuffer *metadata_buf;
 
     uint32_t bitstream_start;
     uint32_t bitstream_size;
@@ -50,7 +50,7 @@ typedef struct ProresVulkanDecodeContext {
     FFVulkanShader vld;
     FFVulkanShader idct;
 
-    AVBufferPool *metadata_pool;
+    AVRefStructPool *metadata_pool;
 } ProresVulkanDecodeContext;
 
 typedef struct ProresVkParameters {
@@ -124,8 +124,8 @@ static int vk_prores_decode_slice(AVCodecContext *avctx,
     ProresVulkanDecodePicture *pp = pr->hwaccel_picture_private;
     FFVulkanDecodePicture     *vp = &pp->vp;
 
-    FFVkBuffer *slice_offset = (FFVkBuffer *)pp->metadata_buf->data;
-    FFVkBuffer *slices_buf   = vp->slices_buf ? (FFVkBuffer 
*)vp->slices_buf->data : NULL;
+    FFVkBuffer *slice_offset = pp->metadata_buf;
+    FFVkBuffer *slices_buf   = vp->slices_buf;
 
     /* Skip picture header */
     if (slices_buf && slices_buf->host_ref && !pp->slice_num)
@@ -174,8 +174,8 @@ static int vk_prores_end_frame(AVCodecContext *avctx)
     if (!pix_desc)
         return AVERROR(EINVAL);
 
-    slice_data = (FFVkBuffer *)vp->slices_buf->data;
-    metadata   = (FFVkBuffer *)pp->metadata_buf->data;
+    slice_data = vp->slices_buf;
+    metadata   = pp->metadata_buf;
 
     pd = (ProresVkParameters) {
         .slice_data       = slice_data->address,
@@ -212,11 +212,8 @@ static int vk_prores_end_frame(AVCodecContext *avctx)
     VkImageView views[AV_NUM_DATA_POINTERS];
     RET(ff_vk_create_imageviews(&ctx->s, exec, views, f, FF_VK_REP_NATIVE));
 
-    /* Transfer ownership to the exec context */
-    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0));
-    vp->slices_buf = NULL;
-    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &pp->metadata_buf, 1, 0));
-    pp->metadata_buf = NULL;
+    ff_vk_exec_move_dep_refstruct(&ctx->s, exec, &vp->slices_buf);
+    ff_vk_exec_move_dep_refstruct(&ctx->s, exec, &pp->metadata_buf);
 
     vkf->layout[0] = VK_IMAGE_LAYOUT_UNDEFINED;
     vkf->access[0] = VK_ACCESS_2_NONE;
@@ -462,7 +459,7 @@ static void vk_decode_prores_uninit(FFVulkanDecodeShared 
*ctx)
     ff_vk_shader_free(&ctx->s, &pv->vld);
     ff_vk_shader_free(&ctx->s, &pv->idct);
 
-    av_buffer_pool_uninit(&pv->metadata_pool);
+    av_refstruct_pool_uninit(&pv->metadata_pool);
 
     av_freep(&pv);
 }
@@ -507,7 +504,7 @@ static void vk_prores_free_frame_priv(AVRefStructOpaque 
_hwctx, void *data)
 
     ff_vk_decode_free_frame(dev_ctx, &pp->vp);
 
-    av_buffer_unref(&pp->metadata_buf);
+    av_refstruct_unref(&pp->metadata_buf);
 }
 
 const FFHWAccel ff_prores_vulkan_hwaccel = {
diff --git a/libavcodec/vulkan_prores_raw.c b/libavcodec/vulkan_prores_raw.c
index 398a1661cc..874e55506e 100644
--- a/libavcodec/vulkan_prores_raw.c
+++ b/libavcodec/vulkan_prores_raw.c
@@ -38,7 +38,7 @@ const FFVulkanDecodeDescriptor ff_vk_dec_prores_raw_desc = {
 typedef struct ProResRAWVulkanDecodePicture {
     FFVulkanDecodePicture vp;
 
-    AVBufferRef *frame_data_buf;
+    FFVkBuffer *frame_data_buf;
     uint32_t nb_tiles;
 } ProResRAWVulkanDecodePicture;
 
@@ -46,7 +46,7 @@ typedef struct ProResRAWVulkanDecodeContext {
     FFVulkanShader decode;
     FFVulkanShader idct;
 
-    AVBufferPool *frame_data_pool;
+    AVRefStructPool *frame_data_pool;
 } ProResRAWVulkanDecodeContext;
 
 typedef struct DecodePushData {
@@ -105,10 +105,9 @@ static int vk_prores_raw_decode_slice(AVCodecContext 
*avctx,
     ProResRAWVulkanDecodePicture *pp = prr->hwaccel_picture_private;
     FFVulkanDecodePicture *vp = &pp->vp;
 
-    FFVkBuffer *frame_data_buf = (FFVkBuffer *)pp->frame_data_buf->data;
+    FFVkBuffer *frame_data_buf = pp->frame_data_buf;
     TileData *td = (TileData *)frame_data_buf->mapped_mem;
-    FFVkBuffer *slices_buf = vp->slices_buf ?
-                             (FFVkBuffer *)vp->slices_buf->data : NULL;
+    FFVkBuffer *slices_buf = vp->slices_buf;
 
     td[pp->nb_tiles].pos[0] = prr->tiles[pp->nb_tiles].x;
     td[pp->nb_tiles].pos[1] = prr->tiles[pp->nb_tiles].y;
@@ -143,8 +142,8 @@ static int vk_prores_raw_end_frame(AVCodecContext *avctx)
     ProResRAWVulkanDecodePicture *pp = prr->hwaccel_picture_private;
     FFVulkanDecodePicture *vp = &pp->vp;
 
-    FFVkBuffer *slices_buf = (FFVkBuffer *)vp->slices_buf->data;
-    FFVkBuffer *frame_data_buf = (FFVkBuffer *)pp->frame_data_buf->data;
+    FFVkBuffer *slices_buf = vp->slices_buf;
+    FFVkBuffer *frame_data_buf = pp->frame_data_buf;
 
     VkImageMemoryBarrier2 img_bar[8];
     int nb_img_bar = 0;
@@ -163,10 +162,8 @@ static int vk_prores_raw_end_frame(AVCodecContext *avctx)
     RET(ff_vk_create_imageviews(&ctx->s, exec, views, prr->frame,
                                 FF_VK_REP_NATIVE));
 
-    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &pp->frame_data_buf, 1, 0));
-    pp->frame_data_buf = NULL;
-    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0));
-    vp->slices_buf = NULL;
+    ff_vk_exec_move_dep_refstruct(&ctx->s, exec, &pp->frame_data_buf);
+    ff_vk_exec_move_dep_refstruct(&ctx->s, exec, &vp->slices_buf);
 
     AVVkFrame *vkf = (AVVkFrame *)prr->frame->data[0];
     vkf->layout[0] = VK_IMAGE_LAYOUT_UNDEFINED;
@@ -363,7 +360,7 @@ static void 
vk_decode_prores_raw_uninit(FFVulkanDecodeShared *ctx)
     ff_vk_shader_free(&ctx->s, &fv->decode);
     ff_vk_shader_free(&ctx->s, &fv->idct);
 
-    av_buffer_pool_uninit(&fv->frame_data_pool);
+    av_refstruct_pool_uninit(&fv->frame_data_pool);
 
     av_freep(&fv);
 }
@@ -406,7 +403,7 @@ static void vk_prores_raw_free_frame_priv(AVRefStructOpaque 
_hwctx, void *data)
 
     ff_vk_decode_free_frame(dev_ctx, vp);
 
-    av_buffer_unref(&pp->frame_data_buf);
+    av_refstruct_unref(&pp->frame_data_buf);
 }
 
 const FFHWAccel ff_prores_raw_vulkan_hwaccel = {
diff --git a/libavfilter/vf_blackdetect_vulkan.c 
b/libavfilter/vf_blackdetect_vulkan.c
index f296e62cc4..a1908e7019 100644
--- a/libavfilter/vf_blackdetect_vulkan.c
+++ b/libavfilter/vf_blackdetect_vulkan.c
@@ -35,7 +35,7 @@ typedef struct BlackDetectVulkanContext {
     FFVkExecPool e;
     AVVulkanDeviceQueueFamily *qf;
     FFVulkanShader shd;
-    AVBufferPool *sum_buf_pool;
+    AVRefStructPool *sum_buf_pool;
 
     double picture_black_ratio_th;
     double pixel_black_th;
@@ -182,8 +182,7 @@ static int blackdetect_vulkan_filter_frame(AVFilterLink 
*link, AVFrame *in)
     FFVulkanContext *vkctx = &s->vkctx;
     FFVulkanFunctions *vk = &vkctx->vkfn;
     FFVkExecContext *exec = NULL;
-    AVBufferRef *sum_buf = NULL;
-    FFVkBuffer *sum_vk;
+    FFVkBuffer *sum_vk = NULL;
 
     BlackDetectBuf *sum;
     BlackDetectPushData push_data;
@@ -202,7 +201,7 @@ static int blackdetect_vulkan_filter_frame(AVFilterLink 
*link, AVFrame *in)
     if (!s->initialized)
         RET(init_filter(ctx));
 
-    err = ff_vk_get_pooled_buffer(vkctx, &s->sum_buf_pool, &sum_buf,
+    err = ff_vk_get_pooled_buffer(vkctx, &s->sum_buf_pool, &sum_vk,
                                   VK_BUFFER_USAGE_TRANSFER_DST_BIT |
                                   VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
                                   NULL,
@@ -212,7 +211,6 @@ static int blackdetect_vulkan_filter_frame(AVFilterLink 
*link, AVFrame *in)
                                   VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
     if (err < 0)
         return err;
-    sum_vk = (FFVkBuffer *)sum_buf->data;
     sum = (BlackDetectBuf *) sum_vk->mapped_mem;
 
     exec = ff_vk_exec_get(vkctx, &s->e);
@@ -308,14 +306,14 @@ static int blackdetect_vulkan_filter_frame(AVFilterLink 
*link, AVFrame *in)
     evaluate(link, in, sum);
     s->last_pts = in->pts;
 
-    av_buffer_unref(&sum_buf);
+    av_refstruct_unref(&sum_vk);
     return ff_filter_frame(outlink, in);
 
 fail:
     if (exec)
         ff_vk_exec_discard_deps(&s->vkctx, exec);
     av_frame_free(&in);
-    av_buffer_unref(&sum_buf);
+    av_refstruct_unref(&sum_vk);
     return err;
 }
 
@@ -332,7 +330,7 @@ static void blackdetect_vulkan_uninit(AVFilterContext 
*avctx)
     ff_vk_exec_pool_free(vkctx, &s->e);
     ff_vk_shader_free(vkctx, &s->shd);
 
-    av_buffer_pool_uninit(&s->sum_buf_pool);
+    av_refstruct_pool_uninit(&s->sum_buf_pool);
 
     ff_vk_uninit(&s->vkctx);
 
diff --git a/libavfilter/vf_nlmeans_vulkan.c b/libavfilter/vf_nlmeans_vulkan.c
index 2a41f6fd8d..b8615316df 100644
--- a/libavfilter/vf_nlmeans_vulkan.c
+++ b/libavfilter/vf_nlmeans_vulkan.c
@@ -46,8 +46,8 @@ typedef struct NLMeansVulkanContext {
     FFVkExecPool e;
     AVVulkanDeviceQueueFamily *qf;
 
-    AVBufferPool *integral_buf_pool;
-    AVBufferPool *ws_buf_pool;
+    AVRefStructPool *integral_buf_pool;
+    AVRefStructPool *ws_buf_pool;
 
     FFVkBuffer xyoffsets_buf;
 
@@ -442,14 +442,12 @@ static int nlmeans_vulkan_filter_frame(AVFilterLink 
*link, AVFrame *in)
     int offsets_dispatched = 0;
 
     /* Integral */
-    AVBufferRef *integral_buf = NULL;
-    FFVkBuffer *integral_vk;
+    FFVkBuffer *integral_vk = NULL;
     size_t int_stride;
     size_t int_size;
 
     /* Weights/sums */
-    AVBufferRef *ws_buf = NULL;
-    FFVkBuffer *ws_vk;
+    FFVkBuffer *ws_vk = NULL;
     uint32_t ws_count = 0;
     uint32_t ws_offset[4];
     uint32_t ws_stride[4];
@@ -492,7 +490,7 @@ static int nlmeans_vulkan_filter_frame(AVFilterLink *link, 
AVFrame *in)
     ws_size = ws_count * sizeof(float);
 
     /* Buffers */
-    err = ff_vk_get_pooled_buffer(&s->vkctx, &s->integral_buf_pool, 
&integral_buf,
+    err = ff_vk_get_pooled_buffer(&s->vkctx, &s->integral_buf_pool, 
&integral_vk,
                                   VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
                                   VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
                                   NULL,
@@ -500,9 +498,7 @@ static int nlmeans_vulkan_filter_frame(AVFilterLink *link, 
AVFrame *in)
                                   VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
     if (err < 0)
         return err;
-    integral_vk = (FFVkBuffer *)integral_buf->data;
-
-    err = ff_vk_get_pooled_buffer(&s->vkctx, &s->ws_buf_pool, &ws_buf,
+    err = ff_vk_get_pooled_buffer(&s->vkctx, &s->ws_buf_pool, &ws_vk,
                                   VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
                                   VK_BUFFER_USAGE_TRANSFER_DST_BIT,
                                   NULL,
@@ -510,8 +506,6 @@ static int nlmeans_vulkan_filter_frame(AVFilterLink *link, 
AVFrame *in)
                                   VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
     if (err < 0)
         return err;
-    ws_vk = (FFVkBuffer *)ws_buf->data;
-
     /* Output frame */
     out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
     if (!out) {
@@ -531,12 +525,6 @@ static int nlmeans_vulkan_filter_frame(AVFilterLink *link, 
AVFrame *in)
                                  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
                                  VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
 
-    RET(ff_vk_exec_add_dep_buf(vkctx, exec, &integral_buf, 1, 0));
-    integral_buf = NULL;
-
-    RET(ff_vk_exec_add_dep_buf(vkctx, exec, &ws_buf,       1, 0));
-    ws_buf = NULL;
-
     /* Input frame prep */
     RET(ff_vk_create_imageviews(vkctx, exec, in_views, in, FF_VK_REP_FLOAT));
     ff_vk_frame_barrier(vkctx, exec, in, img_bar, &nb_img_bar,
@@ -724,9 +712,11 @@ static int nlmeans_vulkan_filter_frame(AVFilterLink *link, 
AVFrame *in)
     RET(denoise_pass(s, exec, ws_vk, comp_offs, comp_planes, ws_offset, 
ws_stride,
                      ws_count, s->opts.t, desc->nb_components));
 
+    ff_vk_exec_move_dep_refstruct(vkctx, exec, &integral_vk);
+    ff_vk_exec_move_dep_refstruct(vkctx, exec, &ws_vk);
     err = ff_vk_exec_submit(vkctx, exec);
     if (err < 0)
-        return err;
+        goto fail;
 
     err = av_frame_copy_props(out, in);
     if (err < 0)
@@ -737,8 +727,8 @@ static int nlmeans_vulkan_filter_frame(AVFilterLink *link, 
AVFrame *in)
     return ff_filter_frame(outlink, out);
 
 fail:
-    av_buffer_unref(&integral_buf);
-    av_buffer_unref(&ws_buf);
+    av_refstruct_unref(&integral_vk);
+    av_refstruct_unref(&ws_vk);
     av_frame_free(&in);
     av_frame_free(&out);
     return err;
@@ -755,8 +745,8 @@ static void nlmeans_vulkan_uninit(AVFilterContext *avctx)
     ff_vk_shader_free(vkctx, &s->shd_weights);
     ff_vk_shader_free(vkctx, &s->shd_denoise);
 
-    av_buffer_pool_uninit(&s->integral_buf_pool);
-    av_buffer_pool_uninit(&s->ws_buf_pool);
+    av_refstruct_pool_uninit(&s->integral_buf_pool);
+    av_refstruct_pool_uninit(&s->ws_buf_pool);
 
     ff_vk_uninit(&s->vkctx);
 
diff --git a/libavfilter/vf_scdet_vulkan.c b/libavfilter/vf_scdet_vulkan.c
index 6f5b0b30f2..f87c780dfc 100644
--- a/libavfilter/vf_scdet_vulkan.c
+++ b/libavfilter/vf_scdet_vulkan.c
@@ -35,7 +35,7 @@ typedef struct SceneDetectVulkanContext {
     FFVkExecPool e;
     AVVulkanDeviceQueueFamily *qf;
     FFVulkanShader shd;
-    AVBufferPool *det_buf_pool;
+    AVRefStructPool *det_buf_pool;
 
     double threshold;
     int sc_pass;
@@ -144,8 +144,7 @@ static int scdet_vulkan_filter_frame(AVFilterLink *link, 
AVFrame *in)
     FFVulkanContext *vkctx = &s->vkctx;
     FFVulkanFunctions *vk = &vkctx->vkfn;
     FFVkExecContext *exec = NULL;
-    AVBufferRef *buf = NULL;
-    FFVkBuffer *buf_vk;
+    FFVkBuffer *buf_vk = NULL;
 
     SceneDetectBuf *sad;
     double score = 0.0;
@@ -160,7 +159,7 @@ static int scdet_vulkan_filter_frame(AVFilterLink *link, 
AVFrame *in)
     if (!s->prev)
         goto done;
 
-    RET(ff_vk_get_pooled_buffer(vkctx, &s->det_buf_pool, &buf,
+    RET(ff_vk_get_pooled_buffer(vkctx, &s->det_buf_pool, &buf_vk,
                                 VK_BUFFER_USAGE_TRANSFER_DST_BIT |
                                 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
                                 NULL,
@@ -168,7 +167,6 @@ static int scdet_vulkan_filter_frame(AVFilterLink *link, 
AVFrame *in)
                                 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
                                 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
                                 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT));
-    buf_vk = (FFVkBuffer *)buf->data;
     sad = (SceneDetectBuf *) buf_vk->mapped_mem;
 
     exec = ff_vk_exec_get(vkctx, &s->e);
@@ -289,7 +287,7 @@ done:
                score, pts);
     }
 
-    av_buffer_unref(&buf);
+    av_refstruct_unref(&buf_vk);
     if (!s->sc_pass || score >= s->threshold)
         return ff_filter_frame(outlink, in);
     else {
@@ -301,7 +299,7 @@ fail:
     if (exec)
         ff_vk_exec_discard_deps(&s->vkctx, exec);
     av_frame_free(&in);
-    av_buffer_unref(&buf);
+    av_refstruct_unref(&buf_vk);
     return err;
 }
 
@@ -316,7 +314,7 @@ static void scdet_vulkan_uninit(AVFilterContext *avctx)
     ff_vk_exec_pool_free(vkctx, &s->e);
     ff_vk_shader_free(vkctx, &s->shd);
 
-    av_buffer_pool_uninit(&s->det_buf_pool);
+    av_refstruct_pool_uninit(&s->det_buf_pool);
 
     ff_vk_uninit(&s->vkctx);
 
diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index 3d2bbb3c7c..ed27c78371 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -191,7 +191,7 @@ typedef struct VulkanFramesPriv {
     FFVkExecPool download_exec;
 
     /* Temporary buffer pools */
-    AVBufferPool *tmp;
+    AVRefStructPool *tmp;
 
     /* Modifier info list to free at uninit */
     VkImageDrmFormatModifierListCreateInfoEXT *modifier_info;
@@ -2955,7 +2955,7 @@ static void vulkan_frames_uninit(AVHWFramesContext *hwfc)
     ff_vk_exec_pool_free(&p->vkctx, &fp->upload_exec);
     ff_vk_exec_pool_free(&p->vkctx, &fp->download_exec);
 
-    av_buffer_pool_uninit(&fp->tmp);
+    av_refstruct_pool_uninit(&fp->tmp);
 }
 
 static int vulkan_frames_init(AVHWFramesContext *hwfc)
@@ -4434,13 +4434,12 @@ static int vulkan_map_from(AVHWFramesContext *hwfc, 
AVFrame *dst,
     return AVERROR(ENOSYS);
 }
 
-static int copy_buffer_data(AVHWFramesContext *hwfc, AVBufferRef *buf,
+static int copy_buffer_data(AVHWFramesContext *hwfc, FFVkBuffer *vkbuf,
                             AVFrame *swf, VkBufferImageCopy *region,
                             int planes, int upload)
 {
     int err;
     VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
-    FFVkBuffer *vkbuf = (FFVkBuffer *)buf->data;
 
     if (upload) {
         for (int i = 0; i < planes; i++)
@@ -4477,7 +4476,7 @@ static int copy_buffer_data(AVHWFramesContext *hwfc, 
AVBufferRef *buf,
     return 0;
 }
 
-static int get_plane_buf(AVHWFramesContext *hwfc, AVBufferRef **dst,
+static int get_plane_buf(AVHWFramesContext *hwfc, FFVkBuffer **dst,
                          AVFrame *swf, VkBufferImageCopy *region, int upload)
 {
     int err;
@@ -4516,7 +4515,7 @@ static int get_plane_buf(AVHWFramesContext *hwfc, 
AVBufferRef **dst,
     return 0;
 }
 
-static int host_map_frame(AVHWFramesContext *hwfc, AVBufferRef **dst, int 
*nb_bufs,
+static int host_map_frame(AVHWFramesContext *hwfc, FFVkBuffer **dst, int 
*nb_bufs,
                           AVFrame *swf, VkBufferImageCopy *region, int upload)
 {
     int err;
@@ -4547,7 +4546,7 @@ static int host_map_frame(AVHWFramesContext *hwfc, 
AVBufferRef **dst, int *nb_bu
         (*nb_bufs)++;
 
         for (int i = 0; i < planes; i++)
-            region[i].bufferOffset = ((FFVkBuffer 
*)dst[0]->data)->virtual_offset +
+            region[i].bufferOffset = dst[0]->virtual_offset +
                                      swf->data[i] - swf->data[0];
     } else if (nb_src_bufs == planes) { /* One buffer per plane */
         for (int i = 0; i < planes; i++) {
@@ -4558,7 +4557,7 @@ static int host_map_frame(AVHWFramesContext *hwfc, 
AVBufferRef **dst, int *nb_bu
                 goto fail;
             (*nb_bufs)++;
 
-            region[i].bufferOffset = ((FFVkBuffer 
*)dst[i]->data)->virtual_offset;
+            region[i].bufferOffset = dst[i]->virtual_offset;
         }
     } else {
         /* Weird layout (3 planes, 2 buffers), patch welcome, fallback to copy 
*/
@@ -4569,7 +4568,7 @@ static int host_map_frame(AVHWFramesContext *hwfc, 
AVBufferRef **dst, int *nb_bu
 
 fail:
     for (int i = 0; i < (*nb_bufs); i++)
-        av_buffer_unref(&dst[i]);
+        av_refstruct_unref(&dst[i]);
     return err;
 }
 
@@ -4716,7 +4715,7 @@ static int vulkan_transfer_frame(AVHWFramesContext *hwfc,
     VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS];
     int nb_img_bar = 0;
 
-    AVBufferRef *bufs[AV_NUM_DATA_POINTERS];
+    FFVkBuffer *bufs[AV_NUM_DATA_POINTERS];
     int nb_bufs = 0;
 
     VkCommandBuffer cmd_buf;
@@ -4813,11 +4812,8 @@ static int vulkan_transfer_frame(AVHWFramesContext *hwfc,
         }
 
         /* Add the buffers as a dependency */
-        err = ff_vk_exec_add_dep_buf(&p->vkctx, exec, bufs, nb_bufs, 1);
-        if (err < 0) {
-            ff_vk_exec_discard_deps(&p->vkctx, exec);
-            goto end;
-        }
+        for (int i = 0; i < nb_bufs; i++)
+            ff_vk_exec_add_dep_refstruct(&p->vkctx, exec, bufs[i]);
     }
 
     ff_vk_frame_barrier(&p->vkctx, exec, hwf, img_bar, &nb_img_bar,
@@ -4838,7 +4834,7 @@ static int vulkan_transfer_frame(AVHWFramesContext *hwfc,
     for (int i = 0; i < planes; i++) {
         int buf_idx = FFMIN(i, (nb_bufs - 1));
         int img_idx = FFMIN(i, (nb_images - 1));
-        FFVkBuffer *vkbuf = (FFVkBuffer *)bufs[buf_idx]->data;
+        FFVkBuffer *vkbuf = bufs[buf_idx];
 
         uint32_t orig_stride = region[i].bufferRowLength;
         region[i].bufferRowLength /= desc->comp[i].step;
@@ -4869,7 +4865,7 @@ static int vulkan_transfer_frame(AVHWFramesContext *hwfc,
 
 end:
     for (int i = 0; i < nb_bufs; i++)
-        av_buffer_unref(&bufs[i]);
+        av_refstruct_unref(&bufs[i]);
 
     return err;
 }
diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c
index c5d7a3e07f..5dd161cae6 100644
--- a/libavutil/vulkan.c
+++ b/libavutil/vulkan.c
@@ -1258,51 +1258,31 @@ void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf)
     buf->mapped_mem = NULL;
 }
 
-static void free_data_buf(void *opaque, uint8_t *data)
+static void pooled_buf_free(AVRefStructOpaque opaque, void *obj)
 {
-    FFVulkanContext *ctx = opaque;
-    FFVkBuffer *buf = (FFVkBuffer *)data;
-    ff_vk_free_buf(ctx, buf);
-    av_free(data);
+    ff_vk_free_buf(opaque.nc, obj);
 }
 
-static AVBufferRef *alloc_data_buf(void *opaque, size_t size)
-{
-    AVBufferRef *ref;
-    uint8_t *buf = av_mallocz(size);
-    if (!buf)
-        return NULL;
-
-    ref = av_buffer_create(buf, size, free_data_buf, opaque, 0);
-    if (!ref)
-        av_free(buf);
-    return ref;
-}
-
-int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVBufferPool **buf_pool,
-                            AVBufferRef **buf, VkBufferUsageFlags usage,
+int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVRefStructPool **buf_pool,
+                            FFVkBuffer **buf, VkBufferUsageFlags usage,
                             void *create_pNext, size_t size,
                             VkMemoryPropertyFlagBits mem_props)
 {
     int err;
-    AVBufferRef *ref;
     FFVkBuffer *data;
 
-    *buf = NULL;
-
     if (!(*buf_pool)) {
-        *buf_pool = av_buffer_pool_init2(sizeof(FFVkBuffer), ctx,
-                                         alloc_data_buf, NULL);
+        *buf_pool = av_refstruct_pool_alloc_ext(sizeof(FFVkBuffer), 0, ctx,
+                                                NULL, NULL, pooled_buf_free,
+                                                NULL);
         if (!(*buf_pool))
             return AVERROR(ENOMEM);
     }
 
-    *buf = ref = av_buffer_pool_get(*buf_pool);
-    if (!ref)
+    *buf = data = av_refstruct_pool_get(*buf_pool);
+    if (!data)
         return AVERROR(ENOMEM);
 
-    data = (FFVkBuffer *)ref->data;
-
     if (data->size >= size)
         return 0;
 
@@ -1313,16 +1293,14 @@ int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, 
AVBufferPool **buf_pool,
                            create_pNext, NULL, usage,
                            mem_props);
     if (err < 0) {
-        av_buffer_unref(&ref);
-        *buf = NULL;
+        av_refstruct_unref(buf);
         return err;
     }
 
     if (mem_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
         err = ff_vk_map_buffer(ctx, data, &data->mapped_mem, 0);
         if (err < 0) {
-            av_buffer_unref(&ref);
-            *buf = NULL;
+            av_refstruct_unref(buf);
             return err;
         }
     }
@@ -1376,15 +1354,12 @@ static int create_mapped_buffer(FFVulkanContext *s,
     return 0;
 }
 
-static void destroy_avvkbuf(void *opaque, uint8_t *data)
+static void host_map_free(AVRefStructOpaque opaque, void *obj)
 {
-    FFVulkanContext *s = opaque;
-    FFVkBuffer *buf = (FFVkBuffer *)data;
-    ff_vk_free_buf(s, buf);
-    av_free(buf);
+    ff_vk_free_buf(opaque.nc, obj);
 }
 
-int ff_vk_host_map_buffer(FFVulkanContext *s, AVBufferRef **dst,
+int ff_vk_host_map_buffer(FFVulkanContext *s, FFVkBuffer **dst,
                           uint8_t *src_data, VkDeviceSize size,
                           const AVBufferRef *src_buf,
                           VkBufferUsageFlags usage)
@@ -1441,7 +1416,7 @@ int ff_vk_host_map_buffer(FFVulkanContext *s, AVBufferRef 
**dst,
     buffer_size = FFALIGN(buffer_size, 
s->hprops.minImportedHostPointerAlignment);
 
     /* Create a buffer struct */
-    vkb = av_mallocz(sizeof(*vkb));
+    vkb = av_refstruct_alloc_ext(sizeof(*vkb), 0, s, host_map_free);
     if (!vkb) {
         av_buffer_unref(&ref);
         return AVERROR(ENOMEM);
@@ -1452,7 +1427,7 @@ int ff_vk_host_map_buffer(FFVulkanContext *s, AVBufferRef 
**dst,
                                props);
     if (err < 0) {
         av_buffer_unref(&ref);
-        av_free(vkb);
+        av_refstruct_unref(&vkb);
         return err;
     }
 
@@ -1471,14 +1446,7 @@ int ff_vk_host_map_buffer(FFVulkanContext *s, 
AVBufferRef **dst,
     vkb->size           = buffer_size - offs;
     vkb->flags         |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
 
-    /* Create a ref */
-    *dst = av_buffer_create((uint8_t *)vkb, sizeof(*vkb),
-                            destroy_avvkbuf, s, 0);
-    if (!(*dst)) {
-        destroy_avvkbuf(s, (uint8_t *)vkb);
-        *dst = NULL;
-        return AVERROR(ENOMEM);
-    }
+    *dst = vkb;
 
     return 0;
 }
diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h
index 19734bf6bf..c6dfa5050b 100644
--- a/libavutil/vulkan.h
+++ b/libavutil/vulkan.h
@@ -612,8 +612,8 @@ void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf);
  * Threadsafe to use. Buffers are automatically mapped on creation if
  * VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT is set in mem_props. Users should
  * synchronize access themselvesd. Mainly meant for device-local buffers. */
-int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVBufferPool **buf_pool,
-                            AVBufferRef **buf, VkBufferUsageFlags usage,
+int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVRefStructPool **buf_pool,
+                            FFVkBuffer **buf, VkBufferUsageFlags usage,
                             void *create_pNext, size_t size,
                             VkMemoryPropertyFlagBits mem_props);
 
@@ -621,7 +621,7 @@ int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, 
AVBufferPool **buf_pool,
  * References the source buffer. Imports size bytes starting at src_data,
  * rounded up to the host-pointer import alignment and clamped to the end
  * of src_buf. */
-int ff_vk_host_map_buffer(FFVulkanContext *s, AVBufferRef **dst,
+int ff_vk_host_map_buffer(FFVulkanContext *s, FFVkBuffer **dst,
                           uint8_t *src_data, VkDeviceSize size,
                           const AVBufferRef *src_buf,
                           VkBufferUsageFlags usage);

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to