On Tue, 03 Jun 2025 01:58:26 +0900 Lynne <d...@lynne.ee> 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; > +
You should check for VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT instead of enabling this blindly, since it may not be supported by all formats. > /* 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); I found vkCopyImageToMemory transfers to be substantially slower than vice versa, maybe you can test this in your implementation? > + } > + } > + > + 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); What if the frame is still in use? > + > 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 */ > > /* 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@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".