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.
Showing the changes to libavfilter (1 of 3 files). Show all
Unified · Split
| @@ -37,6 +37,7 @@ int ff_vk_filter_init_context(AVFilterContext *avctx, FFVulkanContext *s, · 36 unmodified lines | ||
| 37 | 37 | if (frames_ref) { |
| 38 | 38 | int no_storage = 0; |
| 39 | 39 | FFVulkanFunctions *vk; |
| 40 | + VkImageUsageFlagBits usage_req; | |
| 40 | 41 | const VkFormat *sub = av_vkfmt_from_pixfmt(sw_format); |
| 41 | 42 | |
| 42 | 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 | 58 | if (vk_frames->tiling != VK_IMAGE_TILING_OPTIMAL) |
| 58 | 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 | 61 | s->extensions = ff_vk_extensions_to_mask(vk_dev->enabled_dev_extensions, |
| 66 | 62 | vk_dev->nb_enabled_dev_extensions); |
| 63 | + | |
| 64 | + /* More advanced format checks */ | |
| 67 | 65 | err = ff_vk_load_functions(device_ctx, &s->vkfn, s->extensions, 1, 1); |
| 68 | 66 | if (err < 0) |
| 69 | 67 | return err; |
| 70 | 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 | 96 | /* Check if the subformats can do storage */ |
| 73 | 97 | for (int i = 0; sub[i] != VK_FORMAT_UNDEFINED; i++) { |
| 74 | 98 | VkFormatProperties2 prop = { |
| @@ -113,13 +137,6 @@ skip: · 38 unmodified lines | ||
| 113 | 137 | frames_ctx->width = width; |
| 114 | 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 | 140 | err = av_hwframe_ctx_init(frames_ref); |
| 124 | 141 | if (err < 0) { |
| 125 | 142 | av_buffer_unref(&frames_ref); |