diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c index c7a32cc439..e73d4f93c2 100644 --- a/libavcodec/vulkan_decode.c +++ b/libavcodec/vulkan_decode.c @@ -934,6 +934,10 @@ static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + + if (ctx->s.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE | + FF_VK_EXT_VIDEO_MAINTENANCE_1)) + fmt_info.imageUsage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; } /* Get the format of the images necessary */ @@ -1023,6 +1027,7 @@ int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx) AVVulkanFramesContext *hwfc = frames_ctx->hwctx; FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; FFVulkanDecodeProfileData *prof; + FFVulkanDecodeShared *ctx; frames_ctx->sw_format = AV_PIX_FMT_NONE; @@ -1059,6 +1064,11 @@ int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx) if (!dec->dedicated_dpb) hwfc->usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; + ctx = dec->shared_ctx; + if (ctx->s.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE | + FF_VK_EXT_VIDEO_MAINTENANCE_1)) + hwfc->usage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; + return err; } diff --git a/libavfilter/vulkan_filter.c b/libavfilter/vulkan_filter.c index 2878d9063b..6221e0206d 100644 --- a/libavfilter/vulkan_filter.c +++ b/libavfilter/vulkan_filter.c @@ -37,6 +37,7 @@ int ff_vk_filter_init_context(AVFilterContext *avctx, FFVulkanContext *s, if (frames_ref) { int no_storage = 0; FFVulkanFunctions *vk; + VkImageUsageFlagBits usage_req; const VkFormat *sub = av_vkfmt_from_pixfmt(sw_format); frames_ctx = (AVHWFramesContext *)frames_ref->data; @@ -57,18 +58,41 @@ int ff_vk_filter_init_context(AVFilterContext *avctx, FFVulkanContext *s, if (vk_frames->tiling != VK_IMAGE_TILING_OPTIMAL) goto skip; - /* Usage mismatch */ - if ((vk_frames->usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT)) != - (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT)) - goto skip; - s->extensions = ff_vk_extensions_to_mask(vk_dev->enabled_dev_extensions, vk_dev->nb_enabled_dev_extensions); + + /* More advanced format checks */ err = ff_vk_load_functions(device_ctx, &s->vkfn, s->extensions, 1, 1); if (err < 0) return err; vk = &s->vkfn; + /* Usage mismatch */ + usage_req = VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_STORAGE_BIT; + + /* If format supports hardware encoding, make sure + * the context includes it. */ + if (vk_frames->format[1] == VK_FORMAT_UNDEFINED && + (s->extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE | + FF_VK_EXT_VIDEO_MAINTENANCE_1))) { + VkFormatProperties3 fprops = { + .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3, + }; + VkFormatProperties2 prop = { + .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, + .pNext = &fprops, + }; + vk->GetPhysicalDeviceFormatProperties2(vk_dev->phys_dev, + vk_frames->format[0], + &prop); + if (fprops.optimalTilingFeatures & VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR) + usage_req |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; + } + + if ((vk_frames->usage & usage_req) != usage_req) + goto skip; + /* Check if the subformats can do storage */ for (int i = 0; sub[i] != VK_FORMAT_UNDEFINED; i++) { VkFormatProperties2 prop = { @@ -113,13 +137,6 @@ skip: frames_ctx->width = width; frames_ctx->height = height; - vk_frames = frames_ctx->hwctx; - vk_frames->tiling = VK_IMAGE_TILING_OPTIMAL; - vk_frames->usage = VK_IMAGE_USAGE_SAMPLED_BIT | - VK_IMAGE_USAGE_STORAGE_BIT | - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT; - err = av_hwframe_ctx_init(frames_ref); if (err < 0) { av_buffer_unref(&frames_ref); diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index b897a54621..3e00781e9e 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2632,6 +2632,12 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_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 | + FF_VK_EXT_VIDEO_MAINTENANCE_1))) + hwctx->usage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; } /* Image creation flags. @@ -2650,6 +2656,28 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) } } + /* If the image has an ENCODE_SRC usage, and the maintenance1 + * extension is supported, check if it has a profile list. + * If there's no profile list, or it has no encode operations, + * then allow creating the image with no specific profile. */ + if ((hwctx->usage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) && + p->video_maint_1_features.videoMaintenance1) { + const VkVideoProfileListInfoKHR *pl; + pl = ff_vk_find_struct(hwctx->create_pnext, VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR); + if (!pl) { + hwctx->img_flags |= VK_IMAGE_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR; + } else { + uint32_t i; + for (i = 0; i < pl->profileCount; i++) { + /* Video ops start at exactly 0x00010000 */ + if (pl->pProfiles[i].videoCodecOperation & 0xFFFF0000) + break; + } + if (i == pl->profileCount) + hwctx->img_flags |= VK_IMAGE_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR; + } + } + if (!hwctx->lock_frame) hwctx->lock_frame = lock_frame;