PR #25110 opened by Kilian (lusoris)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25110
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25110.patch

Applications mapping RADV Vulkan frames through DRM to VAAPI can read a frame 
before Vulkan has finished writing it. On the Ryzen 9 9950X3D iGPU, 12 to 15 of 
20 mapped frames differed from the Vulkan readback without this patch, compared 
with 0 of 20 with it, in three repetitions each.

vulkan_map_to_drm() attaches a sync file to each exported dma-buf and relies on 
the importer to wait. RADV sets AMDGPU_GEM_CREATE_EXPLICIT_SYNC unless 
RADEON_FLAG_IMPLICIT_SYNC is requested (`radv_amdgpu_bo.c:602-603` in Mesa 
26.2.4 and `radv_amdgpu_bo.c:609-610` on Mesa main 79fa6f5ca5). Linux 7.2's 
`amdgpu_cs.c` and `amdgpu_sync.c` skip reservation fences for submissions on 
explicitly synchronized buffers, including a radeonsi importer of the same 
buffer object. The attached fence is therefore ignored by the VAAPI GPU work.

What the patch does:

- excludes VK_DRIVER_ID_MESA_RADV from the sync-file branch in 
`libavutil/hwcontext_vulkan.c`, making RADV use the existing CPU wait before 
DRM mapping
- keeps the sync-file path for other drivers when its existing conditions are 
met

Testing, Ryzen 9 9950X3D iGPU with Mesa 26.2.4 and Linux 7.2.9, and Intel Arc 
A380 with ANV and iHD, on n9.0.2:

- RADV frame comparisons improve from 12 to 15 mismatches out of 20 to 0 out of 
20 in three repetitions each; sync-file imports fall from 21 per run to 0
- ANV with iHD keeps 63 sync-file imports per run and matches the Vulkan 
readback in both builds
- the exported sync file is still pending at hand-off in every frame; waiting 
on that file on the CPU also removes the race, showing that the fence 
represents the pending work
- the allocation-flag probe rechecked on Linux 7.2.10-1-cachyos with Mesa 
26.2.4 and libdrm 2.4.134 reports RADV dma-buf alloc_flags=0x28e, with 
EXPLICIT_SYNC set
- on master af25036ac0 (GCC 16.2.1, `--enable-gpl --enable-vulkan 
--enable-vaapi --enable-libdrm --enable-nvenc`): the commit applies cleanly, 
`libavutil/hwcontext_vaapi.c` and `libavutil/hwcontext_vulkan.c` build without 
warnings, and FATE (3106 targets) fails the same 17 tests as unpatched master, 
all deflate-output tests (zlib, flashsv, mpng, png, apng, pdv) whose decoded 
output matches and only the compressed bytes differ, from the host zlib-ng; the 
GPU checks were run on n9.0.2, not rerun on master

For review: whether a RADV-specific condition in FFmpeg is acceptable versus a 
Mesa-side fix. A Mesa report is being prepared.



>From 41793ff0ee64bd6fa1d71461008bd4553f7882c8 Mon Sep 17 00:00:00 2001
From: lusoris <[email protected]>
Date: Sat, 10 Oct 2026 12:04:08 +0200
Subject: [PATCH] avutil/hwcontext_vulkan: wait on the CPU before RADV DRM
 mapping

vulkan_map_to_drm() attaches a sync file for the frame's pending work
to each exported dma-buf and skips the CPU wait, relying on the
importer to honour the dma-buf's fences. On RADV that never happens:
RADV allocates exportable memory with AMDGPU_GEM_CREATE_EXPLICIT_SYNC,
and amdgpu ignores the fences in a buffer's reservation object for
every submission on an explicitly synchronized buffer. An importer on
the same device gets the same buffer object, so a VAAPI driver reading
the frame does not wait for the sync file and can read it before the
Vulkan work has finished.

On RADV, wait on the CPU instead, as is done when no sync file can be
exported.

Signed-off-by: lusoris <[email protected]>
---
 libavutil/hwcontext_vulkan.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index 63d2ab5c43..94b6fa9d52 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -4522,8 +4522,14 @@ static int vulkan_map_to_drm(AVHWFramesContext *hwfc, 
AVFrame *dst,
         goto end;
 
 #ifdef DMA_BUF_IOCTL_EXPORT_SYNC_FILE
+    /* RADV allocates exportable memory as explicitly synchronized
+     * (AMDGPU_GEM_CREATE_EXPLICIT_SYNC), and amdgpu then ignores the fences
+     * in the dma-buf for every submission on that buffer, including those of
+     * an importer such as the VAAPI driver. A sync file attached to the
+     * dma-buf would not be waited for, so wait on the CPU instead. */
     if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_SEM) &&
         f->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT &&
+        p->dprops.driverID != VK_DRIVER_ID_MESA_RADV &&
         vk->GetSemaphoreFdKHR && vk->CreateSemaphore) {
         err = vulkan_drm_export_sync_fd(hwfc, f, fp, nb_sems);
         if (err < 0)
-- 
2.54.0

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

Reply via email to