diff mbox series

[FFmpeg-devel,2/2] hwcontext_vulkan: enable encoding of images if video_maintenance1 is enabled

Message ID 20240814185134.935816-2-dev@lynne.ee
State New
Headers show
Series [FFmpeg-devel,1/2] hwcontext_vulkan: enable VK_KHR_video_maintenance1 | expand

Checks

Context Check Description
yinshiyou/configure_loongarch64 warning Failed to apply patch

Commit Message

Lynne Aug. 14, 2024, 6:51 p.m. UTC
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.
---
 libavcodec/vulkan_decode.c   | 10 ++++++++++
 libavfilter/vulkan_filter.c  | 23 ++++++++++++-----------
 libavutil/hwcontext_vulkan.c | 13 +++++++++++++
 3 files changed, 35 insertions(+), 11 deletions(-)
diff mbox series

Patch

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 cef42eeb4d..fd70d90b1a 100644
--- a/libavfilter/vulkan_filter.c
+++ b/libavfilter/vulkan_filter.c
@@ -36,6 +36,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;
@@ -56,13 +57,20 @@  int ff_vk_filter_init_context(AVFilterContext *avctx, FFVulkanContext *s,
         if (vk_frames->tiling != VK_IMAGE_TILING_OPTIMAL)
             goto skip;
 
+        s->extensions = ff_vk_extensions_to_mask(vk_dev->enabled_dev_extensions,
+                                                 vk_dev->nb_enabled_dev_extensions);
+
         /* 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))
+        usage_req = VK_IMAGE_USAGE_SAMPLED_BIT |
+                    VK_IMAGE_USAGE_STORAGE_BIT;
+        if (s->extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE |
+                             FF_VK_EXT_VIDEO_MAINTENANCE_1))
+            usage_req |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
+
+        if ((vk_frames->usage & usage_req) != usage_req)
             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;
@@ -112,13 +120,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 a82355e8bf..3ccefa9525 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -2630,6 +2630,11 @@  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 (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.
@@ -2648,6 +2653,14 @@  static int vulkan_frames_init(AVHWFramesContext *hwfc)
         }
     }
 
+    /* If image has an encode usage, yet there's no profile attached,
+     * and maintenance1 is supported, enable the profile independent
+     * creation flag. */
+    if ((hwctx->usage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) &&
+        !(ff_vk_find_struct(hwctx->create_pnext, VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR)) &&
+        p->video_maint_1_features.videoMaintenance1)
+        hwctx->img_flags |= VK_IMAGE_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR;
+
     if (!hwctx->lock_frame)
         hwctx->lock_frame = lock_frame;