Vulkan encoding was designed in a very... consolidated way. You had to know the exact codec and profile that the image was going to eventually be encoded as at... image creation time. Unfortunately, as good as our code is, glimpsing into the exact future isn't what its capable of. video_maintenance1 removed that requirement, which only then made encoding images practically possible.
Unified · Split
| @@ -934,6 +934,10 @@ static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ · 933 unmodified lines | |||
| 934 | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | | 934 | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | |
| 935 | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | | 935 | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| 936 | VK_IMAGE_USAGE_SAMPLED_BIT; | 936 | VK_IMAGE_USAGE_SAMPLED_BIT; |
| 937 | |||
| 938 | if (ctx->s.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE | | ||
| 939 | FF_VK_EXT_VIDEO_MAINTENANCE_1)) | ||
| 940 | fmt_info.imageUsage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; | ||
| 937 | } | 941 | } |
| 938 | 942 | ||
| 939 | /* Get the format of the images necessary */ | 943 | /* Get the format of the images necessary */ |
| @@ -1023,6 +1027,7 @@ int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx) · 83 unmodified lines | |||
| 1023 | AVVulkanFramesContext *hwfc = frames_ctx->hwctx; | 1027 | AVVulkanFramesContext *hwfc = frames_ctx->hwctx; |
| 1024 | FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; | 1028 | FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; |
| 1025 | FFVulkanDecodeProfileData *prof; | 1029 | FFVulkanDecodeProfileData *prof; |
| 1030 | FFVulkanDecodeShared *ctx; | ||
| 1026 | 1031 | ||
| 1027 | frames_ctx->sw_format = AV_PIX_FMT_NONE; | 1032 | frames_ctx->sw_format = AV_PIX_FMT_NONE; |
| 1028 | 1033 | ||
| @@ -1059,6 +1064,11 @@ int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx) · 30 unmodified lines | |||
| 1059 | if (!dec->dedicated_dpb) | 1064 | if (!dec->dedicated_dpb) |
| 1060 | hwfc->usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; | 1065 | hwfc->usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; |
| 1061 | 1066 | ||
| 1067 | ctx = dec->shared_ctx; | ||
| 1068 | if (ctx->s.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE | | ||
| 1069 | FF_VK_EXT_VIDEO_MAINTENANCE_1)) | ||
| 1070 | hwfc->usage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; | ||
| 1071 | |||
| 1062 | return err; | 1072 | return err; |
| 1063 | } | 1073 | } |
| 1064 | 1074 | ||
| @@ -37,6 +37,7 @@ int ff_vk_filter_init_context(AVFilterContext *avctx, FFVulkanContext *s, · 36 unmodified lines | |||
| 37 | if (frames_ref) { | 37 | if (frames_ref) { |
| 38 | int no_storage = 0; | 38 | int no_storage = 0; |
| 39 | FFVulkanFunctions *vk; | 39 | FFVulkanFunctions *vk; |
| 40 | VkImageUsageFlagBits usage_req; | ||
| 40 | const VkFormat *sub = av_vkfmt_from_pixfmt(sw_format); | 41 | const VkFormat *sub = av_vkfmt_from_pixfmt(sw_format); |
| 41 | 42 | ||
| 42 | frames_ctx = (AVHWFramesContext *)frames_ref->data; | 43 | frames_ctx = (AVHWFramesContext *)frames_ref->data; |
| @@ -57,18 +58,41 @@ int ff_vk_filter_init_context(AVFilterContext *avctx, FFVulkanContext *s, · 14 unmodified lines | |||
| 57 | if (vk_frames->tiling != VK_IMAGE_TILING_OPTIMAL) | 58 | if (vk_frames->tiling != VK_IMAGE_TILING_OPTIMAL) |
| 58 | goto skip; | 59 | goto skip; |
| 59 | 60 | ||
| 60 | /* Usage mismatch */ | ||
| 61 | if ((vk_frames->usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT)) != | ||
| 62 | (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT)) | ||
| 63 | goto skip; | ||
| 64 | |||
| 65 | s->extensions = ff_vk_extensions_to_mask(vk_dev->enabled_dev_extensions, | 61 | s->extensions = ff_vk_extensions_to_mask(vk_dev->enabled_dev_extensions, |
| 66 | vk_dev->nb_enabled_dev_extensions); | 62 | vk_dev->nb_enabled_dev_extensions); |
| 63 | |||
| 64 | /* More advanced format checks */ | ||
| 67 | err = ff_vk_load_functions(device_ctx, &s->vkfn, s->extensions, 1, 1); | 65 | err = ff_vk_load_functions(device_ctx, &s->vkfn, s->extensions, 1, 1); |
| 68 | if (err < 0) | 66 | if (err < 0) |
| 69 | return err; | 67 | return err; |
| 70 | vk = &s->vkfn; | 68 | vk = &s->vkfn; |
| 71 | 69 | ||
| 70 | /* Usage mismatch */ | ||
| 71 | usage_req = VK_IMAGE_USAGE_SAMPLED_BIT | | ||
| 72 | VK_IMAGE_USAGE_STORAGE_BIT; | ||
| 73 | |||
| 74 | /* If format supports hardware encoding, make sure | ||
| 75 | * the context includes it. */ | ||
| 76 | if (vk_frames->format[1] == VK_FORMAT_UNDEFINED && | ||
| 77 | (s->extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE | | ||
| 78 | FF_VK_EXT_VIDEO_MAINTENANCE_1))) { | ||
| 79 | VkFormatProperties3 fprops = { | ||
| 80 | .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3, | ||
| 81 | }; | ||
| 82 | VkFormatProperties2 prop = { | ||
| 83 | .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, | ||
| 84 | .pNext = &fprops, | ||
| 85 | }; | ||
| 86 | vk->GetPhysicalDeviceFormatProperties2(vk_dev->phys_dev, | ||
| 87 | vk_frames->format[0], | ||
| 88 | &prop); | ||
| 89 | if (fprops.optimalTilingFeatures & VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR) | ||
| 90 | usage_req |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; | ||
| 91 | } | ||
| 92 | |||
| 93 | if ((vk_frames->usage & usage_req) != usage_req) | ||
| 94 | goto skip; | ||
| 95 | |||
| 72 | /* Check if the subformats can do storage */ | 96 | /* Check if the subformats can do storage */ |
| 73 | for (int i = 0; sub[i] != VK_FORMAT_UNDEFINED; i++) { | 97 | for (int i = 0; sub[i] != VK_FORMAT_UNDEFINED; i++) { |
| 74 | VkFormatProperties2 prop = { | 98 | VkFormatProperties2 prop = { |
| @@ -113,13 +137,6 @@ skip: · 38 unmodified lines | |||
| 113 | frames_ctx->width = width; | 137 | frames_ctx->width = width; |
| 114 | frames_ctx->height = height; | 138 | frames_ctx->height = height; |
| 115 | 139 | ||
| 116 | vk_frames = frames_ctx->hwctx; | ||
| 117 | vk_frames->tiling = VK_IMAGE_TILING_OPTIMAL; | ||
| 118 | vk_frames->usage = VK_IMAGE_USAGE_SAMPLED_BIT | | ||
| 119 | VK_IMAGE_USAGE_STORAGE_BIT | | ||
| 120 | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | | ||
| 121 | VK_IMAGE_USAGE_TRANSFER_DST_BIT; | ||
| 122 | |||
| 123 | err = av_hwframe_ctx_init(frames_ref); | 140 | err = av_hwframe_ctx_init(frames_ref); |
| 124 | if (err < 0) { | 141 | if (err < 0) { |
| 125 | av_buffer_unref(&frames_ref); | 142 | av_buffer_unref(&frames_ref); |
| @@ -2632,6 +2632,12 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) · 2631 unmodified lines | |||
| 2632 | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | | 2632 | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | |
| 2633 | VK_IMAGE_USAGE_STORAGE_BIT | | 2633 | VK_IMAGE_USAGE_STORAGE_BIT | |
| 2634 | VK_IMAGE_USAGE_SAMPLED_BIT); | 2634 | VK_IMAGE_USAGE_SAMPLED_BIT); |
| 2635 | |||
| 2636 | /* Enables encoding of images, if supported by format and extensions */ | ||
| 2637 | if ((supported_usage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) && | ||
| 2638 | (p->vkctx.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE | | ||
| 2639 | FF_VK_EXT_VIDEO_MAINTENANCE_1))) | ||
| 2640 | hwctx->usage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; | ||
| 2635 | } | 2641 | } |
| 2636 | 2642 | ||
| 2637 | /* Image creation flags. | 2643 | /* Image creation flags. |
| @@ -2650,6 +2656,28 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) · 12 unmodified lines | |||
| 2650 | } | 2656 | } |
| 2651 | } | 2657 | } |
| 2652 | 2658 | ||
| 2659 | /* If the image has an ENCODE_SRC usage, and the maintenance1 | ||
| 2660 | * extension is supported, check if it has a profile list. | ||
| 2661 | * If there's no profile list, or it has no encode operations, | ||
| 2662 | * then allow creating the image with no specific profile. */ | ||
| 2663 | if ((hwctx->usage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) && | ||
| 2664 | p->video_maint_1_features.videoMaintenance1) { | ||
| 2665 | const VkVideoProfileListInfoKHR *pl; | ||
| 2666 | pl = ff_vk_find_struct(hwctx->create_pnext, VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR); | ||
| 2667 | if (!pl) { | ||
| 2668 | hwctx->img_flags |= VK_IMAGE_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR; | ||
| 2669 | } else { | ||
| 2670 | uint32_t i; | ||
| 2671 | for (i = 0; i < pl->profileCount; i++) { | ||
| 2672 | /* Video ops start at exactly 0x00010000 */ | ||
| 2673 | if (pl->pProfiles[i].videoCodecOperation & 0xFFFF0000) | ||
| 2674 | break; | ||
| 2675 | } | ||
| 2676 | if (i == pl->profileCount) | ||
| 2677 | hwctx->img_flags |= VK_IMAGE_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR; | ||
| 2678 | } | ||
| 2679 | } | ||
| 2680 | |||
| 2653 | if (!hwctx->lock_frame) | 2681 | if (!hwctx->lock_frame) |
| 2654 | hwctx->lock_frame = lock_frame; | 2682 | hwctx->lock_frame = lock_frame; |
| 2655 | 2683 | ||