PR #23612 opened by Kacper Michajłow (kasper93)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23612
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23612.patch


From 1b0ad6620972a60b0b30cdad1588a5f6cd1ad616 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]>
Date: Sat, 27 Jun 2026 07:20:46 +0200
Subject: [PATCH 1/2] hwcontext_vulkan: probe host image transfer support
 before enabling
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Notably video decode/encode images are often not possible to allocate
from host visible memory type.

Fixes: #21704
Signed-off-by: Kacper Michajłow <[email protected]>
---
 libavutil/hwcontext_vulkan.c | 70 ++++++++++++++++++++++++++++++++++++
 libavutil/vulkan_functions.h |  1 +
 2 files changed, 71 insertions(+)

diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index 20b6ed46f8..40a943667e 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -2934,6 +2934,69 @@ static void vulkan_frames_uninit(AVHWFramesContext *hwfc)
     av_buffer_pool_uninit(&fp->tmp);
 }
 
+/* Probes whether the host transfer usage bit is actually usable in combination
+ * with the rest of the usage flags. Notably video decode/encode images may not
+ * be possible to allocate from the host visible memory type. */
+static int vulkan_host_transfer_usable(AVHWFramesContext *hwfc)
+{
+    VulkanFramesPriv *fp = hwfc->hwctx;
+    AVVulkanFramesContext *hwctx = &fp->p;
+    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+    AVVulkanDeviceContext *dev_hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+
+    /* DRM modifier tiling can't be probed without the actual modifier, which 
the
+     * driver only picks at creation time. */
+    if (hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
+        return 0;
+
+    VkImageFormatProperties2 props = {
+        .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
+    };
+    VkPhysicalDeviceImageFormatInfo2 pinfo = {
+        .sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
+        .pNext  = hwctx->create_pnext,
+        .format = hwctx->format[0],
+        .type   = VK_IMAGE_TYPE_2D,
+        .tiling = hwctx->tiling,
+        .usage  = hwctx->usage,
+        .flags  = hwctx->img_flags,
+    };
+
+    if (vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev,
+                                                    &pinfo, &props) != 
VK_SUCCESS)
+        return 0;
+
+    if (!p->vkctx.host_image_props.identicalMemoryTypeRequirements) {
+        VkImageCreateInfo create_info = {
+            .sType       = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+            .pNext       = hwctx->create_pnext,
+            .imageType   = VK_IMAGE_TYPE_2D,
+            .format      = hwctx->format[0],
+            .extent      = { hwfc->width, hwfc->height, 1 },
+            .mipLevels   = 1,
+            .arrayLayers = hwctx->nb_layers,
+            .flags       = hwctx->img_flags,
+            .tiling      = hwctx->tiling,
+            .usage       = hwctx->usage,
+            .samples     = VK_SAMPLE_COUNT_1_BIT,
+        };
+        VkDeviceImageMemoryRequirements req_info = {
+            .sType = VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS,
+            .pCreateInfo = &create_info,
+        };
+        VkMemoryRequirements2 req = {
+            .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
+        };
+
+        vk->GetDeviceImageMemoryRequirements(dev_hwctx->act_dev, &req_info, 
&req);
+        if (!req.memoryRequirements.memoryTypeBits)
+            return 0;
+    }
+
+    return 1;
+}
+
 static int vulkan_frames_init(AVHWFramesContext *hwfc)
 {
     int err;
@@ -3066,6 +3129,13 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc)
         }
     }
 
+    /* Drop the host transfer if it isn't usable for this image configuration. 
*/
+    if ((hwctx->usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT) &&
+        !vulkan_host_transfer_usable(hwfc))
+    {
+        hwctx->usage &= ~VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
+    }
+
     if (!hwctx->lock_frame)
         hwctx->lock_frame = lock_frame;
 
diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h
index 86dff046b2..185a8e290d 100644
--- a/libavutil/vulkan_functions.h
+++ b/libavutil/vulkan_functions.h
@@ -172,6 +172,7 @@ typedef uint64_t FFVulkanExtensions;
     /* Image */                                                                
          \
     MACRO(1, 1, FF_VK_EXT_DRM_MODIFIER_FLAGS,   
GetImageDrmFormatModifierPropertiesEXT)  \
     MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetImageMemoryRequirements2)   
          \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              
GetDeviceImageMemoryRequirements)        \
     MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateImage)                   
          \
     MACRO(1, 1, FF_VK_EXT_NO_FLAG,              BindImageMemory2)              
          \
     MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetImageSubresourceLayout)     
          \
-- 
2.52.0


From bd9d9e4fc319644f01cbce537d268f03ff769f8d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]>
Date: Sat, 27 Jun 2026 07:31:38 +0200
Subject: [PATCH 2/2] hwcontext_vulkan: drop NVIDIA/MoltenVK host transfer
 blocklist
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Now that we correctly test if images are valid for host transfer, we can
drop the hardcoded blocklist.

Signed-off-by: Kacper Michajłow <[email protected]>
---
 libavutil/hwcontext_vulkan.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index 40a943667e..dc7b21936b 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -3080,9 +3080,7 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc)
                                            VK_IMAGE_USAGE_STORAGE_BIT      |
                                            VK_IMAGE_USAGE_SAMPLED_BIT);
 
-        if (p->vkctx.extensions & FF_VK_EXT_HOST_IMAGE_COPY &&
-            !(p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY) &&
-            !(p->dprops.driverID == VK_DRIVER_ID_MOLTENVK))
+        if (p->vkctx.extensions & FF_VK_EXT_HOST_IMAGE_COPY)
             hwctx->usage |= supported_usage & 
VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
 
         /* Enables encoding of images, if supported by format and extensions */
@@ -4756,8 +4754,7 @@ 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))
+    if (hwctx->usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT)
         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