[PR] hwcontext_vulkan: probe host image transfer support before enabling (PR #23612)

Kacper Michajłow via ffmpeg-devel <[email protected]>
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <178253840983.59.12289723360997501555@29965ddac10e>
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]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.