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

This backports ac16cfb86e to release/9.0. Without it, downloading 
Vulkan-decoded frames through the host-image-copy path transitions images out 
of a video layout. That violates 
VUID-VkHostImageLayoutTransitionInfo-oldLayout-09230 on drivers that do not 
list video layouts as host-copyable. The cherry-pick (`-x`) applies without 
conflicts.

## Reproduction on Linux (before / after)

Intel Arc A380, ANV (Mesa 26.2.4, `ANV_DEBUG=video-decode` to expose Vulkan 
decode), Khronos validation layer. Built release/9.0 `fd5d616c29` with and 
without the backport:

```sh
ANV_DEBUG=video-decode ffmpeg -v verbose -init_hw_device 
vulkan=vk:A380,debug=validate \
    -hwaccel vulkan -hwaccel_device vk -i in.h264 -f null -
```

`in.h264` is 50 frames of 1280x720 libx264 with B-frames.

| | VUID-...-oldLayout-09230 | decoded frames vs software h264 (showinfo 
checksums) |
| --- | --- | --- |
| release/9.0 | 3 (`oldLayout is VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR which is 
not one of the layouts returned in ...pCopySrcLayouts[18]`) | 50/50 match |
| with backport | 0 | 50/50 match |

ANV lists 18 host-copy source layouts, and none of them is a video layout. 
After the backport, such frames take the GPU download path, so the output is 
unchanged and the validation error is gone.

RADV (Raphael iGPU) lists the video layouts as copyable and shows 0 VUIDs both 
ways for hwupload/hwdownload. NVIDIA does not use the host path. So on Linux, 
the error shows up on ANV.

Both runs also report VUID-VkImageCreateInfo-pNext-06811 on ANV (5 before, 4 
after). That one comes from image creation with the video profile list. It is 
unrelated to this change and present before it.

`make fate-source` passes on the backport.



>From 490d1d4d39cd2f6bd3dba9cb9d0459024990e18b Mon Sep 17 00:00:00 2001
From: Lynne <[email protected]>
Date: Sun, 26 Jul 2026 19:10:08 +0800
Subject: [PATCH] hwcontext_vulkan: only originate host image layout
 transitions from copyable layouts

Host image layout transitions may only originate from a layout in
pCopySrcLayouts, or from UNDEFINED, discarding the contents. The host
transfer path transitioned from whatever layout the frame was last
left in, which for pool-recycled frames can be a video layout, which
no driver lists as host-copyable.

Uploads overwrite the entire image, so transition from UNDEFINED
there. Downloads have to preserve the contents, so route frames in a
non-host-copyable layout through the GPU path.

(cherry picked from commit ac16cfb86e3cdba0c05778ab09309b7d900a136c)
Signed-off-by: lusoris <[email protected]>
---
 libavutil/hwcontext_vulkan.c | 27 ++++++++++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index 90d3d14dbb..26b7e8fd54 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -4584,10 +4584,12 @@ static int vulkan_transfer_host(AVHWFramesContext 
*hwfc, AVFrame *hwf,
         if (compat)
             continue;
 
+        /* This should only ever happen on uploads, so using UNDEFINED is safe 
*/
+        av_assert1(upload);
         layout_ch_info[nb_layout_ch] = (VkHostImageLayoutTransitionInfoEXT) {
             .sType = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,
             .image = hwf_vk->img[i],
-            .oldLayout = hwf_vk->layout[i],
+            .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
             .newLayout = VK_IMAGE_LAYOUT_GENERAL,
             .subresourceRange = {
                 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
@@ -4709,8 +4711,27 @@ static int vulkan_transfer_frame(AVHWFramesContext *hwfc,
     if (swf->width > hwfc->width || swf->height > hwfc->height)
         return AVERROR(EINVAL);
 
-    if (hwctx->usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT &&
-        !(p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY))
+    int host_copy = hwctx->usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT &&
+                    !(p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY);
+
+    /* Host layout transitions may only originate from a host-copyable layout 
*/
+    if (!upload && host_copy) {
+        for (int i = 0; i < nb_images; i++) {
+            int compat = 0;
+            for (int j = 0; j < p->vkctx.host_image_props.copySrcLayoutCount; 
j++) {
+                if (hwf_vk->layout[i] == 
p->vkctx.host_image_props.pCopySrcLayouts[j]) {
+                    compat = 1;
+                    break;
+                }
+            }
+            if (!compat) {
+                host_copy = 0;
+                break;
+            }
+        }
+    }
+
+    if (host_copy)
         return vulkan_transfer_host(hwfc, hwf, swf, upload);
 
     for (int i = 0; i < av_pix_fmt_count_planes(swf->format); i++) {
-- 
2.52.0

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

Reply via email to