[FFmpeg-devel] [PATCH] hwcontext_vulkan: use host image copy
Victor Jaquez
vjaquez at igalia.com
Mon Jun 2 21:55:49 EEST 2025
On Tue, 03 Jun 2025 at 01:58, Lynne wrote:
> ---
> libavutil/hwcontext_vulkan.c | 84 +++++++++++++++++++++++++++++++++++-
> libavutil/vulkan_functions.h | 6 +++
> libavutil/vulkan_loader.h | 1 +
> 3 files changed, 89 insertions(+), 2 deletions(-)
>
> diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
> index ce485a85a2..b22e4e375a 100644
> --- a/libavutil/hwcontext_vulkan.c
> +++ b/libavutil/hwcontext_vulkan.c
> @@ -80,6 +80,7 @@ typedef struct VulkanDeviceFeatures {
> VkPhysicalDeviceVulkan13Features vulkan_1_3;
> VkPhysicalDeviceTimelineSemaphoreFeatures timeline_semaphore;
> VkPhysicalDeviceShaderSubgroupRotateFeaturesKHR subgroup_rotate;
> + VkPhysicalDeviceHostImageCopyFeaturesEXT host_image_copy;
>
> #ifdef VK_KHR_shader_expect_assume
> VkPhysicalDeviceShaderExpectAssumeFeaturesKHR expect_assume;
> @@ -208,6 +209,8 @@ static void device_features_init(AVHWDeviceContext *ctx, VulkanDeviceFeatures *f
> VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES);
> FF_VK_STRUCT_EXT(s, &feats->device, &feats->subgroup_rotate, FF_VK_EXT_SUBGROUP_ROTATE,
> VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES_KHR);
> + FF_VK_STRUCT_EXT(s, &feats->device, &feats->host_image_copy, FF_VK_EXT_HOST_IMAGE_COPY,
> + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT);
>
> #ifdef VK_KHR_shader_expect_assume
> FF_VK_STRUCT_EXT(s, &feats->device, &feats->expect_assume, FF_VK_EXT_EXPECT_ASSUME,
> @@ -287,6 +290,7 @@ static void device_features_copy_needed(VulkanDeviceFeatures *dst, VulkanDeviceF
>
> COPY_VAL(timeline_semaphore.timelineSemaphore);
> COPY_VAL(subgroup_rotate.shaderSubgroupRotate);
> + COPY_VAL(host_image_copy.hostImageCopy);
>
> COPY_VAL(video_maintenance_1.videoMaintenance1);
> #ifdef VK_KHR_video_maintenance2
> @@ -610,6 +614,7 @@ static const VulkanOptExtension optional_device_exts[] = {
> { VK_NV_OPTICAL_FLOW_EXTENSION_NAME, FF_VK_EXT_OPTICAL_FLOW },
> { VK_EXT_SHADER_OBJECT_EXTENSION_NAME, FF_VK_EXT_SHADER_OBJECT },
> { VK_KHR_SHADER_SUBGROUP_ROTATE_EXTENSION_NAME, FF_VK_EXT_SUBGROUP_ROTATE },
> + { VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME, FF_VK_EXT_HOST_IMAGE_COPY },
> #ifdef VK_KHR_shader_expect_assume
> { VK_KHR_SHADER_EXPECT_ASSUME_EXTENSION_NAME, FF_VK_EXT_EXPECT_ASSUME },
> #endif
> @@ -2802,11 +2807,15 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc)
>
> /* Image usage flags */
> if (!hwctx->usage) {
> - hwctx->usage = supported_usage & (VK_IMAGE_USAGE_TRANSFER_DST_BIT |
> - VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
> + hwctx->usage = supported_usage & (VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
> VK_IMAGE_USAGE_STORAGE_BIT |
> VK_IMAGE_USAGE_SAMPLED_BIT);
>
> + if (p->vkctx.extensions & FF_VK_EXT_HOST_IMAGE_COPY)
> + hwctx->usage |= VK_IMAGE_USAGE_HOST_TRANSFER_BIT;
> + else
> + hwctx->usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
> +
> /* Enables encoding of images, if supported by format and extensions */
> if ((supported_usage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) &&
> (p->vkctx.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE |
> @@ -4125,6 +4134,74 @@ fail:
> return err;
> }
>
> +static int vulkan_transfer_host(AVHWFramesContext *hwfc, AVFrame *hwf,
> + AVFrame *swf, int upload)
> +{
> + VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
> + AVVulkanDeviceContext *hwctx = &p->p;
> + FFVulkanFunctions *vk = &p->vkctx.vkfn;
> +
> + AVVkFrame *hwf_vk = (AVVkFrame *)hwf->data[0];
> + const int planes = av_pix_fmt_count_planes(swf->format);
> + const int nb_images = ff_vk_count_images(hwf_vk);
> +
> + if (upload) {
> + VkMemoryToImageCopy region_info = {
> + .sType = VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY,
> + .imageSubresource = {
> + .layerCount = 1,
> + },
> + };
> + VkCopyMemoryToImageInfo copy_info = {
> + .sType = VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO,
> + .flags = VK_HOST_IMAGE_COPY_MEMCPY,
> + .regionCount = 1,
> + .pRegions = ®ion_info,
> + };
> + for (int i = 0; i < planes; i++) {
> + int img_idx = FFMIN(i, (nb_images - 1));
> + uint32_t p_w, p_h;
> + get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
> +
> + region_info.pHostPointer = swf->data[i];
> + region_info.imageSubresource.aspectMask = ff_vk_aspect_flag(hwf, i);
> + region_info.imageExtent = (VkExtent3D){ p_w, p_h, 1 };
> + copy_info.dstImage = hwf_vk->img[img_idx];
> + copy_info.dstImageLayout = hwf_vk->layout[img_idx];
> +
> + vk->CopyMemoryToImageEXT(hwctx->act_dev, ©_info);
> + }
> + } else {
> + VkImageToMemoryCopy region_info = {
> + .sType = VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY,
> + .imageSubresource = {
> + .layerCount = 1,
> + },
> + };
> + VkCopyImageToMemoryInfo copy_info = {
> + .sType = VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO,
> + .flags = VK_HOST_IMAGE_COPY_MEMCPY,
> + .regionCount = 1,
> + .pRegions = ®ion_info,
> + };
> + for (int i = 0; i < planes; i++) {
> + int img_idx = FFMIN(i, (nb_images - 1));
> + uint32_t p_w, p_h;
> + get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
> +
> + region_info.pHostPointer = swf->data[i];
> + region_info.imageSubresource.aspectMask = ff_vk_aspect_flag(hwf, i);
> + region_info.imageExtent = (VkExtent3D){ p_w, p_h, 1 };
> + copy_info.srcImage = hwf_vk->img[img_idx];
> + copy_info.srcImageLayout = hwf_vk->layout[img_idx];
> +
> + vk->CopyImageToMemoryEXT(hwctx->act_dev, ©_info);
> + }
> + }
> +
> + return 0;
> +}
> +
> static int vulkan_transfer_frame(AVHWFramesContext *hwfc,
> AVFrame *swf, AVFrame *hwf,
> int upload)
> @@ -4161,6 +4238,9 @@ static int vulkan_transfer_frame(AVHWFramesContext *hwfc,
> if (swf->width > hwfc->width || swf->height > hwfc->height)
> return AVERROR(EINVAL);
>
> + if (p->vkctx.extensions & FF_VK_EXT_HOST_IMAGE_COPY)
> + return vulkan_transfer_host(hwfc, hwf, swf, upload);
> +
> for (int i = 0; i < av_pix_fmt_count_planes(swf->format); i++) {
> uint32_t p_w, p_h;
> get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
> diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h
> index 8b413013e6..ea0f978bb9 100644
> --- a/libavutil/vulkan_functions.h
> +++ b/libavutil/vulkan_functions.h
> @@ -49,6 +49,7 @@ typedef uint64_t FFVulkanExtensions;
> #define FF_VK_EXT_RELAXED_EXTENDED_INSTR (1ULL << 15) /* VK_KHR_shader_relaxed_extended_instruction */
> #define FF_VK_EXT_EXPECT_ASSUME (1ULL << 16) /* VK_KHR_shader_expect_assume */
> #define FF_VK_EXT_SUBGROUP_ROTATE (1ULL << 17) /* VK_KHR_shader_subgroup_rotate */
> +#define FF_VK_EXT_HOST_IMAGE_COPY (1ULL << 18) /* VK_EXT_image_copy */
VK_EXT_host_image_copy
>
> /* Video extensions */
> #define FF_VK_EXT_VIDEO_QUEUE (1ULL << 36) /* VK_KHR_video_queue */
> @@ -207,6 +208,11 @@ typedef uint64_t FFVulkanExtensions;
> /* sync2 */ \
> MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdPipelineBarrier2) \
> \
> + /* Host image copy */ \
> + MACRO(1, 1, FF_VK_EXT_HOST_IMAGE_COPY, TransitionImageLayoutEXT) \
> + MACRO(1, 1, FF_VK_EXT_HOST_IMAGE_COPY, CopyMemoryToImageEXT) \
> + MACRO(1, 1, FF_VK_EXT_HOST_IMAGE_COPY, CopyImageToMemoryEXT) \
> + \
> /* Video queue */ \
> MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE, CreateVideoSessionKHR) \
> MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE, CreateVideoSessionParametersKHR) \
> diff --git a/libavutil/vulkan_loader.h b/libavutil/vulkan_loader.h
> index a7976fe560..7e805fdd4c 100644
> --- a/libavutil/vulkan_loader.h
> +++ b/libavutil/vulkan_loader.h
> @@ -59,6 +59,7 @@ static inline uint64_t ff_vk_extensions_to_mask(const char * const *extensions,
> { VK_NV_OPTICAL_FLOW_EXTENSION_NAME, FF_VK_EXT_OPTICAL_FLOW },
> { VK_EXT_SHADER_OBJECT_EXTENSION_NAME, FF_VK_EXT_SHADER_OBJECT },
> { VK_KHR_SHADER_SUBGROUP_ROTATE_EXTENSION_NAME, FF_VK_EXT_SUBGROUP_ROTATE },
> + { VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME, FF_VK_EXT_HOST_IMAGE_COPY },
> { VK_KHR_VIDEO_MAINTENANCE_1_EXTENSION_NAME, FF_VK_EXT_VIDEO_MAINTENANCE_1 },
> #ifdef VK_KHR_video_maintenance2
> { VK_KHR_VIDEO_MAINTENANCE_2_EXTENSION_NAME, FF_VK_EXT_VIDEO_MAINTENANCE_2 },
> --
> 2.49.0.395.g12beb8f557c
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".
>
More information about the ffmpeg-devel
mailing list