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

Git pushed a commit to branch master
in repository ffmpeg.

The following commit(s) were added to refs/heads/master by this push:
     new b227d1e4be avfilter/vf_scale_d3d12: fix command allocator sync before 
reset
b227d1e4be is described below

commit b227d1e4be9371e37da8107f7a30364fa8cff5fb
Author:     Dong Nguyen <[email protected]>
AuthorDate: Thu Sep 17 10:35:44 2026 -0400
Commit:     Steven Xiao <[email protected]>
CommitDate: Sat Sep 26 15:42:31 2026 +0000

    avfilter/vf_scale_d3d12: fix command allocator sync before reset
    
    Replace the single command allocator with a pooled allocator approach 
matching d3d12va_encode.c. Each allocator is tagged with the fence value that 
must complete before it can be reused. Fixes #24483.
---
 libavfilter/vf_scale_d3d12.c | 117 +++++++++++++++++++++++++++++++++----------
 1 file changed, 90 insertions(+), 27 deletions(-)

diff --git a/libavfilter/vf_scale_d3d12.c b/libavfilter/vf_scale_d3d12.c
index 03fa92f872..7bddda6552 100644
--- a/libavfilter/vf_scale_d3d12.c
+++ b/libavfilter/vf_scale_d3d12.c
@@ -18,6 +18,7 @@
 
 #define COBJMACROS
 
+#include "libavutil/fifo.h"
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "compat/w32dlfcn.h"
@@ -30,6 +31,11 @@
 #include "scale_eval.h"
 #include "video.h"
 
+typedef struct D3D12ScaleCommandAllocator {
+    ID3D12CommandAllocator *command_allocator;
+    UINT64 fence_value;
+} D3D12ScaleCommandAllocator;
+
 typedef struct ScaleD3D12Context {
     const AVClass *classCtx;
     char *w_expr;
@@ -42,7 +48,8 @@ typedef struct ScaleD3D12Context {
     ID3D12VideoProcessor *video_processor;
     ID3D12CommandQueue *command_queue;
     ID3D12VideoProcessCommandList *command_list;
-    ID3D12CommandAllocator *command_allocator;
+
+    AVFifo *allocator_queue;
 
     /* Synchronization */
     ID3D12Fence *fence;
@@ -71,9 +78,49 @@ static av_cold int scale_d3d12_init(AVFilterContext *ctx) {
     return 0;
 }
 
+static int scale_d3d12_get_valid_command_allocator(ScaleD3D12Context *s, 
AVFilterContext *ctx,
+                                                    ID3D12CommandAllocator 
**ppAllocator)
+{
+    HRESULT hr;
+    D3D12ScaleCommandAllocator allocator;
+
+    if (av_fifo_peek(s->allocator_queue, &allocator, 1, 0) >= 0) {
+        UINT64 completed = ID3D12Fence_GetCompletedValue(s->fence);
+        if (completed >= allocator.fence_value) {
+            *ppAllocator = allocator.command_allocator;
+            av_fifo_read(s->allocator_queue, &allocator, 1);
+            return 0;
+        }
+    }
+
+    hr = ID3D12Device_CreateCommandAllocator(s->device, 
D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS,
+                                             &IID_ID3D12CommandAllocator, 
(void **)ppAllocator);
+    if (FAILED(hr)) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to create a new command allocator: 
HRESULT 0x%lX\n", hr);
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+static int scale_d3d12_discard_command_allocator(ScaleD3D12Context *s, 
ID3D12CommandAllocator *pAllocator,
+                                                  UINT64 fence_value)
+{
+    D3D12ScaleCommandAllocator allocator = {
+        .command_allocator = pAllocator,
+        .fence_value       = fence_value,
+    };
+
+    av_fifo_write(s->allocator_queue, &allocator, 1);
+
+    return 0;
+}
+
 static void release_d3d12_resources(ScaleD3D12Context *s) {
     UINT64 fence_value;
     HRESULT hr;
+    D3D12ScaleCommandAllocator allocator;
+
     /* Wait for all GPU operations to complete before releasing resources */
     if (s->command_queue && s->fence && s->fence_event) {
         fence_value = s->fence_value - 1;
@@ -104,9 +151,10 @@ static void release_d3d12_resources(ScaleD3D12Context *s) {
         s->command_list = NULL;
     }
 
-    if (s->command_allocator) {
-        ID3D12CommandAllocator_Release(s->command_allocator);
-        s->command_allocator = NULL;
+    if (s->allocator_queue) {
+        while (av_fifo_read(s->allocator_queue, &allocator, 1) >= 0)
+            ID3D12CommandAllocator_Release(allocator.command_allocator);
+        av_fifo_freep2(&s->allocator_queue);
     }
 
     if (s->video_processor) {
@@ -181,6 +229,8 @@ static AVRational get_input_framerate(AVFilterContext *ctx, 
AVFilterLink *inlink
 
 static int scale_d3d12_configure_processor(ScaleD3D12Context *s, 
AVFilterContext *ctx) {
     HRESULT hr;
+    int ret;
+    ID3D12CommandAllocator *command_allocator = NULL;
 
     if (s->output_format == DXGI_FORMAT_UNKNOWN) {
         av_log(ctx, AV_LOG_ERROR, "Output format not initialized\n");
@@ -311,23 +361,32 @@ static int 
scale_d3d12_configure_processor(ScaleD3D12Context *s, AVFilterContext
         return AVERROR_EXTERNAL;
     }
 
-    hr = ID3D12Device_CreateCommandAllocator(
-        s->device,
-        D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS,
-        &IID_ID3D12CommandAllocator,
-        (void **)&s->command_allocator
-    );
-
+    hr = ID3D12Device_CreateFence(s->device, 0, D3D12_FENCE_FLAG_NONE, 
&IID_ID3D12Fence, (void **)&s->fence);
     if (FAILED(hr)) {
-        av_log(ctx, AV_LOG_ERROR, "Failed to create command allocator: HRESULT 
0x%lX\n", hr);
+        av_log(ctx, AV_LOG_ERROR, "Failed to create fence: HRESULT 0x%lX\n", 
hr);
         return AVERROR_EXTERNAL;
     }
 
+    s->fence_value = 1;
+    s->fence_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (!s->fence_event) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to create fence event\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->allocator_queue = av_fifo_alloc2(2, sizeof(D3D12ScaleCommandAllocator), 
AV_FIFO_FLAG_AUTO_GROW);
+    if (!s->allocator_queue)
+        return AVERROR(ENOMEM);
+
+    ret = scale_d3d12_get_valid_command_allocator(s, ctx, &command_allocator);
+    if (ret < 0)
+        return ret;
+
     hr = ID3D12Device_CreateCommandList(
         s->device,
         0,
         D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS,
-        s->command_allocator,
+        command_allocator,
         NULL,
         &IID_ID3D12VideoProcessCommandList,
         (void **)&s->command_list
@@ -335,23 +394,15 @@ static int 
scale_d3d12_configure_processor(ScaleD3D12Context *s, AVFilterContext
 
     if (FAILED(hr)) {
         av_log(ctx, AV_LOG_ERROR, "Failed to create command list: HRESULT 
0x%lX\n", hr);
+        ID3D12CommandAllocator_Release(command_allocator);
         return AVERROR_EXTERNAL;
     }
 
     ID3D12VideoProcessCommandList_Close(s->command_list);
 
-    hr = ID3D12Device_CreateFence(s->device, 0, D3D12_FENCE_FLAG_NONE, 
&IID_ID3D12Fence, (void **)&s->fence);
-    if (FAILED(hr)) {
-        av_log(ctx, AV_LOG_ERROR, "Failed to create fence: HRESULT 0x%lX\n", 
hr);
-        return AVERROR_EXTERNAL;
-    }
-
-    s->fence_value = 1;
-    s->fence_event = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (!s->fence_event) {
-        av_log(ctx, AV_LOG_ERROR, "Failed to create fence event\n");
-        return AVERROR_EXTERNAL;
-    }
+    ret = scale_d3d12_discard_command_allocator(s, command_allocator, 0);
+    if (ret < 0)
+        return ret;
 
     av_log(ctx, AV_LOG_VERBOSE, "D3D12 video processor successfully 
configured\n");
     return 0;
@@ -365,6 +416,7 @@ static int scale_d3d12_filter_frame(AVFilterLink *inlink, 
AVFrame *in)
     AVFrame          *out = NULL;
     int ret = 0;
     HRESULT hr;
+    ID3D12CommandAllocator *command_allocator = NULL;
 
     if (!in) {
         av_log(ctx, AV_LOG_ERROR, "Null input frame\n");
@@ -478,14 +530,18 @@ static int scale_d3d12_filter_frame(AVFilterLink *inlink, 
AVFrame *in)
         }
     }
 
-    hr = ID3D12CommandAllocator_Reset(s->command_allocator);
+    ret = scale_d3d12_get_valid_command_allocator(s, ctx, &command_allocator);
+    if (ret < 0)
+        goto fail;
+
+    hr = ID3D12CommandAllocator_Reset(command_allocator);
     if (FAILED(hr)) {
         av_log(ctx, AV_LOG_ERROR, "Failed to reset command allocator: HRESULT 
0x%lX\n", hr);
         ret = AVERROR_EXTERNAL;
         goto fail;
     }
 
-    hr = ID3D12VideoProcessCommandList_Reset(s->command_list, 
s->command_allocator);
+    hr = ID3D12VideoProcessCommandList_Reset(s->command_list, 
command_allocator);
     if (FAILED(hr)) {
         av_log(ctx, AV_LOG_ERROR, "Failed to reset command list: HRESULT 
0x%lX\n", hr);
         ret = AVERROR_EXTERNAL;
@@ -576,6 +632,11 @@ static int scale_d3d12_filter_frame(AVFilterLink *inlink, 
AVFrame *in)
     output_frame->sync_ctx.fence_value = s->fence_value;
     ID3D12Fence_AddRef(s->fence);  ///< Increment reference count
 
+    ret = scale_d3d12_discard_command_allocator(s, command_allocator, 
s->fence_value);
+    command_allocator = NULL;
+    if (ret < 0)
+        goto fail;
+
     s->fence_value++;
 
     ret = av_frame_copy_props(out, in);
@@ -593,6 +654,8 @@ static int scale_d3d12_filter_frame(AVFilterLink *inlink, 
AVFrame *in)
     return ff_filter_frame(outlink, out);
 
 fail:
+    if (command_allocator)
+        scale_d3d12_discard_command_allocator(s, command_allocator, 
s->fence_value);
     av_frame_free(&in);
     av_frame_free(&out);
     return ret;

-- 
To stop receiving notification emails like this one, please contact
[email protected].
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to