Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Jamaika1 via ffmpeg-devel <ffmpeg-devel@ffmpeg.org>
To: ffmpeg-devel@ffmpeg.org
Cc: Jamaika1 <code@ffmpeg.org>
Subject: [FFmpeg-devel] [PATCH] Changing-vulkan-file-directory (PR #20417)
Message-ID: <175691058908.25.12192413182319126055@463a07221176> (raw)

PR #20417 opened by Jamaika1
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20417
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20417.patch

Testing vulkan in msys2 ucrt gcc/mingw.


From 5501cb44351dde57d8ad9412f3106d3da3f1c968 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:41:53 +0000
Subject: [PATCH 001/118] Changing vulkan file directory

Signed-off-by: Jamaika1 <lukaszcz18@wp.pl>
---
 libavfilter/vf_avgblur_vulkan.c | 259 --------------------------------
 1 file changed, 259 deletions(-)
 delete mode 100644 libavfilter/vf_avgblur_vulkan.c

diff --git a/libavfilter/vf_avgblur_vulkan.c b/libavfilter/vf_avgblur_vulkan.c
deleted file mode 100644
index 156278dd78..0000000000
--- a/libavfilter/vf_avgblur_vulkan.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright (c) Lynne
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/random_seed.h"
-#include "libavutil/vulkan_spirv.h"
-#include "libavutil/opt.h"
-#include "vulkan_filter.h"
-
-#include "filters.h"
-#include "video.h"
-
-typedef struct AvgBlurVulkanContext {
-    FFVulkanContext vkctx;
-
-    int initialized;
-    FFVkExecPool e;
-    AVVulkanDeviceQueueFamily *qf;
-    FFVulkanShader shd;
-
-    /* Push constants / options */
-    struct {
-        float filter_norm[4];
-        int32_t filter_len[2];
-    } opts;
-
-    int size_x;
-    int size_y;
-    int planes;
-} AvgBlurVulkanContext;
-
-static const char blur_kernel[] = {
-    C(0, void distort(const ivec2 pos, const int idx)                         )
-    C(0, {                                                                    )
-    C(1,     vec4 sum = vec4(0);                                              )
-    C(1,     for (int y = -filter_len.y; y <= filter_len.y; y++)              )
-    C(1,        for (int x = -filter_len.x; x <= filter_len.x; x++)           )
-    C(2,            sum += imageLoad(input_img[idx], pos + ivec2(x, y));      )
-    C(0,                                                                      )
-    C(1,     imageStore(output_img[idx], pos, sum * filter_norm);             )
-    C(0, }                                                                    )
-};
-
-static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
-{
-    int err;
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    AvgBlurVulkanContext *s = ctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
-    FFVulkanShader *shd;
-    FFVkSPIRVCompiler *spv;
-    FFVulkanDescriptorSetBinding *desc;
-
-    spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
-    if (!s->qf) {
-        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
-        err = AVERROR(ENOTSUP);
-        goto fail;
-    }
-
-    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
-    RET(ff_vk_shader_init(vkctx, &s->shd, "avgblur",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          NULL, 0,
-                          32, 1, 1,
-                          0));
-    shd = &s->shd;
-
-    desc = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name       = "input_img",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "readonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-        {
-            .name       = "output_img",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "writeonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 2, 0, 0));
-
-    GLSLC(0, layout(push_constant, std430) uniform pushConstants {        );
-    GLSLC(1,    vec4 filter_norm;                                         );
-    GLSLC(1,    ivec2 filter_len;                                         );
-    GLSLC(0, };                                                           );
-    GLSLC(0,                                                              );
-
-    ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts),
-                                VK_SHADER_STAGE_COMPUTE_BIT);
-
-    GLSLD(   blur_kernel                                                  );
-    GLSLC(0, void main()                                                  );
-    GLSLC(0, {                                                            );
-    GLSLC(1,     ivec2 size;                                              );
-    GLSLC(1,     vec4 res;                                                );
-    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);       );
-    for (int i = 0; i < planes; i++) {
-        GLSLC(0,                                                          );
-        GLSLF(1,  size = imageSize(output_img[%i]);                     ,i);
-        GLSLC(1,  if (!IS_WITHIN(pos, size))                              );
-        GLSLC(2,      return;                                             );
-        if (s->planes & (1 << i)) {
-            GLSLF(1, distort(pos, %i);                                  ,i);
-        } else {
-            GLSLF(1, res = imageLoad(input_img[%i], pos);               ,i);
-            GLSLF(1, imageStore(output_img[%i], pos, res);              ,i);
-        }
-    }
-    GLSLC(0, }                                                            );
-
-    RET(spv->compile_shader(vkctx, spv, &s->shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(vkctx, &s->shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
-
-    s->initialized = 1;
-    s->opts.filter_len[0] = s->size_x - 1;
-    s->opts.filter_len[1] = s->size_y - 1;
-
-    s->opts.filter_norm[0] = s->opts.filter_len[0]*2 + 1;
-    s->opts.filter_norm[0] = 1.0/(s->opts.filter_norm[0]*s->opts.filter_norm[0]);
-    s->opts.filter_norm[1] = s->opts.filter_norm[0];
-    s->opts.filter_norm[2] = s->opts.filter_norm[0];
-    s->opts.filter_norm[3] = s->opts.filter_norm[0];
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-    if (spv)
-        spv->uninit(&spv);
-
-    return err;
-}
-
-static int avgblur_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
-{
-    int err;
-    AVFrame *out = NULL;
-    AVFilterContext *ctx = link->dst;
-    AvgBlurVulkanContext *s = ctx->priv;
-    AVFilterLink *outlink = ctx->outputs[0];
-
-    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-    if (!out) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    if (!s->initialized)
-        RET(init_filter(ctx, in));
-
-    RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->shd,
-                                    out, in, VK_NULL_HANDLE,
-                                    &s->opts, sizeof(s->opts)));
-
-    err = av_frame_copy_props(out, in);
-    if (err < 0)
-        goto fail;
-
-    av_frame_free(&in);
-
-    return ff_filter_frame(outlink, out);
-
-fail:
-    av_frame_free(&in);
-    av_frame_free(&out);
-    return err;
-}
-
-static void avgblur_vulkan_uninit(AVFilterContext *avctx)
-{
-    AvgBlurVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-
-    ff_vk_exec_pool_free(vkctx, &s->e);
-    ff_vk_shader_free(vkctx, &s->shd);
-
-    ff_vk_uninit(&s->vkctx);
-
-    s->initialized = 0;
-}
-
-#define OFFSET(x) offsetof(AvgBlurVulkanContext, x)
-#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
-static const AVOption avgblur_vulkan_options[] = {
-    { "sizeX",  "Set horizontal radius", OFFSET(size_x), AV_OPT_TYPE_INT, { .i64 = 3 }, 1, 32, .flags = FLAGS },
-    { "sizeY",  "Set vertical radius", OFFSET(size_y), AV_OPT_TYPE_INT, { .i64 = 3 }, 1, 32, .flags = FLAGS },
-    { "planes", "Set planes to filter (bitmask)", OFFSET(planes), AV_OPT_TYPE_INT, {.i64 = 0xF}, 0, 0xF, .flags = FLAGS },
-    { NULL },
-};
-
-AVFILTER_DEFINE_CLASS(avgblur_vulkan);
-
-static const AVFilterPad avgblur_vulkan_inputs[] = {
-    {
-        .name         = "default",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame = &avgblur_vulkan_filter_frame,
-        .config_props = &ff_vk_filter_config_input,
-    },
-};
-
-static const AVFilterPad avgblur_vulkan_outputs[] = {
-    {
-        .name = "default",
-        .type = AVMEDIA_TYPE_VIDEO,
-        .config_props = &ff_vk_filter_config_output,
-    },
-};
-
-const FFFilter ff_vf_avgblur_vulkan = {
-    .p.name         = "avgblur_vulkan",
-    .p.description  = NULL_IF_CONFIG_SMALL("Apply avgblur mask to input video"),
-    .p.priv_class   = &avgblur_vulkan_class,
-    .p.flags        = AVFILTER_FLAG_HWDEVICE,
-    .priv_size      = sizeof(AvgBlurVulkanContext),
-    .init           = &ff_vk_filter_init,
-    .uninit         = &avgblur_vulkan_uninit,
-    FILTER_INPUTS(avgblur_vulkan_inputs),
-    FILTER_OUTPUTS(avgblur_vulkan_outputs),
-    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
-    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
-};
-- 
2.49.1


From 39dcae8b9e6f6dcb149fa45416f07e10f7c0c5e3 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:45:30 +0000
Subject: [PATCH 002/118] Changing vulkan file directory

---
 libavfilter/vulkan/vf_avgblur_vulkan.c | 259 +++++++++++++++++++++++++
 1 file changed, 259 insertions(+)
 create mode 100644 libavfilter/vulkan/vf_avgblur_vulkan.c

diff --git a/libavfilter/vulkan/vf_avgblur_vulkan.c b/libavfilter/vulkan/vf_avgblur_vulkan.c
new file mode 100644
index 0000000000..9f33ec28c1
--- /dev/null
+++ b/libavfilter/vulkan/vf_avgblur_vulkan.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) Lynne
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/random_seed.h"
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+#include "libavutil/opt.h"
+#include "vulkan_filter.h"
+
+#include "libavfilter/filters.h"
+#include "libavfilter/video.h"
+
+typedef struct AvgBlurVulkanContext {
+    FFVulkanContext vkctx;
+
+    int initialized;
+    FFVkExecPool e;
+    AVVulkanDeviceQueueFamily *qf;
+    FFVulkanShader shd;
+
+    /* Push constants / options */
+    struct {
+        float filter_norm[4];
+        int32_t filter_len[2];
+    } opts;
+
+    int size_x;
+    int size_y;
+    int planes;
+} AvgBlurVulkanContext;
+
+static const char blur_kernel[] = {
+    C(0, void distort(const ivec2 pos, const int idx)                         )
+    C(0, {                                                                    )
+    C(1,     vec4 sum = vec4(0);                                              )
+    C(1,     for (int y = -filter_len.y; y <= filter_len.y; y++)              )
+    C(1,        for (int x = -filter_len.x; x <= filter_len.x; x++)           )
+    C(2,            sum += imageLoad(input_img[idx], pos + ivec2(x, y));      )
+    C(0,                                                                      )
+    C(1,     imageStore(output_img[idx], pos, sum * filter_norm);             )
+    C(0, }                                                                    )
+};
+
+static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
+{
+    int err;
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    AvgBlurVulkanContext *s = ctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
+    FFVulkanShader *shd;
+    FFVkSPIRVCompiler *spv;
+    FFVulkanDescriptorSetBinding *desc;
+
+    spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
+    if (!s->qf) {
+        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
+        err = AVERROR(ENOTSUP);
+        goto fail;
+    }
+
+    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
+    RET(ff_vk_shader_init(vkctx, &s->shd, "avgblur",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          NULL, 0,
+                          32, 1, 1,
+                          0));
+    shd = &s->shd;
+
+    desc = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name       = "input_img",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "readonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+        {
+            .name       = "output_img",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "writeonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 2, 0, 0));
+
+    GLSLC(0, layout(push_constant, std430) uniform pushConstants {        );
+    GLSLC(1,    vec4 filter_norm;                                         );
+    GLSLC(1,    ivec2 filter_len;                                         );
+    GLSLC(0, };                                                           );
+    GLSLC(0,                                                              );
+
+    ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts),
+                                VK_SHADER_STAGE_COMPUTE_BIT);
+
+    GLSLD(   blur_kernel                                                  );
+    GLSLC(0, void main()                                                  );
+    GLSLC(0, {                                                            );
+    GLSLC(1,     ivec2 size;                                              );
+    GLSLC(1,     vec4 res;                                                );
+    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);       );
+    for (int i = 0; i < planes; i++) {
+        GLSLC(0,                                                          );
+        GLSLF(1,  size = imageSize(output_img[%i]);                     ,i);
+        GLSLC(1,  if (!IS_WITHIN(pos, size))                              );
+        GLSLC(2,      return;                                             );
+        if (s->planes & (1 << i)) {
+            GLSLF(1, distort(pos, %i);                                  ,i);
+        } else {
+            GLSLF(1, res = imageLoad(input_img[%i], pos);               ,i);
+            GLSLF(1, imageStore(output_img[%i], pos, res);              ,i);
+        }
+    }
+    GLSLC(0, }                                                            );
+
+    RET(spv->compile_shader(vkctx, spv, &s->shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(vkctx, &s->shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
+
+    s->initialized = 1;
+    s->opts.filter_len[0] = s->size_x - 1;
+    s->opts.filter_len[1] = s->size_y - 1;
+
+    s->opts.filter_norm[0] = s->opts.filter_len[0]*2 + 1;
+    s->opts.filter_norm[0] = 1.0/(s->opts.filter_norm[0]*s->opts.filter_norm[0]);
+    s->opts.filter_norm[1] = s->opts.filter_norm[0];
+    s->opts.filter_norm[2] = s->opts.filter_norm[0];
+    s->opts.filter_norm[3] = s->opts.filter_norm[0];
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+    if (spv)
+        spv->uninit(&spv);
+
+    return err;
+}
+
+static int avgblur_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
+{
+    int err;
+    AVFrame *out = NULL;
+    AVFilterContext *ctx = link->dst;
+    AvgBlurVulkanContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+
+    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!out) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    if (!s->initialized)
+        RET(init_filter(ctx, in));
+
+    RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->shd,
+                                    out, in, VK_NULL_HANDLE,
+                                    &s->opts, sizeof(s->opts)));
+
+    err = av_frame_copy_props(out, in);
+    if (err < 0)
+        goto fail;
+
+    av_frame_free(&in);
+
+    return ff_filter_frame(outlink, out);
+
+fail:
+    av_frame_free(&in);
+    av_frame_free(&out);
+    return err;
+}
+
+static void avgblur_vulkan_uninit(AVFilterContext *avctx)
+{
+    AvgBlurVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+
+    ff_vk_exec_pool_free(vkctx, &s->e);
+    ff_vk_shader_free(vkctx, &s->shd);
+
+    ff_vk_uninit(&s->vkctx);
+
+    s->initialized = 0;
+}
+
+#define OFFSET(x) offsetof(AvgBlurVulkanContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
+static const AVOption avgblur_vulkan_options[] = {
+    { "sizeX",  "Set horizontal radius", OFFSET(size_x), AV_OPT_TYPE_INT, { .i64 = 3 }, 1, 32, .flags = FLAGS },
+    { "sizeY",  "Set vertical radius", OFFSET(size_y), AV_OPT_TYPE_INT, { .i64 = 3 }, 1, 32, .flags = FLAGS },
+    { "planes", "Set planes to filter (bitmask)", OFFSET(planes), AV_OPT_TYPE_INT, {.i64 = 0xF}, 0, 0xF, .flags = FLAGS },
+    { NULL },
+};
+
+AVFILTER_DEFINE_CLASS(avgblur_vulkan);
+
+static const AVFilterPad avgblur_vulkan_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = &avgblur_vulkan_filter_frame,
+        .config_props = &ff_vk_filter_config_input,
+    },
+};
+
+static const AVFilterPad avgblur_vulkan_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_VIDEO,
+        .config_props = &ff_vk_filter_config_output,
+    },
+};
+
+const FFFilter ff_vf_avgblur_vulkan = {
+    .p.name         = "avgblur_vulkan",
+    .p.description  = NULL_IF_CONFIG_SMALL("Apply avgblur mask to input video"),
+    .p.priv_class   = &avgblur_vulkan_class,
+    .p.flags        = AVFILTER_FLAG_HWDEVICE,
+    .priv_size      = sizeof(AvgBlurVulkanContext),
+    .init           = &ff_vk_filter_init,
+    .uninit         = &avgblur_vulkan_uninit,
+    FILTER_INPUTS(avgblur_vulkan_inputs),
+    FILTER_OUTPUTS(avgblur_vulkan_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};
-- 
2.49.1


From 39c595bcae324d35dcd97de9e85b3b5f653bca21 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:46:28 +0000
Subject: [PATCH 003/118] Changing vulkan file directory

---
 libavfilter/vf_blackdetect_vulkan.c | 445 ----------------------------
 1 file changed, 445 deletions(-)
 delete mode 100644 libavfilter/vf_blackdetect_vulkan.c

diff --git a/libavfilter/vf_blackdetect_vulkan.c b/libavfilter/vf_blackdetect_vulkan.c
deleted file mode 100644
index 279b057148..0000000000
--- a/libavfilter/vf_blackdetect_vulkan.c
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Copyright 2025 (c) Niklas Haas
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <float.h>
-#include "libavutil/vulkan_spirv.h"
-#include "libavutil/opt.h"
-#include "libavutil/timestamp.h"
-#include "vulkan_filter.h"
-
-#include "filters.h"
-#include "video.h"
-
-typedef struct BlackDetectVulkanContext {
-    FFVulkanContext vkctx;
-
-    int initialized;
-    FFVkExecPool e;
-    AVVulkanDeviceQueueFamily *qf;
-    FFVulkanShader shd;
-    AVBufferPool *sum_buf_pool;
-
-    double black_min_duration_time;
-    double picture_black_ratio_th;
-    double pixel_black_th;
-    int    alpha;
-
-    int64_t black_start;
-} BlackDetectVulkanContext;
-
-typedef struct BlackDetectPushData {
-    float threshold;
-} BlackDetectPushData;
-
-typedef struct BlackDetectBuf {
-#define SLICES 16
-    uint32_t slice_sum[SLICES];
-} BlackDetectBuf;
-
-static av_cold int init_filter(AVFilterContext *ctx)
-{
-    int err;
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    BlackDetectVulkanContext *s = ctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    FFVulkanShader *shd;
-    FFVkSPIRVCompiler *spv;
-    FFVulkanDescriptorSetBinding *desc;
-    const int plane = s->alpha ? 3 : 0;
-
-    const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(s->vkctx.input_format);
-    if (pixdesc->flags & AV_PIX_FMT_FLAG_RGB) {
-        av_log(ctx, AV_LOG_ERROR, "RGB inputs are not supported\n");
-        return AVERROR(ENOTSUP);
-    }
-
-    spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
-    if (!s->qf) {
-        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
-        err = AVERROR(ENOTSUP);
-        goto fail;
-    }
-
-    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
-    RET(ff_vk_shader_init(vkctx, &s->shd, "blackdetect",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          (const char *[]) { "GL_KHR_shader_subgroup_ballot" }, 1,
-                          32, 32, 1,
-                          0));
-    shd = &s->shd;
-
-    GLSLC(0, layout(push_constant, std430) uniform pushConstants {            );
-    GLSLC(1,     float threshold;                                             );
-    GLSLC(0, };                                                               );
-
-    ff_vk_shader_add_push_const(shd, 0, sizeof(BlackDetectPushData),
-                                VK_SHADER_STAGE_COMPUTE_BIT);
-
-    desc = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name       = "input_img",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "readonly",
-            .dimensions = 2,
-            .elems      = av_pix_fmt_count_planes(s->vkctx.input_format),
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        }, {
-            .name        = "sum_buffer",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "uint slice_sum[];",
-        }
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 2, 0, 0));
-
-    GLSLC(0, shared uint wg_sum;                                              );
-    GLSLC(0,                                                                  );
-    GLSLC(0, void main()                                                      );
-    GLSLC(0, {                                                                );
-    GLSLC(1,     wg_sum = 0u;                                                 );
-    GLSLC(1,     barrier();                                                   );
-    GLSLC(0,                                                                  );
-    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);           );
-    GLSLF(1,     if (!IS_WITHIN(pos, imageSize(input_img[%d])))               ,plane);
-    GLSLC(2,         return;                                                  );
-    GLSLF(1,     float value = imageLoad(input_img[%d], pos).x;               ,plane);
-    GLSLC(1,     uvec4 isblack = subgroupBallot(value <= threshold);          );
-    GLSLC(1,     if (subgroupElect())                                         );
-    GLSLC(2,         atomicAdd(wg_sum, subgroupBallotBitCount(isblack));      );
-    GLSLC(1,     barrier();                                                   );
-    GLSLC(1,     if (gl_LocalInvocationIndex == 0u)                           );
-    GLSLF(2,         atomicAdd(slice_sum[gl_WorkGroupID.x %% %du], wg_sum);   ,SLICES);
-    GLSLC(0, }                                                                );
-
-    RET(spv->compile_shader(vkctx, spv, &s->shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(vkctx, &s->shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
-
-    s->black_start = AV_NOPTS_VALUE;
-    s->initialized = 1;
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-    if (spv)
-        spv->uninit(&spv);
-
-    return err;
-}
-
-static void report_black_region(AVFilterContext *ctx, int64_t black_end)
-{
-    BlackDetectVulkanContext *s = ctx->priv;
-    const AVFilterLink *inlink = ctx->inputs[0];
-    if (s->black_start == AV_NOPTS_VALUE)
-        return;
-
-    if ((black_end - s->black_start) >= s->black_min_duration_time / av_q2d(inlink->time_base)) {
-        av_log(ctx, AV_LOG_INFO,
-               "black_start:%s black_end:%s black_duration:%s\n",
-               av_ts2timestr(s->black_start, &inlink->time_base),
-               av_ts2timestr(black_end, &inlink->time_base),
-               av_ts2timestr(black_end - s->black_start, &inlink->time_base));
-    }
-}
-
-static void evaluate(AVFilterLink *link, AVFrame *in,
-                     const BlackDetectBuf *sum)
-{
-    AVFilterContext *ctx = link->dst;
-    BlackDetectVulkanContext *s = ctx->priv;
-    FilterLink *inl = ff_filter_link(link);
-    uint64_t nb_black_pixels = 0;
-    double ratio;
-
-    for (int i = 0; i < FF_ARRAY_ELEMS(sum->slice_sum); i++)
-        nb_black_pixels += sum->slice_sum[i];
-
-    ratio = (double) nb_black_pixels / (link->w * link->h);
-
-    av_log(ctx, AV_LOG_DEBUG,
-           "frame:%"PRId64" picture_black_ratio:%f pts:%s t:%s type:%c\n",
-           inl->frame_count_out, ratio,
-           av_ts2str(in->pts), av_ts2timestr(in->pts, &in->time_base),
-           av_get_picture_type_char(in->pict_type));
-
-    if (ratio >= s->picture_black_ratio_th) {
-        if (s->black_start == AV_NOPTS_VALUE) {
-            s->black_start = in->pts;
-            av_dict_set(&in->metadata, "lavfi.black_start",
-                av_ts2timestr(in->pts, &in->time_base), 0);
-        }
-    } else if (s->black_start != AV_NOPTS_VALUE) {
-        report_black_region(ctx, in->pts);
-        av_dict_set(&in->metadata, "lavfi.black_end",
-            av_ts2timestr(in->pts, &in->time_base), 0);
-        s->black_start = AV_NOPTS_VALUE;
-    }
-}
-
-static int blackdetect_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
-{
-    int err;
-    AVFilterContext *ctx = link->dst;
-    BlackDetectVulkanContext *s = ctx->priv;
-    AVFilterLink *outlink = ctx->outputs[0];
-
-    VkImageView in_views[AV_NUM_DATA_POINTERS];
-    VkImageMemoryBarrier2 img_bar[4];
-    int nb_img_bar = 0;
-
-    FFVulkanContext *vkctx = &s->vkctx;
-    FFVulkanFunctions *vk = &vkctx->vkfn;
-    FFVkExecContext *exec = NULL;
-    AVBufferRef *sum_buf = NULL;
-    FFVkBuffer *sum_vk;
-
-    BlackDetectBuf *sum;
-    BlackDetectPushData push_data;
-
-    if (in->color_range == AVCOL_RANGE_JPEG || s->alpha) {
-        push_data.threshold = s->pixel_black_th;
-    } else {
-        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(vkctx->input_format);
-        const int depth = desc->comp[0].depth;
-        const int ymin = 16  << (depth - 8);
-        const int ymax = 235 << (depth - 8);
-        const int imax = (1 << depth) - 1;
-        push_data.threshold = (s->pixel_black_th * (ymax - ymin) + ymin) / imax;
-    }
-
-    if (!s->initialized)
-        RET(init_filter(ctx));
-
-    err = ff_vk_get_pooled_buffer(vkctx, &s->sum_buf_pool, &sum_buf,
-                                  VK_BUFFER_USAGE_TRANSFER_DST_BIT |
-                                  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
-                                  NULL,
-                                  sizeof(BlackDetectBuf),
-                                  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
-                                  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
-                                  VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
-    if (err < 0)
-        return err;
-    sum_vk = (FFVkBuffer *)sum_buf->data;
-    sum = (BlackDetectBuf *) sum_vk->mapped_mem;
-
-    exec = ff_vk_exec_get(vkctx, &s->e);
-    ff_vk_exec_start(vkctx, exec);
-
-    RET(ff_vk_exec_add_dep_frame(vkctx, exec, in,
-                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
-    RET(ff_vk_create_imageviews(vkctx, exec, in_views, in, FF_VK_REP_FLOAT));
-
-    ff_vk_shader_update_img_array(vkctx, exec, &s->shd, in, in_views, 0, 0,
-                                  VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
-
-    ff_vk_frame_barrier(vkctx, exec, in, img_bar, &nb_img_bar,
-                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                        VK_ACCESS_SHADER_READ_BIT,
-                        VK_IMAGE_LAYOUT_GENERAL,
-                        VK_QUEUE_FAMILY_IGNORED);
-
-    /* zero sum buffer */
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-            .pBufferMemoryBarriers = &(VkBufferMemoryBarrier2) {
-                .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-                .srcStageMask = VK_PIPELINE_STAGE_2_NONE,
-                .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
-                .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
-                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-                .buffer = sum_vk->buf,
-                .size = sum_vk->size,
-                .offset = 0,
-            },
-            .bufferMemoryBarrierCount = 1,
-        });
-
-    vk->CmdFillBuffer(exec->buf, sum_vk->buf, 0, sum_vk->size, 0x0);
-
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-            .pImageMemoryBarriers = img_bar,
-            .imageMemoryBarrierCount = nb_img_bar,
-            .pBufferMemoryBarriers = &(VkBufferMemoryBarrier2) {
-                .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-                .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
-                .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
-                .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
-                                 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
-                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-                .buffer = sum_vk->buf,
-                .size = sum_vk->size,
-                .offset = 0,
-            },
-            .bufferMemoryBarrierCount = 1,
-        });
-
-    RET(ff_vk_shader_update_desc_buffer(&s->vkctx, exec, &s->shd, 0, 1, 0,
-                                        sum_vk, 0, sum_vk->size,
-                                        VK_FORMAT_UNDEFINED));
-
-    ff_vk_exec_bind_shader(vkctx, exec, &s->shd);
-    ff_vk_shader_update_push_const(vkctx, exec, &s->shd, VK_SHADER_STAGE_COMPUTE_BIT,
-                                   0, sizeof(push_data), &push_data);
-
-    vk->CmdDispatch(exec->buf,
-                    FFALIGN(in->width,  s->shd.lg_size[0]) / s->shd.lg_size[0],
-                    FFALIGN(in->height, s->shd.lg_size[1]) / s->shd.lg_size[1],
-                    s->shd.lg_size[2]);
-
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-            .pBufferMemoryBarriers = &(VkBufferMemoryBarrier2) {
-                .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-                .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                .dstStageMask = VK_PIPELINE_STAGE_2_HOST_BIT,
-                .srcAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
-                                 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
-                .dstAccessMask = VK_ACCESS_HOST_READ_BIT,
-                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-                .buffer = sum_vk->buf,
-                .size = sum_vk->size,
-                .offset = 0,
-            },
-            .bufferMemoryBarrierCount = 1,
-        });
-
-    RET(ff_vk_exec_submit(vkctx, exec));
-    ff_vk_exec_wait(vkctx, exec);
-    evaluate(link, in, sum);
-
-    av_buffer_unref(&sum_buf);
-    return ff_filter_frame(outlink, in);
-
-fail:
-    if (exec)
-        ff_vk_exec_discard_deps(&s->vkctx, exec);
-    av_frame_free(&in);
-    av_buffer_unref(&sum_buf);
-    return err;
-}
-
-static void blackdetect_vulkan_uninit(AVFilterContext *avctx)
-{
-    BlackDetectVulkanContext *s = avctx->priv;
-    AVFilterLink *inlink = avctx->inputs[0];
-    FilterLink *inl = ff_filter_link(inlink);
-    FFVulkanContext *vkctx = &s->vkctx;
-
-    report_black_region(avctx, inl->current_pts);
-
-    ff_vk_exec_pool_free(vkctx, &s->e);
-    ff_vk_shader_free(vkctx, &s->shd);
-
-    av_buffer_pool_uninit(&s->sum_buf_pool);
-
-    ff_vk_uninit(&s->vkctx);
-
-    s->initialized = 0;
-}
-
-static int config_output(AVFilterLink *outlink)
-{
-    AVFilterContext *ctx = outlink->src;
-    BlackDetectVulkanContext *s = ctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(vkctx->input_format);
-
-    if (s->alpha && !(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) {
-        av_log(ctx, AV_LOG_ERROR, "Input format %s does not have an alpha channel\n",
-               av_get_pix_fmt_name(vkctx->input_format));
-        return AVERROR(EINVAL);
-    }
-
-    if (desc->flags & (AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_XYZ) ||
-        !(desc->flags & AV_PIX_FMT_FLAG_PLANAR)) {
-        av_log(ctx, AV_LOG_ERROR, "Input format %s is not planar YUV\n",
-               av_get_pix_fmt_name(vkctx->input_format));
-        return AVERROR(EINVAL);
-    }
-
-    return ff_vk_filter_config_output(outlink);
-}
-
-#define OFFSET(x) offsetof(BlackDetectVulkanContext, x)
-#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
-static const AVOption blackdetect_vulkan_options[] = {
-    { "d",                  "set minimum detected black duration in seconds", OFFSET(black_min_duration_time), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 0, DBL_MAX, FLAGS },
-    { "black_min_duration", "set minimum detected black duration in seconds", OFFSET(black_min_duration_time), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 0, DBL_MAX, FLAGS },
-    { "picture_black_ratio_th", "set the picture black ratio threshold", OFFSET(picture_black_ratio_th), AV_OPT_TYPE_DOUBLE, {.dbl=.98}, 0, 1, FLAGS },
-    { "pic_th",                 "set the picture black ratio threshold", OFFSET(picture_black_ratio_th), AV_OPT_TYPE_DOUBLE, {.dbl=.98}, 0, 1, FLAGS },
-    { "pixel_black_th", "set the pixel black threshold", OFFSET(pixel_black_th), AV_OPT_TYPE_DOUBLE, {.dbl=.10}, 0, 1, FLAGS },
-    { "pix_th",         "set the pixel black threshold", OFFSET(pixel_black_th), AV_OPT_TYPE_DOUBLE, {.dbl=.10}, 0, 1, FLAGS },
-    { "alpha",          "check alpha instead of luma", OFFSET(alpha), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
-    { NULL }
-};
-
-AVFILTER_DEFINE_CLASS(blackdetect_vulkan);
-
-static const AVFilterPad blackdetect_vulkan_inputs[] = {
-    {
-        .name         = "default",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame = &blackdetect_vulkan_filter_frame,
-        .config_props = &ff_vk_filter_config_input,
-    },
-};
-
-static const AVFilterPad blackdetect_vulkan_outputs[] = {
-    {
-        .name = "default",
-        .type = AVMEDIA_TYPE_VIDEO,
-        .config_props = &config_output,
-    },
-};
-
-const FFFilter ff_vf_blackdetect_vulkan = {
-    .p.name         = "blackdetect_vulkan",
-    .p.description  = NULL_IF_CONFIG_SMALL("Detect video intervals that are (almost) black."),
-    .p.priv_class   = &blackdetect_vulkan_class,
-    .p.flags        = AVFILTER_FLAG_HWDEVICE,
-    .priv_size      = sizeof(BlackDetectVulkanContext),
-    .init           = &ff_vk_filter_init,
-    .uninit         = &blackdetect_vulkan_uninit,
-    FILTER_INPUTS(blackdetect_vulkan_inputs),
-    FILTER_OUTPUTS(blackdetect_vulkan_outputs),
-    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
-    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
-};
-- 
2.49.1


From 32384df38c93bbb7f6aa317482e80325ea0af68b Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:48:05 +0000
Subject: [PATCH 004/118] Changing vulkan file directory

---
 libavfilter/vulkan/vf_blackdetect_vulkan.c | 445 +++++++++++++++++++++
 1 file changed, 445 insertions(+)
 create mode 100644 libavfilter/vulkan/vf_blackdetect_vulkan.c

diff --git a/libavfilter/vulkan/vf_blackdetect_vulkan.c b/libavfilter/vulkan/vf_blackdetect_vulkan.c
new file mode 100644
index 0000000000..b7330c297e
--- /dev/null
+++ b/libavfilter/vulkan/vf_blackdetect_vulkan.c
@@ -0,0 +1,445 @@
+/*
+ * Copyright 2025 (c) Niklas Haas
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <float.h>
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+#include "libavutil/opt.h"
+#include "libavutil/timestamp.h"
+#include "vulkan_filter.h"
+
+#include "libavfilter/filters.h"
+#include "libavfilter/video.h"
+
+typedef struct BlackDetectVulkanContext {
+    FFVulkanContext vkctx;
+
+    int initialized;
+    FFVkExecPool e;
+    AVVulkanDeviceQueueFamily *qf;
+    FFVulkanShader shd;
+    AVBufferPool *sum_buf_pool;
+
+    double black_min_duration_time;
+    double picture_black_ratio_th;
+    double pixel_black_th;
+    int    alpha;
+
+    int64_t black_start;
+} BlackDetectVulkanContext;
+
+typedef struct BlackDetectPushData {
+    float threshold;
+} BlackDetectPushData;
+
+typedef struct BlackDetectBuf {
+#define SLICES 16
+    uint32_t slice_sum[SLICES];
+} BlackDetectBuf;
+
+static av_cold int init_filter(AVFilterContext *ctx)
+{
+    int err;
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    BlackDetectVulkanContext *s = ctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    FFVulkanShader *shd;
+    FFVkSPIRVCompiler *spv;
+    FFVulkanDescriptorSetBinding *desc;
+    const int plane = s->alpha ? 3 : 0;
+
+    const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(s->vkctx.input_format);
+    if (pixdesc->flags & AV_PIX_FMT_FLAG_RGB) {
+        av_log(ctx, AV_LOG_ERROR, "RGB inputs are not supported\n");
+        return AVERROR(ENOTSUP);
+    }
+
+    spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
+    if (!s->qf) {
+        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
+        err = AVERROR(ENOTSUP);
+        goto fail;
+    }
+
+    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
+    RET(ff_vk_shader_init(vkctx, &s->shd, "blackdetect",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          (const char *[]) { "GL_KHR_shader_subgroup_ballot" }, 1,
+                          32, 32, 1,
+                          0));
+    shd = &s->shd;
+
+    GLSLC(0, layout(push_constant, std430) uniform pushConstants {            );
+    GLSLC(1,     float threshold;                                             );
+    GLSLC(0, };                                                               );
+
+    ff_vk_shader_add_push_const(shd, 0, sizeof(BlackDetectPushData),
+                                VK_SHADER_STAGE_COMPUTE_BIT);
+
+    desc = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name       = "input_img",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "readonly",
+            .dimensions = 2,
+            .elems      = av_pix_fmt_count_planes(s->vkctx.input_format),
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        }, {
+            .name        = "sum_buffer",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "uint slice_sum[];",
+        }
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 2, 0, 0));
+
+    GLSLC(0, shared uint wg_sum;                                              );
+    GLSLC(0,                                                                  );
+    GLSLC(0, void main()                                                      );
+    GLSLC(0, {                                                                );
+    GLSLC(1,     wg_sum = 0u;                                                 );
+    GLSLC(1,     barrier();                                                   );
+    GLSLC(0,                                                                  );
+    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);           );
+    GLSLF(1,     if (!IS_WITHIN(pos, imageSize(input_img[%d])))               ,plane);
+    GLSLC(2,         return;                                                  );
+    GLSLF(1,     float value = imageLoad(input_img[%d], pos).x;               ,plane);
+    GLSLC(1,     uvec4 isblack = subgroupBallot(value <= threshold);          );
+    GLSLC(1,     if (subgroupElect())                                         );
+    GLSLC(2,         atomicAdd(wg_sum, subgroupBallotBitCount(isblack));      );
+    GLSLC(1,     barrier();                                                   );
+    GLSLC(1,     if (gl_LocalInvocationIndex == 0u)                           );
+    GLSLF(2,         atomicAdd(slice_sum[gl_WorkGroupID.x %% %du], wg_sum);   ,SLICES);
+    GLSLC(0, }                                                                );
+
+    RET(spv->compile_shader(vkctx, spv, &s->shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(vkctx, &s->shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
+
+    s->black_start = AV_NOPTS_VALUE;
+    s->initialized = 1;
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+    if (spv)
+        spv->uninit(&spv);
+
+    return err;
+}
+
+static void report_black_region(AVFilterContext *ctx, int64_t black_end)
+{
+    BlackDetectVulkanContext *s = ctx->priv;
+    const AVFilterLink *inlink = ctx->inputs[0];
+    if (s->black_start == AV_NOPTS_VALUE)
+        return;
+
+    if ((black_end - s->black_start) >= s->black_min_duration_time / av_q2d(inlink->time_base)) {
+        av_log(ctx, AV_LOG_INFO,
+               "black_start:%s black_end:%s black_duration:%s\n",
+               av_ts2timestr(s->black_start, &inlink->time_base),
+               av_ts2timestr(black_end, &inlink->time_base),
+               av_ts2timestr(black_end - s->black_start, &inlink->time_base));
+    }
+}
+
+static void evaluate(AVFilterLink *link, AVFrame *in,
+                     const BlackDetectBuf *sum)
+{
+    AVFilterContext *ctx = link->dst;
+    BlackDetectVulkanContext *s = ctx->priv;
+    FilterLink *inl = ff_filter_link(link);
+    uint64_t nb_black_pixels = 0;
+    double ratio;
+
+    for (int i = 0; i < FF_ARRAY_ELEMS(sum->slice_sum); i++)
+        nb_black_pixels += sum->slice_sum[i];
+
+    ratio = (double) nb_black_pixels / (link->w * link->h);
+
+    av_log(ctx, AV_LOG_DEBUG,
+           "frame:%"PRId64" picture_black_ratio:%f pts:%s t:%s type:%c\n",
+           inl->frame_count_out, ratio,
+           av_ts2str(in->pts), av_ts2timestr(in->pts, &in->time_base),
+           av_get_picture_type_char(in->pict_type));
+
+    if (ratio >= s->picture_black_ratio_th) {
+        if (s->black_start == AV_NOPTS_VALUE) {
+            s->black_start = in->pts;
+            av_dict_set(&in->metadata, "lavfi.black_start",
+                av_ts2timestr(in->pts, &in->time_base), 0);
+        }
+    } else if (s->black_start != AV_NOPTS_VALUE) {
+        report_black_region(ctx, in->pts);
+        av_dict_set(&in->metadata, "lavfi.black_end",
+            av_ts2timestr(in->pts, &in->time_base), 0);
+        s->black_start = AV_NOPTS_VALUE;
+    }
+}
+
+static int blackdetect_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
+{
+    int err;
+    AVFilterContext *ctx = link->dst;
+    BlackDetectVulkanContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+
+    VkImageView in_views[AV_NUM_DATA_POINTERS];
+    VkImageMemoryBarrier2 img_bar[4];
+    int nb_img_bar = 0;
+
+    FFVulkanContext *vkctx = &s->vkctx;
+    FFVulkanFunctions *vk = &vkctx->vkfn;
+    FFVkExecContext *exec = NULL;
+    AVBufferRef *sum_buf = NULL;
+    FFVkBuffer *sum_vk;
+
+    BlackDetectBuf *sum;
+    BlackDetectPushData push_data;
+
+    if (in->color_range == AVCOL_RANGE_JPEG || s->alpha) {
+        push_data.threshold = s->pixel_black_th;
+    } else {
+        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(vkctx->input_format);
+        const int depth = desc->comp[0].depth;
+        const int ymin = 16  << (depth - 8);
+        const int ymax = 235 << (depth - 8);
+        const int imax = (1 << depth) - 1;
+        push_data.threshold = (s->pixel_black_th * (ymax - ymin) + ymin) / imax;
+    }
+
+    if (!s->initialized)
+        RET(init_filter(ctx));
+
+    err = ff_vk_get_pooled_buffer(vkctx, &s->sum_buf_pool, &sum_buf,
+                                  VK_BUFFER_USAGE_TRANSFER_DST_BIT |
+                                  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+                                  NULL,
+                                  sizeof(BlackDetectBuf),
+                                  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+                                  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+                                  VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
+    if (err < 0)
+        return err;
+    sum_vk = (FFVkBuffer *)sum_buf->data;
+    sum = (BlackDetectBuf *) sum_vk->mapped_mem;
+
+    exec = ff_vk_exec_get(vkctx, &s->e);
+    ff_vk_exec_start(vkctx, exec);
+
+    RET(ff_vk_exec_add_dep_frame(vkctx, exec, in,
+                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
+    RET(ff_vk_create_imageviews(vkctx, exec, in_views, in, FF_VK_REP_FLOAT));
+
+    ff_vk_shader_update_img_array(vkctx, exec, &s->shd, in, in_views, 0, 0,
+                                  VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
+
+    ff_vk_frame_barrier(vkctx, exec, in, img_bar, &nb_img_bar,
+                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                        VK_ACCESS_SHADER_READ_BIT,
+                        VK_IMAGE_LAYOUT_GENERAL,
+                        VK_QUEUE_FAMILY_IGNORED);
+
+    /* zero sum buffer */
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+            .pBufferMemoryBarriers = &(VkBufferMemoryBarrier2) {
+                .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+                .srcStageMask = VK_PIPELINE_STAGE_2_NONE,
+                .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
+                .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                .buffer = sum_vk->buf,
+                .size = sum_vk->size,
+                .offset = 0,
+            },
+            .bufferMemoryBarrierCount = 1,
+        });
+
+    vk->CmdFillBuffer(exec->buf, sum_vk->buf, 0, sum_vk->size, 0x0);
+
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+            .pImageMemoryBarriers = img_bar,
+            .imageMemoryBarrierCount = nb_img_bar,
+            .pBufferMemoryBarriers = &(VkBufferMemoryBarrier2) {
+                .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+                .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
+                .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+                .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
+                                 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
+                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                .buffer = sum_vk->buf,
+                .size = sum_vk->size,
+                .offset = 0,
+            },
+            .bufferMemoryBarrierCount = 1,
+        });
+
+    RET(ff_vk_shader_update_desc_buffer(&s->vkctx, exec, &s->shd, 0, 1, 0,
+                                        sum_vk, 0, sum_vk->size,
+                                        VK_FORMAT_UNDEFINED));
+
+    ff_vk_exec_bind_shader(vkctx, exec, &s->shd);
+    ff_vk_shader_update_push_const(vkctx, exec, &s->shd, VK_SHADER_STAGE_COMPUTE_BIT,
+                                   0, sizeof(push_data), &push_data);
+
+    vk->CmdDispatch(exec->buf,
+                    FFALIGN(in->width,  s->shd.lg_size[0]) / s->shd.lg_size[0],
+                    FFALIGN(in->height, s->shd.lg_size[1]) / s->shd.lg_size[1],
+                    s->shd.lg_size[2]);
+
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+            .pBufferMemoryBarriers = &(VkBufferMemoryBarrier2) {
+                .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+                .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                .dstStageMask = VK_PIPELINE_STAGE_2_HOST_BIT,
+                .srcAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
+                                 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
+                .dstAccessMask = VK_ACCESS_HOST_READ_BIT,
+                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                .buffer = sum_vk->buf,
+                .size = sum_vk->size,
+                .offset = 0,
+            },
+            .bufferMemoryBarrierCount = 1,
+        });
+
+    RET(ff_vk_exec_submit(vkctx, exec));
+    ff_vk_exec_wait(vkctx, exec);
+    evaluate(link, in, sum);
+
+    av_buffer_unref(&sum_buf);
+    return ff_filter_frame(outlink, in);
+
+fail:
+    if (exec)
+        ff_vk_exec_discard_deps(&s->vkctx, exec);
+    av_frame_free(&in);
+    av_buffer_unref(&sum_buf);
+    return err;
+}
+
+static void blackdetect_vulkan_uninit(AVFilterContext *avctx)
+{
+    BlackDetectVulkanContext *s = avctx->priv;
+    AVFilterLink *inlink = avctx->inputs[0];
+    FilterLink *inl = ff_filter_link(inlink);
+    FFVulkanContext *vkctx = &s->vkctx;
+
+    report_black_region(avctx, inl->current_pts);
+
+    ff_vk_exec_pool_free(vkctx, &s->e);
+    ff_vk_shader_free(vkctx, &s->shd);
+
+    av_buffer_pool_uninit(&s->sum_buf_pool);
+
+    ff_vk_uninit(&s->vkctx);
+
+    s->initialized = 0;
+}
+
+static int config_output(AVFilterLink *outlink)
+{
+    AVFilterContext *ctx = outlink->src;
+    BlackDetectVulkanContext *s = ctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(vkctx->input_format);
+
+    if (s->alpha && !(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) {
+        av_log(ctx, AV_LOG_ERROR, "Input format %s does not have an alpha channel\n",
+               av_get_pix_fmt_name(vkctx->input_format));
+        return AVERROR(EINVAL);
+    }
+
+    if (desc->flags & (AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_XYZ) ||
+        !(desc->flags & AV_PIX_FMT_FLAG_PLANAR)) {
+        av_log(ctx, AV_LOG_ERROR, "Input format %s is not planar YUV\n",
+               av_get_pix_fmt_name(vkctx->input_format));
+        return AVERROR(EINVAL);
+    }
+
+    return ff_vk_filter_config_output(outlink);
+}
+
+#define OFFSET(x) offsetof(BlackDetectVulkanContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
+static const AVOption blackdetect_vulkan_options[] = {
+    { "d",                  "set minimum detected black duration in seconds", OFFSET(black_min_duration_time), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 0, DBL_MAX, FLAGS },
+    { "black_min_duration", "set minimum detected black duration in seconds", OFFSET(black_min_duration_time), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 0, DBL_MAX, FLAGS },
+    { "picture_black_ratio_th", "set the picture black ratio threshold", OFFSET(picture_black_ratio_th), AV_OPT_TYPE_DOUBLE, {.dbl=.98}, 0, 1, FLAGS },
+    { "pic_th",                 "set the picture black ratio threshold", OFFSET(picture_black_ratio_th), AV_OPT_TYPE_DOUBLE, {.dbl=.98}, 0, 1, FLAGS },
+    { "pixel_black_th", "set the pixel black threshold", OFFSET(pixel_black_th), AV_OPT_TYPE_DOUBLE, {.dbl=.10}, 0, 1, FLAGS },
+    { "pix_th",         "set the pixel black threshold", OFFSET(pixel_black_th), AV_OPT_TYPE_DOUBLE, {.dbl=.10}, 0, 1, FLAGS },
+    { "alpha",          "check alpha instead of luma", OFFSET(alpha), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(blackdetect_vulkan);
+
+static const AVFilterPad blackdetect_vulkan_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = &blackdetect_vulkan_filter_frame,
+        .config_props = &ff_vk_filter_config_input,
+    },
+};
+
+static const AVFilterPad blackdetect_vulkan_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_VIDEO,
+        .config_props = &config_output,
+    },
+};
+
+const FFFilter ff_vf_blackdetect_vulkan = {
+    .p.name         = "blackdetect_vulkan",
+    .p.description  = NULL_IF_CONFIG_SMALL("Detect video intervals that are (almost) black."),
+    .p.priv_class   = &blackdetect_vulkan_class,
+    .p.flags        = AVFILTER_FLAG_HWDEVICE,
+    .priv_size      = sizeof(BlackDetectVulkanContext),
+    .init           = &ff_vk_filter_init,
+    .uninit         = &blackdetect_vulkan_uninit,
+    FILTER_INPUTS(blackdetect_vulkan_inputs),
+    FILTER_OUTPUTS(blackdetect_vulkan_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};
-- 
2.49.1


From eadf958003b170b5409c6580ba7369cb48da4f2d Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:48:41 +0000
Subject: [PATCH 005/118] Changing vulkan file directory

---
 libavfilter/vf_blend_vulkan.c | 399 ----------------------------------
 1 file changed, 399 deletions(-)
 delete mode 100644 libavfilter/vf_blend_vulkan.c

diff --git a/libavfilter/vf_blend_vulkan.c b/libavfilter/vf_blend_vulkan.c
deleted file mode 100644
index 57cf3c696b..0000000000
--- a/libavfilter/vf_blend_vulkan.c
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * copyright (c) 2021-2022 Wu Jianhua <jianhua.wu@intel.com>
- * Copyright (c) Lynne
- *
- * The blend modes are based on the blend.c.
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/random_seed.h"
-#include "libavutil/vulkan_spirv.h"
-#include "libavutil/opt.h"
-#include "vulkan_filter.h"
-
-#include "filters.h"
-#include "framesync.h"
-#include "blend.h"
-#include "video.h"
-
-#define IN_TOP    0
-#define IN_BOTTOM 1
-
-typedef struct FilterParamsVulkan {
-    const char *blend;
-    const char *blend_func;
-    double opacity;
-    enum BlendMode mode;
-} FilterParamsVulkan;
-
-typedef struct BlendVulkanContext {
-    FFVulkanContext vkctx;
-    FFFrameSync fs;
-
-    int initialized;
-    FFVkExecPool e;
-    AVVulkanDeviceQueueFamily *qf;
-    FFVulkanShader shd;
-
-    FilterParamsVulkan params[4];
-    double all_opacity;
-    enum BlendMode all_mode;
-} BlendVulkanContext;
-
-#define DEFINE_BLEND_MODE(MODE, EXPR) \
-static const char blend_##MODE[] = "blend_"#MODE; \
-static const char blend_##MODE##_func[] = { \
-    C(0, vec4 blend_##MODE(vec4 top, vec4 bottom, float opacity) {   ) \
-    C(1,     vec4 dst = EXPR;                                        ) \
-    C(1,     return dst;                                             ) \
-    C(0, }                                                           ) \
-};
-
-#define A top
-#define B bottom
-
-#define FN(EXPR) A + ((EXPR) - A) * opacity
-
-DEFINE_BLEND_MODE(NORMAL, A * opacity + B * (1.0f - opacity))
-DEFINE_BLEND_MODE(MULTIPLY, FN(1.0f * A * B / 1.0f))
-
-static inline void init_blend_func(FilterParamsVulkan *param)
-{
-#define CASE(MODE) case BLEND_##MODE: \
-            param->blend = blend_##MODE;\
-            param->blend_func =  blend_##MODE##_func; \
-            break;
-
-    switch (param->mode) {
-    CASE(NORMAL)
-    CASE(MULTIPLY)
-    default: param->blend = NULL; break;
-    }
-
-#undef CASE
-}
-
-static int config_params(AVFilterContext *avctx)
-{
-    BlendVulkanContext *s = avctx->priv;
-
-    for (int plane = 0; plane < FF_ARRAY_ELEMS(s->params); plane++) {
-        FilterParamsVulkan *param = &s->params[plane];
-
-        if (s->all_mode >= 0)
-            param->mode = s->all_mode;
-        if (s->all_opacity < 1)
-            param->opacity = s->all_opacity;
-
-        init_blend_func(param);
-        if (!param->blend) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "Currently the blend mode specified is not supported yet.\n");
-            return AVERROR(EINVAL);
-        }
-    }
-
-    return 0;
-}
-
-static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
-                           char *res, int res_len, int flags)
-{
-    int ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
-    if (ret < 0)
-        return ret;
-
-    return config_params(ctx);
-}
-
-static av_cold int init_filter(AVFilterContext *avctx)
-{
-    int err = 0;
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    BlendVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
-    FFVulkanShader *shd = &s->shd;
-    FFVkSPIRVCompiler *spv;
-    FFVulkanDescriptorSetBinding *desc;
-
-    spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
-    if (!s->qf) {
-        av_log(avctx, AV_LOG_ERROR, "Device has no compute queues\n");
-        err = AVERROR(ENOTSUP);
-        goto fail;
-    }
-
-    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
-    RET(ff_vk_shader_init(vkctx, &s->shd, "blend",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          NULL, 0,
-                          32, 32, 1,
-                          0));
-
-    desc = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name       = "top_images",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "readonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-        {
-            .name       = "bottom_images",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "readonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-        {
-            .name       = "output_images",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "writeonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 3, 0, 0));
-
-    for (int i = 0, j = 0; i < planes; i++) {
-        for (j = 0; j < i; j++)
-            if (s->params[i].blend_func == s->params[j].blend_func)
-                break;
-        /* note: the bracket is needed, for GLSLD is a macro with multiple statements. */
-        if (j == i) {
-            GLSLD(s->params[i].blend_func);
-        }
-    }
-
-    GLSLC(0, void main()                                                    );
-    GLSLC(0, {                                                              );
-    GLSLC(1,     ivec2 size;                                                );
-    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);         );
-    for (int i = 0; i < planes; i++) {
-        GLSLC(0,                                                            );
-        GLSLF(1, size = imageSize(output_images[%i]);                     ,i);
-        GLSLC(1, if (IS_WITHIN(pos, size)) {                                );
-        GLSLF(2,     const vec4 top = imageLoad(top_images[%i], pos);       ,i);
-        GLSLF(2,     const vec4 bottom = imageLoad(bottom_images[%i], pos); ,i);
-        GLSLF(2,     const float opacity = %f;                            ,s->params[i].opacity);
-        GLSLF(2,     vec4 dst = %s(top, bottom, opacity);                 ,s->params[i].blend);
-        GLSLC(0,                                                            );
-        GLSLF(2,     imageStore(output_images[%i], pos, dst);             ,i);
-        GLSLC(1, }                                                          );
-    }
-    GLSLC(0, }                                                              );
-
-    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
-
-    s->initialized = 1;
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-    if (spv)
-        spv->uninit(&spv);
-
-    return err;
-}
-
-static int blend_frame(FFFrameSync *fs)
-{
-    int err;
-    AVFilterContext *avctx = fs->parent;
-    BlendVulkanContext *s = avctx->priv;
-    AVFilterLink *outlink = avctx->outputs[0];
-    AVFrame *top, *bottom, *out;
-
-    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-    if (!out) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    RET(ff_framesync_get_frame(fs, IN_TOP,    &top,    0));
-    RET(ff_framesync_get_frame(fs, IN_BOTTOM, &bottom, 0));
-
-    RET(av_frame_copy_props(out, top));
-
-    if (!s->initialized) {
-        AVHWFramesContext *top_fc = (AVHWFramesContext*)top->hw_frames_ctx->data;
-        AVHWFramesContext *bottom_fc = (AVHWFramesContext*)bottom->hw_frames_ctx->data;
-        if (top_fc->sw_format != bottom_fc->sw_format) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "Currently the sw format of the bottom video need to match the top!\n");
-            err = AVERROR(EINVAL);
-            goto fail;
-        }
-        RET(init_filter(avctx));
-    }
-
-    RET(ff_vk_filter_process_Nin(&s->vkctx, &s->e, &s->shd,
-                                 out, (AVFrame *[]){ top, bottom }, 2,
-                                 VK_NULL_HANDLE, NULL, 0));
-
-    return ff_filter_frame(outlink, out);
-
-fail:
-    av_frame_free(&out);
-    return err;
-}
-
-static av_cold int init(AVFilterContext *avctx)
-{
-    BlendVulkanContext *s = avctx->priv;
-
-    s->fs.on_event = blend_frame;
-
-    return ff_vk_filter_init(avctx);
-}
-
-static av_cold void uninit(AVFilterContext *avctx)
-{
-    BlendVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-
-    ff_vk_exec_pool_free(vkctx, &s->e);
-    ff_vk_shader_free(vkctx, &s->shd);
-
-    ff_vk_uninit(&s->vkctx);
-    ff_framesync_uninit(&s->fs);
-
-    s->initialized = 0;
-}
-
-static int config_props_output(AVFilterLink *outlink)
-{
-    int err;
-    FilterLink *outl       = ff_filter_link(outlink);
-    AVFilterContext *avctx = outlink->src;
-    BlendVulkanContext *s = avctx->priv;
-    AVFilterLink *toplink = avctx->inputs[IN_TOP];
-    FilterLink   *tl      = ff_filter_link(toplink);
-    AVFilterLink *bottomlink = avctx->inputs[IN_BOTTOM];
-
-    if (toplink->w != bottomlink->w || toplink->h != bottomlink->h) {
-        av_log(avctx, AV_LOG_ERROR, "First input link %s parameters "
-                "(size %dx%d) do not match the corresponding "
-                "second input link %s parameters (size %dx%d)\n",
-                avctx->input_pads[IN_TOP].name, toplink->w, toplink->h,
-                avctx->input_pads[IN_BOTTOM].name, bottomlink->w, bottomlink->h);
-        return AVERROR(EINVAL);
-    }
-
-    outlink->sample_aspect_ratio = toplink->sample_aspect_ratio;
-    outl->frame_rate = tl->frame_rate;
-
-    RET(ff_vk_filter_config_output(outlink));
-
-    RET(ff_framesync_init_dualinput(&s->fs, avctx));
-
-    RET(ff_framesync_configure(&s->fs));
-    outlink->time_base = s->fs.time_base;
-
-    RET(config_params(avctx));
-
-fail:
-    return err;
-}
-
-static int activate(AVFilterContext *avctx)
-{
-    BlendVulkanContext *s = avctx->priv;
-    return ff_framesync_activate(&s->fs);
-}
-
-#define OFFSET(x) offsetof(BlendVulkanContext, x)
-#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
-
-static const AVOption blend_vulkan_options[] = {
-    { "c0_mode", "set component #0 blend mode", OFFSET(params[0].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, .unit = "mode" },
-    { "c1_mode", "set component #1 blend mode", OFFSET(params[1].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, .unit = "mode" },
-    { "c2_mode", "set component #2 blend mode", OFFSET(params[2].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, .unit = "mode" },
-    { "c3_mode", "set component #3 blend mode", OFFSET(params[3].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, .unit = "mode" },
-    { "all_mode", "set blend mode for all components", OFFSET(all_mode), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, BLEND_NB - 1, FLAGS, .unit = "mode" },
-        { "normal",   "", 0, AV_OPT_TYPE_CONST, { .i64 = BLEND_NORMAL   }, 0, 0, FLAGS, .unit = "mode" },
-        { "multiply", "", 0, AV_OPT_TYPE_CONST, { .i64 = BLEND_MULTIPLY }, 0, 0, FLAGS, .unit = "mode" },
-
-    { "c0_opacity",  "set color component #0 opacity", OFFSET(params[0].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS },
-    { "c1_opacity",  "set color component #1 opacity", OFFSET(params[1].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS },
-    { "c2_opacity",  "set color component #2 opacity", OFFSET(params[2].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS },
-    { "c3_opacity",  "set color component #3 opacity", OFFSET(params[3].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS },
-    { "all_opacity", "set opacity for all color components", OFFSET(all_opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS },
-
-    { NULL }
-};
-
-AVFILTER_DEFINE_CLASS(blend_vulkan);
-
-static const AVFilterPad blend_vulkan_inputs[] = {
-    {
-        .name         = "top",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .config_props = &ff_vk_filter_config_input,
-    },
-    {
-        .name         = "bottom",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .config_props = &ff_vk_filter_config_input,
-    },
-};
-
-
-static const AVFilterPad blend_vulkan_outputs[] = {
-    {
-        .name         = "default",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .config_props = &config_props_output,
-    }
-};
-
-const FFFilter ff_vf_blend_vulkan = {
-    .p.name          = "blend_vulkan",
-    .p.description   = NULL_IF_CONFIG_SMALL("Blend two video frames in Vulkan"),
-    .p.priv_class    = &blend_vulkan_class,
-    .p.flags         = AVFILTER_FLAG_HWDEVICE,
-    .priv_size       = sizeof(BlendVulkanContext),
-    .init            = &init,
-    .uninit          = &uninit,
-    .activate        = &activate,
-    FILTER_INPUTS(blend_vulkan_inputs),
-    FILTER_OUTPUTS(blend_vulkan_outputs),
-    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
-    .flags_internal  = FF_FILTER_FLAG_HWFRAME_AWARE,
-    .process_command = &process_command,
-};
-- 
2.49.1


From 58cedfe6764899d191e4f3e42f557023b63eb477 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:49:14 +0000
Subject: [PATCH 006/118] Changing vulkan file directory

---
 libavfilter/vulkan/vf_blend_vulkan.c | 399 +++++++++++++++++++++++++++
 1 file changed, 399 insertions(+)
 create mode 100644 libavfilter/vulkan/vf_blend_vulkan.c

diff --git a/libavfilter/vulkan/vf_blend_vulkan.c b/libavfilter/vulkan/vf_blend_vulkan.c
new file mode 100644
index 0000000000..83e217be02
--- /dev/null
+++ b/libavfilter/vulkan/vf_blend_vulkan.c
@@ -0,0 +1,399 @@
+/*
+ * copyright (c) 2021-2022 Wu Jianhua <jianhua.wu@intel.com>
+ * Copyright (c) Lynne
+ *
+ * The blend modes are based on the blend.c.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/random_seed.h"
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+#include "libavutil/opt.h"
+#include "vulkan_filter.h"
+
+#include "libavfilter/filters.h"
+#include "libavfilter/framesync.h"
+#include "libavfilter/blend.h"
+#include "libavfilter/video.h"
+
+#define IN_TOP    0
+#define IN_BOTTOM 1
+
+typedef struct FilterParamsVulkan {
+    const char *blend;
+    const char *blend_func;
+    double opacity;
+    enum BlendMode mode;
+} FilterParamsVulkan;
+
+typedef struct BlendVulkanContext {
+    FFVulkanContext vkctx;
+    FFFrameSync fs;
+
+    int initialized;
+    FFVkExecPool e;
+    AVVulkanDeviceQueueFamily *qf;
+    FFVulkanShader shd;
+
+    FilterParamsVulkan params[4];
+    double all_opacity;
+    enum BlendMode all_mode;
+} BlendVulkanContext;
+
+#define DEFINE_BLEND_MODE(MODE, EXPR) \
+static const char blend_##MODE[] = "blend_"#MODE; \
+static const char blend_##MODE##_func[] = { \
+    C(0, vec4 blend_##MODE(vec4 top, vec4 bottom, float opacity) {   ) \
+    C(1,     vec4 dst = EXPR;                                        ) \
+    C(1,     return dst;                                             ) \
+    C(0, }                                                           ) \
+};
+
+#define A top
+#define B bottom
+
+#define FN(EXPR) A + ((EXPR) - A) * opacity
+
+DEFINE_BLEND_MODE(NORMAL, A * opacity + B * (1.0f - opacity))
+DEFINE_BLEND_MODE(MULTIPLY, FN(1.0f * A * B / 1.0f))
+
+static inline void init_blend_func(FilterParamsVulkan *param)
+{
+#define CASE(MODE) case BLEND_##MODE: \
+            param->blend = blend_##MODE;\
+            param->blend_func =  blend_##MODE##_func; \
+            break;
+
+    switch (param->mode) {
+    CASE(NORMAL)
+    CASE(MULTIPLY)
+    default: param->blend = NULL; break;
+    }
+
+#undef CASE
+}
+
+static int config_params(AVFilterContext *avctx)
+{
+    BlendVulkanContext *s = avctx->priv;
+
+    for (int plane = 0; plane < FF_ARRAY_ELEMS(s->params); plane++) {
+        FilterParamsVulkan *param = &s->params[plane];
+
+        if (s->all_mode >= 0)
+            param->mode = s->all_mode;
+        if (s->all_opacity < 1)
+            param->opacity = s->all_opacity;
+
+        init_blend_func(param);
+        if (!param->blend) {
+            av_log(avctx, AV_LOG_ERROR,
+                   "Currently the blend mode specified is not supported yet.\n");
+            return AVERROR(EINVAL);
+        }
+    }
+
+    return 0;
+}
+
+static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
+                           char *res, int res_len, int flags)
+{
+    int ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
+    if (ret < 0)
+        return ret;
+
+    return config_params(ctx);
+}
+
+static av_cold int init_filter(AVFilterContext *avctx)
+{
+    int err = 0;
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    BlendVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
+    FFVulkanShader *shd = &s->shd;
+    FFVkSPIRVCompiler *spv;
+    FFVulkanDescriptorSetBinding *desc;
+
+    spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
+    if (!s->qf) {
+        av_log(avctx, AV_LOG_ERROR, "Device has no compute queues\n");
+        err = AVERROR(ENOTSUP);
+        goto fail;
+    }
+
+    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
+    RET(ff_vk_shader_init(vkctx, &s->shd, "blend",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          NULL, 0,
+                          32, 32, 1,
+                          0));
+
+    desc = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name       = "top_images",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "readonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+        {
+            .name       = "bottom_images",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "readonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+        {
+            .name       = "output_images",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "writeonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 3, 0, 0));
+
+    for (int i = 0, j = 0; i < planes; i++) {
+        for (j = 0; j < i; j++)
+            if (s->params[i].blend_func == s->params[j].blend_func)
+                break;
+        /* note: the bracket is needed, for GLSLD is a macro with multiple statements. */
+        if (j == i) {
+            GLSLD(s->params[i].blend_func);
+        }
+    }
+
+    GLSLC(0, void main()                                                    );
+    GLSLC(0, {                                                              );
+    GLSLC(1,     ivec2 size;                                                );
+    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);         );
+    for (int i = 0; i < planes; i++) {
+        GLSLC(0,                                                            );
+        GLSLF(1, size = imageSize(output_images[%i]);                     ,i);
+        GLSLC(1, if (IS_WITHIN(pos, size)) {                                );
+        GLSLF(2,     const vec4 top = imageLoad(top_images[%i], pos);       ,i);
+        GLSLF(2,     const vec4 bottom = imageLoad(bottom_images[%i], pos); ,i);
+        GLSLF(2,     const float opacity = %f;                            ,s->params[i].opacity);
+        GLSLF(2,     vec4 dst = %s(top, bottom, opacity);                 ,s->params[i].blend);
+        GLSLC(0,                                                            );
+        GLSLF(2,     imageStore(output_images[%i], pos, dst);             ,i);
+        GLSLC(1, }                                                          );
+    }
+    GLSLC(0, }                                                              );
+
+    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
+
+    s->initialized = 1;
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+    if (spv)
+        spv->uninit(&spv);
+
+    return err;
+}
+
+static int blend_frame(FFFrameSync *fs)
+{
+    int err;
+    AVFilterContext *avctx = fs->parent;
+    BlendVulkanContext *s = avctx->priv;
+    AVFilterLink *outlink = avctx->outputs[0];
+    AVFrame *top, *bottom, *out;
+
+    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!out) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    RET(ff_framesync_get_frame(fs, IN_TOP,    &top,    0));
+    RET(ff_framesync_get_frame(fs, IN_BOTTOM, &bottom, 0));
+
+    RET(av_frame_copy_props(out, top));
+
+    if (!s->initialized) {
+        AVHWFramesContext *top_fc = (AVHWFramesContext*)top->hw_frames_ctx->data;
+        AVHWFramesContext *bottom_fc = (AVHWFramesContext*)bottom->hw_frames_ctx->data;
+        if (top_fc->sw_format != bottom_fc->sw_format) {
+            av_log(avctx, AV_LOG_ERROR,
+                   "Currently the sw format of the bottom video need to match the top!\n");
+            err = AVERROR(EINVAL);
+            goto fail;
+        }
+        RET(init_filter(avctx));
+    }
+
+    RET(ff_vk_filter_process_Nin(&s->vkctx, &s->e, &s->shd,
+                                 out, (AVFrame *[]){ top, bottom }, 2,
+                                 VK_NULL_HANDLE, NULL, 0));
+
+    return ff_filter_frame(outlink, out);
+
+fail:
+    av_frame_free(&out);
+    return err;
+}
+
+static av_cold int init(AVFilterContext *avctx)
+{
+    BlendVulkanContext *s = avctx->priv;
+
+    s->fs.on_event = blend_frame;
+
+    return ff_vk_filter_init(avctx);
+}
+
+static av_cold void uninit(AVFilterContext *avctx)
+{
+    BlendVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+
+    ff_vk_exec_pool_free(vkctx, &s->e);
+    ff_vk_shader_free(vkctx, &s->shd);
+
+    ff_vk_uninit(&s->vkctx);
+    ff_framesync_uninit(&s->fs);
+
+    s->initialized = 0;
+}
+
+static int config_props_output(AVFilterLink *outlink)
+{
+    int err;
+    FilterLink *outl       = ff_filter_link(outlink);
+    AVFilterContext *avctx = outlink->src;
+    BlendVulkanContext *s = avctx->priv;
+    AVFilterLink *toplink = avctx->inputs[IN_TOP];
+    FilterLink   *tl      = ff_filter_link(toplink);
+    AVFilterLink *bottomlink = avctx->inputs[IN_BOTTOM];
+
+    if (toplink->w != bottomlink->w || toplink->h != bottomlink->h) {
+        av_log(avctx, AV_LOG_ERROR, "First input link %s parameters "
+                "(size %dx%d) do not match the corresponding "
+                "second input link %s parameters (size %dx%d)\n",
+                avctx->input_pads[IN_TOP].name, toplink->w, toplink->h,
+                avctx->input_pads[IN_BOTTOM].name, bottomlink->w, bottomlink->h);
+        return AVERROR(EINVAL);
+    }
+
+    outlink->sample_aspect_ratio = toplink->sample_aspect_ratio;
+    outl->frame_rate = tl->frame_rate;
+
+    RET(ff_vk_filter_config_output(outlink));
+
+    RET(ff_framesync_init_dualinput(&s->fs, avctx));
+
+    RET(ff_framesync_configure(&s->fs));
+    outlink->time_base = s->fs.time_base;
+
+    RET(config_params(avctx));
+
+fail:
+    return err;
+}
+
+static int activate(AVFilterContext *avctx)
+{
+    BlendVulkanContext *s = avctx->priv;
+    return ff_framesync_activate(&s->fs);
+}
+
+#define OFFSET(x) offsetof(BlendVulkanContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
+
+static const AVOption blend_vulkan_options[] = {
+    { "c0_mode", "set component #0 blend mode", OFFSET(params[0].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, .unit = "mode" },
+    { "c1_mode", "set component #1 blend mode", OFFSET(params[1].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, .unit = "mode" },
+    { "c2_mode", "set component #2 blend mode", OFFSET(params[2].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, .unit = "mode" },
+    { "c3_mode", "set component #3 blend mode", OFFSET(params[3].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, .unit = "mode" },
+    { "all_mode", "set blend mode for all components", OFFSET(all_mode), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, BLEND_NB - 1, FLAGS, .unit = "mode" },
+        { "normal",   "", 0, AV_OPT_TYPE_CONST, { .i64 = BLEND_NORMAL   }, 0, 0, FLAGS, .unit = "mode" },
+        { "multiply", "", 0, AV_OPT_TYPE_CONST, { .i64 = BLEND_MULTIPLY }, 0, 0, FLAGS, .unit = "mode" },
+
+    { "c0_opacity",  "set color component #0 opacity", OFFSET(params[0].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS },
+    { "c1_opacity",  "set color component #1 opacity", OFFSET(params[1].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS },
+    { "c2_opacity",  "set color component #2 opacity", OFFSET(params[2].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS },
+    { "c3_opacity",  "set color component #3 opacity", OFFSET(params[3].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS },
+    { "all_opacity", "set opacity for all color components", OFFSET(all_opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS },
+
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(blend_vulkan);
+
+static const AVFilterPad blend_vulkan_inputs[] = {
+    {
+        .name         = "top",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = &ff_vk_filter_config_input,
+    },
+    {
+        .name         = "bottom",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = &ff_vk_filter_config_input,
+    },
+};
+
+
+static const AVFilterPad blend_vulkan_outputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = &config_props_output,
+    }
+};
+
+const FFFilter ff_vf_blend_vulkan = {
+    .p.name          = "blend_vulkan",
+    .p.description   = NULL_IF_CONFIG_SMALL("Blend two video frames in Vulkan"),
+    .p.priv_class    = &blend_vulkan_class,
+    .p.flags         = AVFILTER_FLAG_HWDEVICE,
+    .priv_size       = sizeof(BlendVulkanContext),
+    .init            = &init,
+    .uninit          = &uninit,
+    .activate        = &activate,
+    FILTER_INPUTS(blend_vulkan_inputs),
+    FILTER_OUTPUTS(blend_vulkan_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
+    .flags_internal  = FF_FILTER_FLAG_HWFRAME_AWARE,
+    .process_command = &process_command,
+};
-- 
2.49.1


From 8dd9511e075f43937fdcc39335adb76150e32497 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:49:57 +0000
Subject: [PATCH 007/118] Changing vulkan file directory

---
 libavfilter/vf_bwdif_vulkan.c | 337 ----------------------------------
 1 file changed, 337 deletions(-)
 delete mode 100644 libavfilter/vf_bwdif_vulkan.c

diff --git a/libavfilter/vf_bwdif_vulkan.c b/libavfilter/vf_bwdif_vulkan.c
deleted file mode 100644
index 549e814886..0000000000
--- a/libavfilter/vf_bwdif_vulkan.c
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * Copyright (c) Lynne
- * Copyright (C) 2018 Philip Langdale <philipl@overt.org>
- * Copyright (C) 2016 Thomas Mundt <loudmax@yahoo.de>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/random_seed.h"
-#include "libavutil/opt.h"
-#include "libavutil/vulkan_spirv.h"
-#include "vulkan_filter.h"
-#include "yadif.h"
-#include "filters.h"
-
-typedef struct BWDIFVulkanContext {
-    YADIFContext yadif;
-    FFVulkanContext vkctx;
-
-    int initialized;
-    FFVkExecPool e;
-    AVVulkanDeviceQueueFamily *qf;
-    FFVulkanShader shd;
-} BWDIFVulkanContext;
-
-typedef struct BWDIFParameters {
-    int parity;
-    int tff;
-    int current_field;
-} BWDIFParameters;
-
-extern const char *ff_source_bwdif_comp;
-
-static av_cold int init_filter(AVFilterContext *ctx)
-{
-    int err;
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    BWDIFVulkanContext *s = ctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
-    FFVulkanShader *shd;
-    FFVkSPIRVCompiler *spv;
-    FFVulkanDescriptorSetBinding *desc;
-
-    spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
-    if (!s->qf) {
-        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
-        err = AVERROR(ENOTSUP);
-        goto fail;
-    }
-
-    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
-
-    RET(ff_vk_shader_init(vkctx, &s->shd, "bwdif",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          NULL, 0,
-                          1, 64, 1,
-                          0));
-    shd = &s->shd;
-
-    desc = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name       = "prev",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "readonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-        {
-            .name       = "cur",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "readonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-        {
-            .name       = "next",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "readonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-        {
-            .name       = "dst",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "writeonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 4, 0, 0));
-
-    GLSLC(0, layout(push_constant, std430) uniform pushConstants {                 );
-    GLSLC(1,    int parity;                                                        );
-    GLSLC(1,    int tff;                                                           );
-    GLSLC(1,    int current_field;                                                 );
-    GLSLC(0, };                                                                    );
-
-    ff_vk_shader_add_push_const(&s->shd, 0, sizeof(BWDIFParameters),
-                                VK_SHADER_STAGE_COMPUTE_BIT);
-
-    GLSLD(ff_source_bwdif_comp                                                     );
-    GLSLC(0, void main()                                                           );
-    GLSLC(0, {                                                                     );
-    GLSLC(1,     ivec2 size;                                                       );
-    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);                );
-    GLSLC(1,     bool filter_field = ((pos.y ^ parity) & 1) == 1;                  );
-    GLSLF(1,     bool is_intra = filter_field && (current_field == %i);           ,YADIF_FIELD_END);
-    GLSLC(1,     bool field_parity = (parity ^ tff) != 0;                          );
-    GLSLC(0,                                                                       );
-    GLSLC(1,     size = imageSize(dst[0]);                                         );
-    GLSLC(1,     if (!IS_WITHIN(pos, size)) {                                      );
-    GLSLC(2,         return;                                                       );
-    GLSLC(1,     } else if (is_intra) {                                            );
-    for (int i = 0; i < planes; i++) {
-        if (i == 1) {
-            GLSLF(2, size = imageSize(dst[%i]);                                    ,i);
-            GLSLC(2, if (!IS_WITHIN(pos, size))                                    );
-            GLSLC(3,     return;                                                   );
-        }
-        GLSLF(2,     process_plane_intra(%i, pos);                                 ,i);
-    }
-    GLSLC(1,     } else if (filter_field) {                                        );
-    for (int i = 0; i < planes; i++) {
-        if (i == 1) {
-            GLSLF(2, size = imageSize(dst[%i]);                                    ,i);
-            GLSLC(2, if (!IS_WITHIN(pos, size))                                    );
-            GLSLC(3,     return;                                                   );
-        }
-        GLSLF(2,     process_plane(%i, pos, filter_field, is_intra, field_parity); ,i);
-    }
-    GLSLC(1,     } else {                                                          );
-    for (int i = 0; i < planes; i++) {
-        if (i == 1) {
-            GLSLF(2, size = imageSize(dst[%i]);                                    ,i);
-            GLSLC(2, if (!IS_WITHIN(pos, size))                                    );
-            GLSLC(3,     return;                                                   );
-        }
-        GLSLF(2,     imageStore(dst[%i], pos, imageLoad(cur[%i], pos));            ,i, i);
-    }
-    GLSLC(1,     }                                                                 );
-    GLSLC(0, }                                                                     );
-
-    RET(spv->compile_shader(vkctx, spv, &s->shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(vkctx, &s->shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
-
-    s->initialized = 1;
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-    if (spv)
-        spv->uninit(&spv);
-
-    return err;
-}
-
-static void bwdif_vulkan_filter_frame(AVFilterContext *ctx, AVFrame *dst,
-                                      int parity, int tff)
-{
-    BWDIFVulkanContext *s = ctx->priv;
-    YADIFContext *y = &s->yadif;
-    BWDIFParameters params = {
-        .parity = parity,
-        .tff = tff,
-        .current_field = y->current_field,
-    };
-
-    ff_vk_filter_process_Nin(&s->vkctx, &s->e, &s->shd, dst,
-                             (AVFrame *[]){ y->prev, y->cur, y->next }, 3,
-                             VK_NULL_HANDLE, &params, sizeof(params));
-
-    if (y->current_field == YADIF_FIELD_END)
-        y->current_field = YADIF_FIELD_NORMAL;
-}
-
-static void bwdif_vulkan_uninit(AVFilterContext *avctx)
-{
-    BWDIFVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-
-    ff_vk_exec_pool_free(vkctx, &s->e);
-    ff_vk_shader_free(vkctx, &s->shd);
-
-    ff_vk_uninit(&s->vkctx);
-
-    ff_yadif_uninit(avctx);
-
-    s->initialized = 0;
-}
-
-static int bwdif_vulkan_config_input(AVFilterLink *inlink)
-{
-    FilterLink *l = ff_filter_link(inlink);
-    AVHWFramesContext *input_frames;
-    AVFilterContext *avctx = inlink->dst;
-    BWDIFVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-
-    if (!l->hw_frames_ctx) {
-        av_log(inlink->dst, AV_LOG_ERROR, "Vulkan filtering requires a "
-               "hardware frames context on the input.\n");
-        return AVERROR(EINVAL);
-    }
-
-    input_frames = (AVHWFramesContext *)l->hw_frames_ctx->data;
-    if (input_frames->format != AV_PIX_FMT_VULKAN)
-        return AVERROR(EINVAL);
-
-    /* Extract the device and default output format from the first input. */
-    if (avctx->inputs[0] != inlink)
-        return 0;
-
-    /* Save the ref, without reffing it */
-    vkctx->input_frames_ref = l->hw_frames_ctx;
-
-    /* Defaults */
-    vkctx->output_format = input_frames->sw_format;
-    vkctx->output_width  = inlink->w;
-    vkctx->output_height = inlink->h;
-
-    return 0;
-}
-
-static int bwdif_vulkan_config_output(AVFilterLink *outlink)
-{
-    FilterLink *l = ff_filter_link(outlink);
-    int err;
-    AVFilterContext *avctx = outlink->src;
-    BWDIFVulkanContext *s = avctx->priv;
-    YADIFContext *y = &s->yadif;
-    FFVulkanContext *vkctx = &s->vkctx;
-
-    av_buffer_unref(&l->hw_frames_ctx);
-
-    err = ff_vk_filter_init_context(avctx, vkctx, vkctx->input_frames_ref,
-                                    vkctx->output_width, vkctx->output_height,
-                                    vkctx->output_format);
-    if (err < 0)
-        return err;
-
-    /* For logging */
-    vkctx->class = y->class;
-
-    l->hw_frames_ctx = av_buffer_ref(vkctx->frames_ref);
-    if (!l->hw_frames_ctx)
-        return AVERROR(ENOMEM);
-
-    err = ff_yadif_config_output_common(outlink);
-    if (err < 0)
-        return err;
-
-    y->csp = av_pix_fmt_desc_get(vkctx->frames->sw_format);
-    y->filter = bwdif_vulkan_filter_frame;
-
-    if (AV_CEIL_RSHIFT(outlink->w, y->csp->log2_chroma_w) < 4 || AV_CEIL_RSHIFT(outlink->h, y->csp->log2_chroma_h) < 4) {
-        av_log(avctx, AV_LOG_ERROR, "Video with planes less than 4 columns or lines is not supported\n");
-        return AVERROR(EINVAL);
-    }
-
-    return init_filter(avctx);
-}
-
-static const AVClass bwdif_vulkan_class = {
-    .class_name = "bwdif_vulkan",
-    .item_name  = av_default_item_name,
-    .option     = ff_yadif_options,
-    .version    = LIBAVUTIL_VERSION_INT,
-    .category   = AV_CLASS_CATEGORY_FILTER,
-};
-
-static const AVFilterPad bwdif_vulkan_inputs[] = {
-    {
-        .name         = "default",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame  = ff_yadif_filter_frame,
-        .config_props = &bwdif_vulkan_config_input,
-    },
-};
-
-static const AVFilterPad bwdif_vulkan_outputs[] = {
-    {
-        .name = "default",
-        .type = AVMEDIA_TYPE_VIDEO,
-        .request_frame = ff_yadif_request_frame,
-        .config_props = &bwdif_vulkan_config_output,
-    },
-};
-
-const FFFilter ff_vf_bwdif_vulkan = {
-    .p.name         = "bwdif_vulkan",
-    .p.description  = NULL_IF_CONFIG_SMALL("Deinterlace Vulkan frames via bwdif"),
-    .p.priv_class   = &bwdif_vulkan_class,
-    .p.flags        = AVFILTER_FLAG_HWDEVICE |
-                      AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
-    .priv_size      = sizeof(BWDIFVulkanContext),
-    .init           = &ff_vk_filter_init,
-    .uninit         = &bwdif_vulkan_uninit,
-    FILTER_INPUTS(bwdif_vulkan_inputs),
-    FILTER_OUTPUTS(bwdif_vulkan_outputs),
-    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
-    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
-};
-- 
2.49.1


From 868579008423a7861e65f4bd2a7812839f4d1159 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:51:02 +0000
Subject: [PATCH 008/118] Changing vulkan file directory

---
 libavfilter/vulkan/vf_bwdif_vulkan.c | 337 +++++++++++++++++++++++++++
 1 file changed, 337 insertions(+)
 create mode 100644 libavfilter/vulkan/vf_bwdif_vulkan.c

diff --git a/libavfilter/vulkan/vf_bwdif_vulkan.c b/libavfilter/vulkan/vf_bwdif_vulkan.c
new file mode 100644
index 0000000000..7164fe69ba
--- /dev/null
+++ b/libavfilter/vulkan/vf_bwdif_vulkan.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) Lynne
+ * Copyright (C) 2018 Philip Langdale <philipl@overt.org>
+ * Copyright (C) 2016 Thomas Mundt <loudmax@yahoo.de>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/random_seed.h"
+#include "libavutil/opt.h"
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+#include "vulkan_filter.h"
+#include "libavfilter/yadif.h"
+#include "libavfilter/filters.h"
+
+typedef struct BWDIFVulkanContext {
+    YADIFContext yadif;
+    FFVulkanContext vkctx;
+
+    int initialized;
+    FFVkExecPool e;
+    AVVulkanDeviceQueueFamily *qf;
+    FFVulkanShader shd;
+} BWDIFVulkanContext;
+
+typedef struct BWDIFParameters {
+    int parity;
+    int tff;
+    int current_field;
+} BWDIFParameters;
+
+extern const char *ff_source_bwdif_comp;
+
+static av_cold int init_filter(AVFilterContext *ctx)
+{
+    int err;
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    BWDIFVulkanContext *s = ctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
+    FFVulkanShader *shd;
+    FFVkSPIRVCompiler *spv;
+    FFVulkanDescriptorSetBinding *desc;
+
+    spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
+    if (!s->qf) {
+        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
+        err = AVERROR(ENOTSUP);
+        goto fail;
+    }
+
+    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
+
+    RET(ff_vk_shader_init(vkctx, &s->shd, "bwdif",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          NULL, 0,
+                          1, 64, 1,
+                          0));
+    shd = &s->shd;
+
+    desc = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name       = "prev",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "readonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+        {
+            .name       = "cur",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "readonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+        {
+            .name       = "next",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "readonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+        {
+            .name       = "dst",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "writeonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 4, 0, 0));
+
+    GLSLC(0, layout(push_constant, std430) uniform pushConstants {                 );
+    GLSLC(1,    int parity;                                                        );
+    GLSLC(1,    int tff;                                                           );
+    GLSLC(1,    int current_field;                                                 );
+    GLSLC(0, };                                                                    );
+
+    ff_vk_shader_add_push_const(&s->shd, 0, sizeof(BWDIFParameters),
+                                VK_SHADER_STAGE_COMPUTE_BIT);
+
+    GLSLD(ff_source_bwdif_comp                                                     );
+    GLSLC(0, void main()                                                           );
+    GLSLC(0, {                                                                     );
+    GLSLC(1,     ivec2 size;                                                       );
+    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);                );
+    GLSLC(1,     bool filter_field = ((pos.y ^ parity) & 1) == 1;                  );
+    GLSLF(1,     bool is_intra = filter_field && (current_field == %i);           ,YADIF_FIELD_END);
+    GLSLC(1,     bool field_parity = (parity ^ tff) != 0;                          );
+    GLSLC(0,                                                                       );
+    GLSLC(1,     size = imageSize(dst[0]);                                         );
+    GLSLC(1,     if (!IS_WITHIN(pos, size)) {                                      );
+    GLSLC(2,         return;                                                       );
+    GLSLC(1,     } else if (is_intra) {                                            );
+    for (int i = 0; i < planes; i++) {
+        if (i == 1) {
+            GLSLF(2, size = imageSize(dst[%i]);                                    ,i);
+            GLSLC(2, if (!IS_WITHIN(pos, size))                                    );
+            GLSLC(3,     return;                                                   );
+        }
+        GLSLF(2,     process_plane_intra(%i, pos);                                 ,i);
+    }
+    GLSLC(1,     } else if (filter_field) {                                        );
+    for (int i = 0; i < planes; i++) {
+        if (i == 1) {
+            GLSLF(2, size = imageSize(dst[%i]);                                    ,i);
+            GLSLC(2, if (!IS_WITHIN(pos, size))                                    );
+            GLSLC(3,     return;                                                   );
+        }
+        GLSLF(2,     process_plane(%i, pos, filter_field, is_intra, field_parity); ,i);
+    }
+    GLSLC(1,     } else {                                                          );
+    for (int i = 0; i < planes; i++) {
+        if (i == 1) {
+            GLSLF(2, size = imageSize(dst[%i]);                                    ,i);
+            GLSLC(2, if (!IS_WITHIN(pos, size))                                    );
+            GLSLC(3,     return;                                                   );
+        }
+        GLSLF(2,     imageStore(dst[%i], pos, imageLoad(cur[%i], pos));            ,i, i);
+    }
+    GLSLC(1,     }                                                                 );
+    GLSLC(0, }                                                                     );
+
+    RET(spv->compile_shader(vkctx, spv, &s->shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(vkctx, &s->shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
+
+    s->initialized = 1;
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+    if (spv)
+        spv->uninit(&spv);
+
+    return err;
+}
+
+static void bwdif_vulkan_filter_frame(AVFilterContext *ctx, AVFrame *dst,
+                                      int parity, int tff)
+{
+    BWDIFVulkanContext *s = ctx->priv;
+    YADIFContext *y = &s->yadif;
+    BWDIFParameters params = {
+        .parity = parity,
+        .tff = tff,
+        .current_field = y->current_field,
+    };
+
+    ff_vk_filter_process_Nin(&s->vkctx, &s->e, &s->shd, dst,
+                             (AVFrame *[]){ y->prev, y->cur, y->next }, 3,
+                             VK_NULL_HANDLE, &params, sizeof(params));
+
+    if (y->current_field == YADIF_FIELD_END)
+        y->current_field = YADIF_FIELD_NORMAL;
+}
+
+static void bwdif_vulkan_uninit(AVFilterContext *avctx)
+{
+    BWDIFVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+
+    ff_vk_exec_pool_free(vkctx, &s->e);
+    ff_vk_shader_free(vkctx, &s->shd);
+
+    ff_vk_uninit(&s->vkctx);
+
+    ff_yadif_uninit(avctx);
+
+    s->initialized = 0;
+}
+
+static int bwdif_vulkan_config_input(AVFilterLink *inlink)
+{
+    FilterLink *l = ff_filter_link(inlink);
+    AVHWFramesContext *input_frames;
+    AVFilterContext *avctx = inlink->dst;
+    BWDIFVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+
+    if (!l->hw_frames_ctx) {
+        av_log(inlink->dst, AV_LOG_ERROR, "Vulkan filtering requires a "
+               "hardware frames context on the input.\n");
+        return AVERROR(EINVAL);
+    }
+
+    input_frames = (AVHWFramesContext *)l->hw_frames_ctx->data;
+    if (input_frames->format != AV_PIX_FMT_VULKAN)
+        return AVERROR(EINVAL);
+
+    /* Extract the device and default output format from the first input. */
+    if (avctx->inputs[0] != inlink)
+        return 0;
+
+    /* Save the ref, without reffing it */
+    vkctx->input_frames_ref = l->hw_frames_ctx;
+
+    /* Defaults */
+    vkctx->output_format = input_frames->sw_format;
+    vkctx->output_width  = inlink->w;
+    vkctx->output_height = inlink->h;
+
+    return 0;
+}
+
+static int bwdif_vulkan_config_output(AVFilterLink *outlink)
+{
+    FilterLink *l = ff_filter_link(outlink);
+    int err;
+    AVFilterContext *avctx = outlink->src;
+    BWDIFVulkanContext *s = avctx->priv;
+    YADIFContext *y = &s->yadif;
+    FFVulkanContext *vkctx = &s->vkctx;
+
+    av_buffer_unref(&l->hw_frames_ctx);
+
+    err = ff_vk_filter_init_context(avctx, vkctx, vkctx->input_frames_ref,
+                                    vkctx->output_width, vkctx->output_height,
+                                    vkctx->output_format);
+    if (err < 0)
+        return err;
+
+    /* For logging */
+    vkctx->class = y->class;
+
+    l->hw_frames_ctx = av_buffer_ref(vkctx->frames_ref);
+    if (!l->hw_frames_ctx)
+        return AVERROR(ENOMEM);
+
+    err = ff_yadif_config_output_common(outlink);
+    if (err < 0)
+        return err;
+
+    y->csp = av_pix_fmt_desc_get(vkctx->frames->sw_format);
+    y->filter = bwdif_vulkan_filter_frame;
+
+    if (AV_CEIL_RSHIFT(outlink->w, y->csp->log2_chroma_w) < 4 || AV_CEIL_RSHIFT(outlink->h, y->csp->log2_chroma_h) < 4) {
+        av_log(avctx, AV_LOG_ERROR, "Video with planes less than 4 columns or lines is not supported\n");
+        return AVERROR(EINVAL);
+    }
+
+    return init_filter(avctx);
+}
+
+static const AVClass bwdif_vulkan_class = {
+    .class_name = "bwdif_vulkan",
+    .item_name  = av_default_item_name,
+    .option     = ff_yadif_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+    .category   = AV_CLASS_CATEGORY_FILTER,
+};
+
+static const AVFilterPad bwdif_vulkan_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame  = ff_yadif_filter_frame,
+        .config_props = &bwdif_vulkan_config_input,
+    },
+};
+
+static const AVFilterPad bwdif_vulkan_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_VIDEO,
+        .request_frame = ff_yadif_request_frame,
+        .config_props = &bwdif_vulkan_config_output,
+    },
+};
+
+const FFFilter ff_vf_bwdif_vulkan = {
+    .p.name         = "bwdif_vulkan",
+    .p.description  = NULL_IF_CONFIG_SMALL("Deinterlace Vulkan frames via bwdif"),
+    .p.priv_class   = &bwdif_vulkan_class,
+    .p.flags        = AVFILTER_FLAG_HWDEVICE |
+                      AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
+    .priv_size      = sizeof(BWDIFVulkanContext),
+    .init           = &ff_vk_filter_init,
+    .uninit         = &bwdif_vulkan_uninit,
+    FILTER_INPUTS(bwdif_vulkan_inputs),
+    FILTER_OUTPUTS(bwdif_vulkan_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};
-- 
2.49.1


From bb950737d8c70903138cf874c893d793e8c9225b Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:51:40 +0000
Subject: [PATCH 009/118] Changing vulkan file directory

---
 libavfilter/vf_chromaber_vulkan.c | 264 ------------------------------
 1 file changed, 264 deletions(-)
 delete mode 100644 libavfilter/vf_chromaber_vulkan.c

diff --git a/libavfilter/vf_chromaber_vulkan.c b/libavfilter/vf_chromaber_vulkan.c
deleted file mode 100644
index 65b53afd64..0000000000
--- a/libavfilter/vf_chromaber_vulkan.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright (c) Lynne
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/random_seed.h"
-#include "libavutil/opt.h"
-#include "libavutil/vulkan_spirv.h"
-#include "vulkan_filter.h"
-
-#include "filters.h"
-#include "video.h"
-
-typedef struct ChromaticAberrationVulkanContext {
-    FFVulkanContext vkctx;
-
-    int initialized;
-    FFVkExecPool e;
-    AVVulkanDeviceQueueFamily *qf;
-    FFVulkanShader shd;
-    VkSampler sampler;
-
-    /* Push constants / options */
-    struct {
-        float dist[2];
-    } opts;
-} ChromaticAberrationVulkanContext;
-
-static const char distort_chroma_kernel[] = {
-    C(0, void distort_rgb(ivec2 size, ivec2 pos)                               )
-    C(0, {                                                                     )
-    C(1,     const vec2 p = ((vec2(pos)/vec2(size)) - 0.5f)*2.0f;              )
-    C(1,     const vec2 o = p * (dist - 1.0f);                                 )
-    C(0,                                                                       )
-    C(1,     vec4 res;                                                         )
-    C(1,     res.r = texture(input_img[0], ((p - o)/2.0f) + 0.5f).r;           )
-    C(1,     res.g = texture(input_img[0], ((p    )/2.0f) + 0.5f).g;           )
-    C(1,     res.b = texture(input_img[0], ((p + o)/2.0f) + 0.5f).b;           )
-    C(1,     res.a = texture(input_img[0], ((p    )/2.0f) + 0.5f).a;           )
-    C(1,     imageStore(output_img[0], pos, res);                              )
-    C(0, }                                                                     )
-    C(0,                                                                       )
-    C(0, void distort_chroma(int idx, ivec2 size, ivec2 pos)                   )
-    C(0, {                                                                     )
-    C(1,     vec2 p = ((vec2(pos)/vec2(size)) - 0.5f)*2.0f;                    )
-    C(1,     float d = sqrt(p.x*p.x + p.y*p.y);                                )
-    C(1,     p *= d / (d*dist);                                                )
-    C(1,     vec4 res = texture(input_img[idx], (p/2.0f) + 0.5f);              )
-    C(1,     imageStore(output_img[idx], pos, res);                            )
-    C(0, }                                                                     )
-};
-
-static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
-{
-    int err;
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    ChromaticAberrationVulkanContext *s = ctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
-    FFVulkanShader *shd = &s->shd;
-    FFVkSPIRVCompiler *spv;
-    FFVulkanDescriptorSetBinding *desc;
-
-    /* Normalize options */
-    s->opts.dist[0] = (s->opts.dist[0] / 100.0f) + 1.0f;
-    s->opts.dist[1] = (s->opts.dist[1] / 100.0f) + 1.0f;
-
-    spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
-    if (!s->qf) {
-        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
-        err = AVERROR(ENOTSUP);
-        goto fail;
-    }
-
-    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
-    RET(ff_vk_init_sampler(vkctx, &s->sampler, 0, VK_FILTER_LINEAR));
-    RET(ff_vk_shader_init(vkctx, &s->shd, "chromatic_abberation",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          NULL, 0,
-                          32, 32, 1,
-                          0));
-
-    GLSLC(0, layout(push_constant, std430) uniform pushConstants {        );
-    GLSLC(1,    vec2 dist;                                                );
-    GLSLC(0, };                                                           );
-    GLSLC(0,                                                              );
-
-    ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts),
-                                VK_SHADER_STAGE_COMPUTE_BIT);
-
-    desc = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name       = "input_img",
-            .type       = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-            .samplers   = DUP_SAMPLER(s->sampler),
-        },
-        {
-            .name       = "output_img",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "writeonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 2, 0, 0));
-
-    GLSLD(   distort_chroma_kernel                                        );
-    GLSLC(0, void main()                                                  );
-    GLSLC(0, {                                                            );
-    GLSLC(1,     ivec2 pos = ivec2(gl_GlobalInvocationID.xy);             );
-    if (planes == 1) {
-        GLSLC(1, distort_rgb(imageSize(output_img[0]), pos);              );
-    } else {
-        GLSLC(1, ivec2 size = imageSize(output_img[0]);                   );
-        GLSLC(1, vec2 npos = vec2(pos)/vec2(size);                        );
-        GLSLC(1, vec4 res = texture(input_img[0], npos);                  );
-        GLSLC(1, imageStore(output_img[0], pos, res);                     );
-        for (int i = 1; i < planes; i++) {
-            GLSLC(0,                                                      );
-            GLSLF(1,  size = imageSize(output_img[%i]);                 ,i);
-            GLSLC(1,  if (!IS_WITHIN(pos, size))                          );
-            GLSLC(2,      return;                                         );
-            GLSLF(1,  distort_chroma(%i, size, pos);                    ,i);
-        }
-    }
-    GLSLC(0, }                                                            );
-
-    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
-
-    s->initialized = 1;
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-    if (spv)
-        spv->uninit(&spv);
-
-    return err;
-}
-
-static int chromaber_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
-{
-    int err;
-    AVFilterContext *ctx = link->dst;
-    ChromaticAberrationVulkanContext *s = ctx->priv;
-    AVFilterLink *outlink = ctx->outputs[0];
-
-    AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-    if (!out) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    if (!s->initialized)
-        RET(init_filter(ctx, in));
-
-    RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->shd, out, in,
-                                    s->sampler, &s->opts, sizeof(s->opts)));
-
-    err = av_frame_copy_props(out, in);
-    if (err < 0)
-        goto fail;
-
-    av_frame_free(&in);
-
-    return ff_filter_frame(outlink, out);
-
-fail:
-    av_frame_free(&in);
-    av_frame_free(&out);
-    return err;
-}
-
-static void chromaber_vulkan_uninit(AVFilterContext *avctx)
-{
-    ChromaticAberrationVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    FFVulkanFunctions *vk = &vkctx->vkfn;
-
-    ff_vk_exec_pool_free(vkctx, &s->e);
-    ff_vk_shader_free(vkctx, &s->shd);
-
-    if (s->sampler)
-        vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler,
-                           vkctx->hwctx->alloc);
-
-    ff_vk_uninit(&s->vkctx);
-
-    s->initialized = 0;
-}
-
-#define OFFSET(x) offsetof(ChromaticAberrationVulkanContext, x)
-#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
-static const AVOption chromaber_vulkan_options[] = {
-    { "dist_x", "Set horizontal distortion amount", OFFSET(opts.dist[0]), AV_OPT_TYPE_FLOAT, {.dbl = 0.0f}, -10.0f, 10.0f, .flags = FLAGS },
-    { "dist_y", "Set vertical distortion amount",   OFFSET(opts.dist[1]), AV_OPT_TYPE_FLOAT, {.dbl = 0.0f}, -10.0f, 10.0f, .flags = FLAGS },
-    { NULL },
-};
-
-AVFILTER_DEFINE_CLASS(chromaber_vulkan);
-
-static const AVFilterPad chromaber_vulkan_inputs[] = {
-    {
-        .name         = "default",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame = &chromaber_vulkan_filter_frame,
-        .config_props = &ff_vk_filter_config_input,
-    },
-};
-
-static const AVFilterPad chromaber_vulkan_outputs[] = {
-    {
-        .name = "default",
-        .type = AVMEDIA_TYPE_VIDEO,
-        .config_props = &ff_vk_filter_config_output,
-    },
-};
-
-const FFFilter ff_vf_chromaber_vulkan = {
-    .p.name         = "chromaber_vulkan",
-    .p.description  = NULL_IF_CONFIG_SMALL("Offset chroma of input video (chromatic aberration)"),
-    .p.priv_class   = &chromaber_vulkan_class,
-    .p.flags        = AVFILTER_FLAG_HWDEVICE,
-    .priv_size      = sizeof(ChromaticAberrationVulkanContext),
-    .init           = &ff_vk_filter_init,
-    .uninit         = &chromaber_vulkan_uninit,
-    FILTER_INPUTS(chromaber_vulkan_inputs),
-    FILTER_OUTPUTS(chromaber_vulkan_outputs),
-    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
-    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
-};
-- 
2.49.1


From 61ce4dae19345bbf9b54792af50ab1cb7bea8b22 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:52:16 +0000
Subject: [PATCH 010/118] Changing vulkan file directory

---
 libavfilter/vulkan/vf_chromaber_vulkan.c | 264 +++++++++++++++++++++++
 1 file changed, 264 insertions(+)
 create mode 100644 libavfilter/vulkan/vf_chromaber_vulkan.c

diff --git a/libavfilter/vulkan/vf_chromaber_vulkan.c b/libavfilter/vulkan/vf_chromaber_vulkan.c
new file mode 100644
index 0000000000..6066c9581c
--- /dev/null
+++ b/libavfilter/vulkan/vf_chromaber_vulkan.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) Lynne
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/random_seed.h"
+#include "libavutil/opt.h"
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+#include "vulkan_filter.h"
+
+#include "libavfilter/filters.h"
+#include "libavfilter/video.h"
+
+typedef struct ChromaticAberrationVulkanContext {
+    FFVulkanContext vkctx;
+
+    int initialized;
+    FFVkExecPool e;
+    AVVulkanDeviceQueueFamily *qf;
+    FFVulkanShader shd;
+    VkSampler sampler;
+
+    /* Push constants / options */
+    struct {
+        float dist[2];
+    } opts;
+} ChromaticAberrationVulkanContext;
+
+static const char distort_chroma_kernel[] = {
+    C(0, void distort_rgb(ivec2 size, ivec2 pos)                               )
+    C(0, {                                                                     )
+    C(1,     const vec2 p = ((vec2(pos)/vec2(size)) - 0.5f)*2.0f;              )
+    C(1,     const vec2 o = p * (dist - 1.0f);                                 )
+    C(0,                                                                       )
+    C(1,     vec4 res;                                                         )
+    C(1,     res.r = texture(input_img[0], ((p - o)/2.0f) + 0.5f).r;           )
+    C(1,     res.g = texture(input_img[0], ((p    )/2.0f) + 0.5f).g;           )
+    C(1,     res.b = texture(input_img[0], ((p + o)/2.0f) + 0.5f).b;           )
+    C(1,     res.a = texture(input_img[0], ((p    )/2.0f) + 0.5f).a;           )
+    C(1,     imageStore(output_img[0], pos, res);                              )
+    C(0, }                                                                     )
+    C(0,                                                                       )
+    C(0, void distort_chroma(int idx, ivec2 size, ivec2 pos)                   )
+    C(0, {                                                                     )
+    C(1,     vec2 p = ((vec2(pos)/vec2(size)) - 0.5f)*2.0f;                    )
+    C(1,     float d = sqrt(p.x*p.x + p.y*p.y);                                )
+    C(1,     p *= d / (d*dist);                                                )
+    C(1,     vec4 res = texture(input_img[idx], (p/2.0f) + 0.5f);              )
+    C(1,     imageStore(output_img[idx], pos, res);                            )
+    C(0, }                                                                     )
+};
+
+static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
+{
+    int err;
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    ChromaticAberrationVulkanContext *s = ctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
+    FFVulkanShader *shd = &s->shd;
+    FFVkSPIRVCompiler *spv;
+    FFVulkanDescriptorSetBinding *desc;
+
+    /* Normalize options */
+    s->opts.dist[0] = (s->opts.dist[0] / 100.0f) + 1.0f;
+    s->opts.dist[1] = (s->opts.dist[1] / 100.0f) + 1.0f;
+
+    spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
+    if (!s->qf) {
+        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
+        err = AVERROR(ENOTSUP);
+        goto fail;
+    }
+
+    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
+    RET(ff_vk_init_sampler(vkctx, &s->sampler, 0, VK_FILTER_LINEAR));
+    RET(ff_vk_shader_init(vkctx, &s->shd, "chromatic_abberation",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          NULL, 0,
+                          32, 32, 1,
+                          0));
+
+    GLSLC(0, layout(push_constant, std430) uniform pushConstants {        );
+    GLSLC(1,    vec2 dist;                                                );
+    GLSLC(0, };                                                           );
+    GLSLC(0,                                                              );
+
+    ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts),
+                                VK_SHADER_STAGE_COMPUTE_BIT);
+
+    desc = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name       = "input_img",
+            .type       = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+            .samplers   = DUP_SAMPLER(s->sampler),
+        },
+        {
+            .name       = "output_img",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "writeonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 2, 0, 0));
+
+    GLSLD(   distort_chroma_kernel                                        );
+    GLSLC(0, void main()                                                  );
+    GLSLC(0, {                                                            );
+    GLSLC(1,     ivec2 pos = ivec2(gl_GlobalInvocationID.xy);             );
+    if (planes == 1) {
+        GLSLC(1, distort_rgb(imageSize(output_img[0]), pos);              );
+    } else {
+        GLSLC(1, ivec2 size = imageSize(output_img[0]);                   );
+        GLSLC(1, vec2 npos = vec2(pos)/vec2(size);                        );
+        GLSLC(1, vec4 res = texture(input_img[0], npos);                  );
+        GLSLC(1, imageStore(output_img[0], pos, res);                     );
+        for (int i = 1; i < planes; i++) {
+            GLSLC(0,                                                      );
+            GLSLF(1,  size = imageSize(output_img[%i]);                 ,i);
+            GLSLC(1,  if (!IS_WITHIN(pos, size))                          );
+            GLSLC(2,      return;                                         );
+            GLSLF(1,  distort_chroma(%i, size, pos);                    ,i);
+        }
+    }
+    GLSLC(0, }                                                            );
+
+    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
+
+    s->initialized = 1;
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+    if (spv)
+        spv->uninit(&spv);
+
+    return err;
+}
+
+static int chromaber_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
+{
+    int err;
+    AVFilterContext *ctx = link->dst;
+    ChromaticAberrationVulkanContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+
+    AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!out) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    if (!s->initialized)
+        RET(init_filter(ctx, in));
+
+    RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->shd, out, in,
+                                    s->sampler, &s->opts, sizeof(s->opts)));
+
+    err = av_frame_copy_props(out, in);
+    if (err < 0)
+        goto fail;
+
+    av_frame_free(&in);
+
+    return ff_filter_frame(outlink, out);
+
+fail:
+    av_frame_free(&in);
+    av_frame_free(&out);
+    return err;
+}
+
+static void chromaber_vulkan_uninit(AVFilterContext *avctx)
+{
+    ChromaticAberrationVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    FFVulkanFunctions *vk = &vkctx->vkfn;
+
+    ff_vk_exec_pool_free(vkctx, &s->e);
+    ff_vk_shader_free(vkctx, &s->shd);
+
+    if (s->sampler)
+        vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler,
+                           vkctx->hwctx->alloc);
+
+    ff_vk_uninit(&s->vkctx);
+
+    s->initialized = 0;
+}
+
+#define OFFSET(x) offsetof(ChromaticAberrationVulkanContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
+static const AVOption chromaber_vulkan_options[] = {
+    { "dist_x", "Set horizontal distortion amount", OFFSET(opts.dist[0]), AV_OPT_TYPE_FLOAT, {.dbl = 0.0f}, -10.0f, 10.0f, .flags = FLAGS },
+    { "dist_y", "Set vertical distortion amount",   OFFSET(opts.dist[1]), AV_OPT_TYPE_FLOAT, {.dbl = 0.0f}, -10.0f, 10.0f, .flags = FLAGS },
+    { NULL },
+};
+
+AVFILTER_DEFINE_CLASS(chromaber_vulkan);
+
+static const AVFilterPad chromaber_vulkan_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = &chromaber_vulkan_filter_frame,
+        .config_props = &ff_vk_filter_config_input,
+    },
+};
+
+static const AVFilterPad chromaber_vulkan_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_VIDEO,
+        .config_props = &ff_vk_filter_config_output,
+    },
+};
+
+const FFFilter ff_vf_chromaber_vulkan = {
+    .p.name         = "chromaber_vulkan",
+    .p.description  = NULL_IF_CONFIG_SMALL("Offset chroma of input video (chromatic aberration)"),
+    .p.priv_class   = &chromaber_vulkan_class,
+    .p.flags        = AVFILTER_FLAG_HWDEVICE,
+    .priv_size      = sizeof(ChromaticAberrationVulkanContext),
+    .init           = &ff_vk_filter_init,
+    .uninit         = &chromaber_vulkan_uninit,
+    FILTER_INPUTS(chromaber_vulkan_inputs),
+    FILTER_OUTPUTS(chromaber_vulkan_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};
-- 
2.49.1


From 2077a171e097c2343f36086b9930f18d93db5ce2 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:53:02 +0000
Subject: [PATCH 011/118] Changing vulkan file directory

---
 libavfilter/vf_flip_vulkan.c | 297 -----------------------------------
 1 file changed, 297 deletions(-)
 delete mode 100644 libavfilter/vf_flip_vulkan.c

diff --git a/libavfilter/vf_flip_vulkan.c b/libavfilter/vf_flip_vulkan.c
deleted file mode 100644
index 3e2aed0fda..0000000000
--- a/libavfilter/vf_flip_vulkan.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * copyright (c) 2021 Wu Jianhua <jianhua.wu@intel.com>
- * Copyright (c) Lynne
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/random_seed.h"
-#include "libavutil/opt.h"
-#include "libavutil/vulkan_spirv.h"
-#include "vulkan_filter.h"
-
-#include "filters.h"
-#include "video.h"
-
-enum FlipType {
-    FLIP_VERTICAL,
-    FLIP_HORIZONTAL,
-    FLIP_BOTH
-};
-
-typedef struct FlipVulkanContext {
-    FFVulkanContext vkctx;
-
-    int initialized;
-    FFVkExecPool e;
-    AVVulkanDeviceQueueFamily *qf;
-    FFVulkanShader shd;
-} FlipVulkanContext;
-
-static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in, enum FlipType type)
-{
-    int err = 0;
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    FlipVulkanContext *s = ctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
-    FFVulkanShader *shd = &s->shd;
-    FFVkSPIRVCompiler *spv;
-    FFVulkanDescriptorSetBinding *desc;
-
-    spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
-    if (!s->qf) {
-        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
-        err = AVERROR(ENOTSUP);
-        goto fail;
-    }
-
-    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
-    RET(ff_vk_shader_init(vkctx, &s->shd, "flip",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          NULL, 0,
-                          32, 32, 1,
-                          0));
-
-    desc = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name       = "input_image",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "readonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-        {
-            .name       = "output_image",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "writeonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 2, 0, 0));
-
-    GLSLC(0, void main()                                                                    );
-    GLSLC(0, {                                                                              );
-    GLSLC(1,     ivec2 size;                                                                );
-    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);                         );
-    for (int i = 0; i < planes; i++) {
-        GLSLC(0,                                                                            );
-        GLSLF(1, size = imageSize(output_image[%i]);                                      ,i);
-        GLSLC(1, if (IS_WITHIN(pos, size)) {                                                );
-        switch (type)
-        {
-        case FLIP_HORIZONTAL:
-            GLSLF(2, vec4 res = imageLoad(input_image[%i], ivec2(size.x - pos.x, pos.y)); ,i);
-            break;
-        case FLIP_VERTICAL:
-            GLSLF(2, vec4 res = imageLoad(input_image[%i], ivec2(pos.x, size.y - pos.y)); ,i);
-            break;
-        case FLIP_BOTH:
-            GLSLF(2, vec4 res = imageLoad(input_image[%i], ivec2(size.xy - pos.xy));,      i);
-            break;
-        default:
-            GLSLF(2, vec4 res = imageLoad(input_image[%i], pos);                          ,i);
-            break;
-        }
-        GLSLF(2,     imageStore(output_image[%i], pos, res);                              ,i);
-        GLSLC(1, }                                                                          );
-    }
-    GLSLC(0, }                                                                              );
-
-    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
-
-    s->initialized = 1;
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-    if (spv)
-        spv->uninit(&spv);
-
-    return err;
-}
-
-static av_cold void flip_vulkan_uninit(AVFilterContext *avctx)
-{
-    FlipVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-
-    ff_vk_exec_pool_free(vkctx, &s->e);
-    ff_vk_shader_free(vkctx, &s->shd);
-
-    ff_vk_uninit(&s->vkctx);
-
-    s->initialized = 0;
-}
-
-static int filter_frame(AVFilterLink *link, AVFrame *in, enum FlipType type)
-{
-    int err;
-    AVFrame *out = NULL;
-    AVFilterContext *ctx = link->dst;
-    FlipVulkanContext *s = ctx->priv;
-    AVFilterLink *outlink = ctx->outputs[0];
-
-    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-    if (!out) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    if (!s->initialized)
-        RET(init_filter(ctx, in, type));
-
-    RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->shd, out, in,
-                                    VK_NULL_HANDLE, NULL, 0));
-
-    RET(av_frame_copy_props(out, in));
-
-    av_frame_free(&in);
-
-    return ff_filter_frame(outlink, out);
-
-fail:
-    av_frame_free(&in);
-    av_frame_free(&out);
-    return err;
-}
-
-static int hflip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
-{
-    return filter_frame(link, in, FLIP_HORIZONTAL);
-}
-
-static int vflip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
-{
-    return filter_frame(link, in, FLIP_VERTICAL);
-}
-
-static int flip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
-{
-    return filter_frame(link, in, FLIP_BOTH);
-}
-
-static const AVFilterPad flip_vulkan_outputs[] = {
-    {
-        .name         = "default",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .config_props = &ff_vk_filter_config_output,
-    }
-};
-
-static const AVOption hflip_vulkan_options[] = {
-    { NULL },
-};
-
-AVFILTER_DEFINE_CLASS(hflip_vulkan);
-
-static const AVFilterPad hflip_vulkan_inputs[] = {
-    {
-        .name         = "default",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame = &hflip_vulkan_filter_frame,
-        .config_props = &ff_vk_filter_config_input,
-    }
-};
-
-const FFFilter ff_vf_hflip_vulkan = {
-    .p.name         = "hflip_vulkan",
-    .p.description  = NULL_IF_CONFIG_SMALL("Horizontally flip the input video in Vulkan"),
-    .p.priv_class   = &hflip_vulkan_class,
-    .priv_size      = sizeof(FlipVulkanContext),
-    .init           = &ff_vk_filter_init,
-    .uninit         = &flip_vulkan_uninit,
-    FILTER_INPUTS(hflip_vulkan_inputs),
-    FILTER_OUTPUTS(flip_vulkan_outputs),
-    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
-    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
-};
-
-static const AVOption vflip_vulkan_options[] = {
-    { NULL },
-};
-
-AVFILTER_DEFINE_CLASS(vflip_vulkan);
-
-static const AVFilterPad vflip_vulkan_inputs[] = {
-    {
-        .name         = "default",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame = &vflip_vulkan_filter_frame,
-        .config_props = &ff_vk_filter_config_input,
-    }
-};
-
-const FFFilter ff_vf_vflip_vulkan = {
-    .p.name         = "vflip_vulkan",
-    .p.description  = NULL_IF_CONFIG_SMALL("Vertically flip the input video in Vulkan"),
-    .p.priv_class   = &vflip_vulkan_class,
-    .priv_size      = sizeof(FlipVulkanContext),
-    .init           = &ff_vk_filter_init,
-    .uninit         = &flip_vulkan_uninit,
-    FILTER_INPUTS(vflip_vulkan_inputs),
-    FILTER_OUTPUTS(flip_vulkan_outputs),
-    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
-    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
-};
-
-static const AVOption flip_vulkan_options[] = {
-    { NULL },
-};
-
-AVFILTER_DEFINE_CLASS(flip_vulkan);
-
-static const AVFilterPad flip_vulkan_inputs[] = {
-    {
-        .name         = "default",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame = &flip_vulkan_filter_frame,
-        .config_props = &ff_vk_filter_config_input,
-    }
-};
-
-const FFFilter ff_vf_flip_vulkan = {
-    .p.name         = "flip_vulkan",
-    .p.description  = NULL_IF_CONFIG_SMALL("Flip both horizontally and vertically"),
-    .p.priv_class   = &flip_vulkan_class,
-    .p.flags        = AVFILTER_FLAG_HWDEVICE,
-    .priv_size      = sizeof(FlipVulkanContext),
-    .init           = &ff_vk_filter_init,
-    .uninit         = &flip_vulkan_uninit,
-    FILTER_INPUTS(flip_vulkan_inputs),
-    FILTER_OUTPUTS(flip_vulkan_outputs),
-    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
-    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
-};
-- 
2.49.1


From 1c29ae6603f0fed130e5ea6d1316baafbe1db735 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:53:26 +0000
Subject: [PATCH 012/118] Changing vulkan file directory

---
 libavfilter/vulkan/vf_flip_vulkan.c | 297 ++++++++++++++++++++++++++++
 1 file changed, 297 insertions(+)
 create mode 100644 libavfilter/vulkan/vf_flip_vulkan.c

diff --git a/libavfilter/vulkan/vf_flip_vulkan.c b/libavfilter/vulkan/vf_flip_vulkan.c
new file mode 100644
index 0000000000..b00a7e5510
--- /dev/null
+++ b/libavfilter/vulkan/vf_flip_vulkan.c
@@ -0,0 +1,297 @@
+/*
+ * copyright (c) 2021 Wu Jianhua <jianhua.wu@intel.com>
+ * Copyright (c) Lynne
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/random_seed.h"
+#include "libavutil/opt.h"
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+#include "vulkan_filter.h"
+
+#include "libavfilter/filters.h"
+#include "libavfilter/video.h"
+
+enum FlipType {
+    FLIP_VERTICAL,
+    FLIP_HORIZONTAL,
+    FLIP_BOTH
+};
+
+typedef struct FlipVulkanContext {
+    FFVulkanContext vkctx;
+
+    int initialized;
+    FFVkExecPool e;
+    AVVulkanDeviceQueueFamily *qf;
+    FFVulkanShader shd;
+} FlipVulkanContext;
+
+static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in, enum FlipType type)
+{
+    int err = 0;
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    FlipVulkanContext *s = ctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
+    FFVulkanShader *shd = &s->shd;
+    FFVkSPIRVCompiler *spv;
+    FFVulkanDescriptorSetBinding *desc;
+
+    spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
+    if (!s->qf) {
+        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
+        err = AVERROR(ENOTSUP);
+        goto fail;
+    }
+
+    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
+    RET(ff_vk_shader_init(vkctx, &s->shd, "flip",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          NULL, 0,
+                          32, 32, 1,
+                          0));
+
+    desc = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name       = "input_image",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "readonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+        {
+            .name       = "output_image",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "writeonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 2, 0, 0));
+
+    GLSLC(0, void main()                                                                    );
+    GLSLC(0, {                                                                              );
+    GLSLC(1,     ivec2 size;                                                                );
+    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);                         );
+    for (int i = 0; i < planes; i++) {
+        GLSLC(0,                                                                            );
+        GLSLF(1, size = imageSize(output_image[%i]);                                      ,i);
+        GLSLC(1, if (IS_WITHIN(pos, size)) {                                                );
+        switch (type)
+        {
+        case FLIP_HORIZONTAL:
+            GLSLF(2, vec4 res = imageLoad(input_image[%i], ivec2(size.x - pos.x, pos.y)); ,i);
+            break;
+        case FLIP_VERTICAL:
+            GLSLF(2, vec4 res = imageLoad(input_image[%i], ivec2(pos.x, size.y - pos.y)); ,i);
+            break;
+        case FLIP_BOTH:
+            GLSLF(2, vec4 res = imageLoad(input_image[%i], ivec2(size.xy - pos.xy));,      i);
+            break;
+        default:
+            GLSLF(2, vec4 res = imageLoad(input_image[%i], pos);                          ,i);
+            break;
+        }
+        GLSLF(2,     imageStore(output_image[%i], pos, res);                              ,i);
+        GLSLC(1, }                                                                          );
+    }
+    GLSLC(0, }                                                                              );
+
+    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
+
+    s->initialized = 1;
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+    if (spv)
+        spv->uninit(&spv);
+
+    return err;
+}
+
+static av_cold void flip_vulkan_uninit(AVFilterContext *avctx)
+{
+    FlipVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+
+    ff_vk_exec_pool_free(vkctx, &s->e);
+    ff_vk_shader_free(vkctx, &s->shd);
+
+    ff_vk_uninit(&s->vkctx);
+
+    s->initialized = 0;
+}
+
+static int filter_frame(AVFilterLink *link, AVFrame *in, enum FlipType type)
+{
+    int err;
+    AVFrame *out = NULL;
+    AVFilterContext *ctx = link->dst;
+    FlipVulkanContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+
+    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!out) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    if (!s->initialized)
+        RET(init_filter(ctx, in, type));
+
+    RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->shd, out, in,
+                                    VK_NULL_HANDLE, NULL, 0));
+
+    RET(av_frame_copy_props(out, in));
+
+    av_frame_free(&in);
+
+    return ff_filter_frame(outlink, out);
+
+fail:
+    av_frame_free(&in);
+    av_frame_free(&out);
+    return err;
+}
+
+static int hflip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
+{
+    return filter_frame(link, in, FLIP_HORIZONTAL);
+}
+
+static int vflip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
+{
+    return filter_frame(link, in, FLIP_VERTICAL);
+}
+
+static int flip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
+{
+    return filter_frame(link, in, FLIP_BOTH);
+}
+
+static const AVFilterPad flip_vulkan_outputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = &ff_vk_filter_config_output,
+    }
+};
+
+static const AVOption hflip_vulkan_options[] = {
+    { NULL },
+};
+
+AVFILTER_DEFINE_CLASS(hflip_vulkan);
+
+static const AVFilterPad hflip_vulkan_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = &hflip_vulkan_filter_frame,
+        .config_props = &ff_vk_filter_config_input,
+    }
+};
+
+const FFFilter ff_vf_hflip_vulkan = {
+    .p.name         = "hflip_vulkan",
+    .p.description  = NULL_IF_CONFIG_SMALL("Horizontally flip the input video in Vulkan"),
+    .p.priv_class   = &hflip_vulkan_class,
+    .priv_size      = sizeof(FlipVulkanContext),
+    .init           = &ff_vk_filter_init,
+    .uninit         = &flip_vulkan_uninit,
+    FILTER_INPUTS(hflip_vulkan_inputs),
+    FILTER_OUTPUTS(flip_vulkan_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};
+
+static const AVOption vflip_vulkan_options[] = {
+    { NULL },
+};
+
+AVFILTER_DEFINE_CLASS(vflip_vulkan);
+
+static const AVFilterPad vflip_vulkan_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = &vflip_vulkan_filter_frame,
+        .config_props = &ff_vk_filter_config_input,
+    }
+};
+
+const FFFilter ff_vf_vflip_vulkan = {
+    .p.name         = "vflip_vulkan",
+    .p.description  = NULL_IF_CONFIG_SMALL("Vertically flip the input video in Vulkan"),
+    .p.priv_class   = &vflip_vulkan_class,
+    .priv_size      = sizeof(FlipVulkanContext),
+    .init           = &ff_vk_filter_init,
+    .uninit         = &flip_vulkan_uninit,
+    FILTER_INPUTS(vflip_vulkan_inputs),
+    FILTER_OUTPUTS(flip_vulkan_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};
+
+static const AVOption flip_vulkan_options[] = {
+    { NULL },
+};
+
+AVFILTER_DEFINE_CLASS(flip_vulkan);
+
+static const AVFilterPad flip_vulkan_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = &flip_vulkan_filter_frame,
+        .config_props = &ff_vk_filter_config_input,
+    }
+};
+
+const FFFilter ff_vf_flip_vulkan = {
+    .p.name         = "flip_vulkan",
+    .p.description  = NULL_IF_CONFIG_SMALL("Flip both horizontally and vertically"),
+    .p.priv_class   = &flip_vulkan_class,
+    .p.flags        = AVFILTER_FLAG_HWDEVICE,
+    .priv_size      = sizeof(FlipVulkanContext),
+    .init           = &ff_vk_filter_init,
+    .uninit         = &flip_vulkan_uninit,
+    FILTER_INPUTS(flip_vulkan_inputs),
+    FILTER_OUTPUTS(flip_vulkan_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};
-- 
2.49.1


From 02ccafbadab8361156f6d08bca4ab3aeca3a2a1e Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:53:56 +0000
Subject: [PATCH 013/118] Changing vulkan file directory

---
 libavfilter/vf_gblur_vulkan.c | 379 ----------------------------------
 1 file changed, 379 deletions(-)
 delete mode 100644 libavfilter/vf_gblur_vulkan.c

diff --git a/libavfilter/vf_gblur_vulkan.c b/libavfilter/vf_gblur_vulkan.c
deleted file mode 100644
index 1b447e2754..0000000000
--- a/libavfilter/vf_gblur_vulkan.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * copyright (c) 2021-2022 Wu Jianhua <jianhua.wu@intel.com>
- * Copyright (c) Lynne
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/mem.h"
-#include "libavutil/random_seed.h"
-#include "libavutil/opt.h"
-#include "libavutil/vulkan_spirv.h"
-#include "vulkan_filter.h"
-
-#include "filters.h"
-#include "video.h"
-
-#define CGS 32
-#define GBLUR_MAX_KERNEL_SIZE 127
-
-typedef struct GBlurVulkanContext {
-    FFVulkanContext vkctx;
-
-    int initialized;
-    FFVkExecPool e;
-    AVVulkanDeviceQueueFamily *qf;
-    VkSampler sampler;
-    FFVulkanShader shd_hor;
-    FFVkBuffer params_hor;
-    FFVulkanShader shd_ver;
-    FFVkBuffer params_ver;
-
-    int size;
-    int sizeV;
-    int planes;
-    float sigma;
-    float sigmaV;
-} GBlurVulkanContext;
-
-static const char gblur_func[] = {
-    C(0, void gblur(const ivec2 pos, const int index)                             )
-    C(0, {                                                                        )
-    C(1,     vec4 sum = imageLoad(input_images[index], pos) * kernel[0];          )
-    C(0,                                                                          )
-    C(1,     for(int i = 1; i < kernel.length(); i++) {                           )
-    C(2,         sum += imageLoad(input_images[index], pos + OFFSET) * kernel[i]; )
-    C(2,         sum += imageLoad(input_images[index], pos - OFFSET) * kernel[i]; )
-    C(1,     }                                                                    )
-    C(0,                                                                          )
-    C(1,     imageStore(output_images[index], pos, sum);                          )
-    C(0, }                                                                        )
-};
-
-static inline float gaussian(float sigma, float x)
-{
-    return 1.0 / (sqrt(2.0 * M_PI) * sigma) *
-           exp(-(x * x) / (2.0 * sigma * sigma));
-}
-
-static inline float gaussian_simpson_integration(float sigma, float a, float b)
-{
-    return (b - a) * (1.0 / 6.0) * ((gaussian(sigma, a) +
-           4.0 * gaussian(sigma, (a + b) * 0.5) + gaussian(sigma, b)));
-}
-
-static void init_gaussian_kernel(float *kernel, float sigma, float kernel_size)
-{
-    int x;
-    float sum;
-
-    sum = 0;
-    for (x = 0; x < kernel_size; x++) {
-        kernel[x] = gaussian_simpson_integration(sigma, x - 0.5f, x + 0.5f);
-        if (!x)
-            sum += kernel[x];
-        else
-            sum += kernel[x] * 2.0;
-    }
-    /* Normalized */
-    sum = 1.0 / sum;
-    for (x = 0; x < kernel_size; x++) {
-        kernel[x] *= sum;
-    }
-}
-
-static inline void init_kernel_size(void *log_ctx, int *out_size)
-{
-    int size = *out_size;
-
-    if (!(size & 1)) {
-        av_log(log_ctx, AV_LOG_WARNING, "The kernel size should be odd\n");
-        size++;
-    }
-
-    *out_size = (size >> 1) + 1;
-}
-
-static av_cold void init_gaussian_params(AVFilterContext *ctx)
-{
-    GBlurVulkanContext *s = ctx->priv;
-    if (s->sigmaV <= 0)
-        s->sigmaV = s->sigma;
-
-    init_kernel_size(ctx, &s->size);
-
-    if (s->sizeV <= 0)
-        s->sizeV = s->size;
-    else
-        init_kernel_size(ctx, &s->sizeV);
-}
-
-static int init_gblur_pipeline(GBlurVulkanContext *s,
-                               FFVulkanShader *shd, FFVkBuffer *params_buf,
-                               int ksize, float sigma, FFVkSPIRVCompiler *spv)
-{
-    int err = 0;
-    uint8_t *kernel_mapped;
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-
-    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
-
-    FFVulkanDescriptorSetBinding buf_desc = {
-        .name        = "data",
-        .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-        .mem_quali   = "readonly",
-        .mem_layout  = "std430",
-        .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-        .buf_content = "float kernel",
-        .buf_elems   = ksize,
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(&s->vkctx, shd, &buf_desc, 1, 1, 0));
-
-    GLSLD(   gblur_func                                               );
-    GLSLC(0, void main()                                              );
-    GLSLC(0, {                                                        );
-    GLSLC(1,     ivec2 size;                                          );
-    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);   );
-    for (int i = 0; i < planes; i++) {
-        GLSLC(0,                                                      );
-        GLSLF(1,  size = imageSize(output_images[%i]);              ,i);
-        GLSLC(1,  if (!IS_WITHIN(pos, size))                          );
-        GLSLC(2,      return;                                         );
-        if (s->planes & (1 << i)) {
-            GLSLF(1,      gblur(pos, %i);                           ,i);
-        } else {
-            GLSLF(1, vec4 res = imageLoad(input_images[%i], pos);   ,i);
-            GLSLF(1, imageStore(output_images[%i], pos, res);       ,i);
-        }
-    }
-    GLSLC(0, }                                                        );
-
-    RET(spv->compile_shader(&s->vkctx, spv, shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(&s->vkctx, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(&s->vkctx, &s->e, shd));
-
-    RET(ff_vk_create_buf(&s->vkctx, params_buf, sizeof(float) * ksize, NULL, NULL,
-                         VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
-                         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
-    RET(ff_vk_map_buffer(&s->vkctx, params_buf, &kernel_mapped, 0));
-
-    init_gaussian_kernel((float *)kernel_mapped, sigma, ksize);
-
-    RET(ff_vk_unmap_buffer(&s->vkctx, params_buf, 1));
-    RET(ff_vk_shader_update_desc_buffer(&s->vkctx, &s->e.contexts[0], shd, 1, 0, 0,
-                                        params_buf, 0, params_buf->size,
-                                        VK_FORMAT_UNDEFINED));
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-    return err;
-}
-
-static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
-{
-    int err = 0;
-    GBlurVulkanContext *s = ctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
-
-    FFVulkanShader *shd;
-    FFVkSPIRVCompiler *spv;
-    FFVulkanDescriptorSetBinding *desc;
-
-    spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
-    if (!s->qf) {
-        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
-        err = AVERROR(ENOTSUP);
-        goto fail;
-    }
-
-    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
-
-    desc = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name       = "input_images",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "readonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-        {
-            .name       = "output_images",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "writeonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-    };
-
-    init_gaussian_params(ctx);
-
-    {
-        shd = &s->shd_hor;
-        RET(ff_vk_shader_init(vkctx, shd, "gblur_hor",
-                              VK_SHADER_STAGE_COMPUTE_BIT,
-                              NULL, 0,
-                              32, 1, 1,
-                              0));
-
-        RET(ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 2, 0, 0));
-
-        GLSLC(0, #define OFFSET (ivec2(i, 0.0)));
-        RET(init_gblur_pipeline(s, shd, &s->params_hor, s->size, s->sigma, spv));
-    }
-
-    {
-        shd = &s->shd_ver;
-        RET(ff_vk_shader_init(vkctx, shd, "gblur_hor",
-                              VK_SHADER_STAGE_COMPUTE_BIT,
-                              NULL, 0,
-                              1, 32, 1,
-                              0));
-
-        RET(ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 2, 0, 0));
-
-        GLSLC(0, #define OFFSET (ivec2(0.0, i)));
-        RET(init_gblur_pipeline(s, shd, &s->params_ver, s->sizeV, s->sigmaV, spv));
-    }
-
-    s->initialized = 1;
-
-fail:
-    if (spv)
-        spv->uninit(&spv);
-
-    return err;
-}
-
-static av_cold void gblur_vulkan_uninit(AVFilterContext *avctx)
-{
-    GBlurVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-
-    ff_vk_exec_pool_free(vkctx, &s->e);
-    ff_vk_shader_free(vkctx, &s->shd_hor);
-    ff_vk_shader_free(vkctx, &s->shd_ver);
-    ff_vk_free_buf(vkctx, &s->params_hor);
-    ff_vk_free_buf(vkctx, &s->params_ver);
-
-    ff_vk_uninit(&s->vkctx);
-
-    s->initialized = 0;
-}
-
-static int gblur_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
-{
-    int err;
-    AVFrame *tmp = NULL, *out = NULL;
-    AVFilterContext *ctx = link->dst;
-    GBlurVulkanContext *s = ctx->priv;
-    AVFilterLink *outlink = ctx->outputs[0];
-
-    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-    if (!out) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    tmp = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-    if (!tmp) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    if (!s->initialized)
-        RET(init_filter(ctx, in));
-
-    RET(ff_vk_filter_process_2pass(&s->vkctx, &s->e,
-                                   (FFVulkanShader *[2]){ &s->shd_hor, &s->shd_ver },
-                                   out, tmp, in, VK_NULL_HANDLE, NULL, 0));
-
-    err = av_frame_copy_props(out, in);
-    if (err < 0)
-        goto fail;
-
-    av_frame_free(&in);
-    av_frame_free(&tmp);
-
-    return ff_filter_frame(outlink, out);
-
-fail:
-    av_frame_free(&in);
-    av_frame_free(&tmp);
-    av_frame_free(&out);
-    return err;
-}
-
-#define OFFSET(x) offsetof(GBlurVulkanContext, x)
-#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
-static const AVOption gblur_vulkan_options[] = {
-    { "sigma",  "Set sigma",                OFFSET(sigma),  AV_OPT_TYPE_FLOAT, { .dbl = 0.5 }, 0.01, 1024.0,                FLAGS },
-    { "sigmaV", "Set vertical sigma",       OFFSET(sigmaV), AV_OPT_TYPE_FLOAT, { .dbl = 0   }, 0.0,  1024.0,                FLAGS },
-    { "planes", "Set planes to filter",     OFFSET(planes), AV_OPT_TYPE_INT,   { .i64 = 0xF }, 0,    0xF,                   FLAGS },
-    { "size",   "Set kernel size",          OFFSET(size),   AV_OPT_TYPE_INT,   { .i64 = 19  }, 1,    GBLUR_MAX_KERNEL_SIZE, FLAGS },
-    { "sizeV",  "Set vertical kernel size", OFFSET(sizeV),  AV_OPT_TYPE_INT,   { .i64 = 0   }, 0,    GBLUR_MAX_KERNEL_SIZE, FLAGS },
-    { NULL },
-};
-
-AVFILTER_DEFINE_CLASS(gblur_vulkan);
-
-static const AVFilterPad gblur_vulkan_inputs[] = {
-    {
-        .name         = "default",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame = &gblur_vulkan_filter_frame,
-        .config_props = &ff_vk_filter_config_input,
-    }
-};
-
-static const AVFilterPad gblur_vulkan_outputs[] = {
-    {
-        .name         = "default",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .config_props = &ff_vk_filter_config_output,
-    }
-};
-
-const FFFilter ff_vf_gblur_vulkan = {
-    .p.name         = "gblur_vulkan",
-    .p.description  = NULL_IF_CONFIG_SMALL("Gaussian Blur in Vulkan"),
-    .p.priv_class   = &gblur_vulkan_class,
-    .p.flags        = AVFILTER_FLAG_HWDEVICE,
-    .priv_size      = sizeof(GBlurVulkanContext),
-    .init           = &ff_vk_filter_init,
-    .uninit         = &gblur_vulkan_uninit,
-    FILTER_INPUTS(gblur_vulkan_inputs),
-    FILTER_OUTPUTS(gblur_vulkan_outputs),
-    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
-    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
-};
-- 
2.49.1


From 9d0af8705418ef8b2cfcce6f2134398d4b0d0f13 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:54:35 +0000
Subject: [PATCH 014/118] Changing vulkan file directory

---
 libavfilter/vulkan/vf_gblur_vulkan.c | 379 +++++++++++++++++++++++++++
 1 file changed, 379 insertions(+)
 create mode 100644 libavfilter/vulkan/vf_gblur_vulkan.c

diff --git a/libavfilter/vulkan/vf_gblur_vulkan.c b/libavfilter/vulkan/vf_gblur_vulkan.c
new file mode 100644
index 0000000000..168ef01d56
--- /dev/null
+++ b/libavfilter/vulkan/vf_gblur_vulkan.c
@@ -0,0 +1,379 @@
+/*
+ * copyright (c) 2021-2022 Wu Jianhua <jianhua.wu@intel.com>
+ * Copyright (c) Lynne
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/mem.h"
+#include "libavutil/random_seed.h"
+#include "libavutil/opt.h"
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+#include "vulkan_filter.h"
+
+#include "libavfilter/filters.h"
+#include "libavfilter/video.h"
+
+#define CGS 32
+#define GBLUR_MAX_KERNEL_SIZE 127
+
+typedef struct GBlurVulkanContext {
+    FFVulkanContext vkctx;
+
+    int initialized;
+    FFVkExecPool e;
+    AVVulkanDeviceQueueFamily *qf;
+    VkSampler sampler;
+    FFVulkanShader shd_hor;
+    FFVkBuffer params_hor;
+    FFVulkanShader shd_ver;
+    FFVkBuffer params_ver;
+
+    int size;
+    int sizeV;
+    int planes;
+    float sigma;
+    float sigmaV;
+} GBlurVulkanContext;
+
+static const char gblur_func[] = {
+    C(0, void gblur(const ivec2 pos, const int index)                             )
+    C(0, {                                                                        )
+    C(1,     vec4 sum = imageLoad(input_images[index], pos) * kernel[0];          )
+    C(0,                                                                          )
+    C(1,     for(int i = 1; i < kernel.length(); i++) {                           )
+    C(2,         sum += imageLoad(input_images[index], pos + OFFSET) * kernel[i]; )
+    C(2,         sum += imageLoad(input_images[index], pos - OFFSET) * kernel[i]; )
+    C(1,     }                                                                    )
+    C(0,                                                                          )
+    C(1,     imageStore(output_images[index], pos, sum);                          )
+    C(0, }                                                                        )
+};
+
+static inline float gaussian(float sigma, float x)
+{
+    return 1.0 / (sqrt(2.0 * M_PI) * sigma) *
+           exp(-(x * x) / (2.0 * sigma * sigma));
+}
+
+static inline float gaussian_simpson_integration(float sigma, float a, float b)
+{
+    return (b - a) * (1.0 / 6.0) * ((gaussian(sigma, a) +
+           4.0 * gaussian(sigma, (a + b) * 0.5) + gaussian(sigma, b)));
+}
+
+static void init_gaussian_kernel(float *kernel, float sigma, float kernel_size)
+{
+    int x;
+    float sum;
+
+    sum = 0;
+    for (x = 0; x < kernel_size; x++) {
+        kernel[x] = gaussian_simpson_integration(sigma, x - 0.5f, x + 0.5f);
+        if (!x)
+            sum += kernel[x];
+        else
+            sum += kernel[x] * 2.0;
+    }
+    /* Normalized */
+    sum = 1.0 / sum;
+    for (x = 0; x < kernel_size; x++) {
+        kernel[x] *= sum;
+    }
+}
+
+static inline void init_kernel_size(void *log_ctx, int *out_size)
+{
+    int size = *out_size;
+
+    if (!(size & 1)) {
+        av_log(log_ctx, AV_LOG_WARNING, "The kernel size should be odd\n");
+        size++;
+    }
+
+    *out_size = (size >> 1) + 1;
+}
+
+static av_cold void init_gaussian_params(AVFilterContext *ctx)
+{
+    GBlurVulkanContext *s = ctx->priv;
+    if (s->sigmaV <= 0)
+        s->sigmaV = s->sigma;
+
+    init_kernel_size(ctx, &s->size);
+
+    if (s->sizeV <= 0)
+        s->sizeV = s->size;
+    else
+        init_kernel_size(ctx, &s->sizeV);
+}
+
+static int init_gblur_pipeline(GBlurVulkanContext *s,
+                               FFVulkanShader *shd, FFVkBuffer *params_buf,
+                               int ksize, float sigma, FFVkSPIRVCompiler *spv)
+{
+    int err = 0;
+    uint8_t *kernel_mapped;
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+
+    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
+
+    FFVulkanDescriptorSetBinding buf_desc = {
+        .name        = "data",
+        .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+        .mem_quali   = "readonly",
+        .mem_layout  = "std430",
+        .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+        .buf_content = "float kernel",
+        .buf_elems   = ksize,
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(&s->vkctx, shd, &buf_desc, 1, 1, 0));
+
+    GLSLD(   gblur_func                                               );
+    GLSLC(0, void main()                                              );
+    GLSLC(0, {                                                        );
+    GLSLC(1,     ivec2 size;                                          );
+    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);   );
+    for (int i = 0; i < planes; i++) {
+        GLSLC(0,                                                      );
+        GLSLF(1,  size = imageSize(output_images[%i]);              ,i);
+        GLSLC(1,  if (!IS_WITHIN(pos, size))                          );
+        GLSLC(2,      return;                                         );
+        if (s->planes & (1 << i)) {
+            GLSLF(1,      gblur(pos, %i);                           ,i);
+        } else {
+            GLSLF(1, vec4 res = imageLoad(input_images[%i], pos);   ,i);
+            GLSLF(1, imageStore(output_images[%i], pos, res);       ,i);
+        }
+    }
+    GLSLC(0, }                                                        );
+
+    RET(spv->compile_shader(&s->vkctx, spv, shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(&s->vkctx, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(&s->vkctx, &s->e, shd));
+
+    RET(ff_vk_create_buf(&s->vkctx, params_buf, sizeof(float) * ksize, NULL, NULL,
+                         VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+                         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
+    RET(ff_vk_map_buffer(&s->vkctx, params_buf, &kernel_mapped, 0));
+
+    init_gaussian_kernel((float *)kernel_mapped, sigma, ksize);
+
+    RET(ff_vk_unmap_buffer(&s->vkctx, params_buf, 1));
+    RET(ff_vk_shader_update_desc_buffer(&s->vkctx, &s->e.contexts[0], shd, 1, 0, 0,
+                                        params_buf, 0, params_buf->size,
+                                        VK_FORMAT_UNDEFINED));
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+    return err;
+}
+
+static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
+{
+    int err = 0;
+    GBlurVulkanContext *s = ctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
+
+    FFVulkanShader *shd;
+    FFVkSPIRVCompiler *spv;
+    FFVulkanDescriptorSetBinding *desc;
+
+    spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
+    if (!s->qf) {
+        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
+        err = AVERROR(ENOTSUP);
+        goto fail;
+    }
+
+    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
+
+    desc = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name       = "input_images",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "readonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+        {
+            .name       = "output_images",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "writeonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+    };
+
+    init_gaussian_params(ctx);
+
+    {
+        shd = &s->shd_hor;
+        RET(ff_vk_shader_init(vkctx, shd, "gblur_hor",
+                              VK_SHADER_STAGE_COMPUTE_BIT,
+                              NULL, 0,
+                              32, 1, 1,
+                              0));
+
+        RET(ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 2, 0, 0));
+
+        GLSLC(0, #define OFFSET (ivec2(i, 0.0)));
+        RET(init_gblur_pipeline(s, shd, &s->params_hor, s->size, s->sigma, spv));
+    }
+
+    {
+        shd = &s->shd_ver;
+        RET(ff_vk_shader_init(vkctx, shd, "gblur_hor",
+                              VK_SHADER_STAGE_COMPUTE_BIT,
+                              NULL, 0,
+                              1, 32, 1,
+                              0));
+
+        RET(ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 2, 0, 0));
+
+        GLSLC(0, #define OFFSET (ivec2(0.0, i)));
+        RET(init_gblur_pipeline(s, shd, &s->params_ver, s->sizeV, s->sigmaV, spv));
+    }
+
+    s->initialized = 1;
+
+fail:
+    if (spv)
+        spv->uninit(&spv);
+
+    return err;
+}
+
+static av_cold void gblur_vulkan_uninit(AVFilterContext *avctx)
+{
+    GBlurVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+
+    ff_vk_exec_pool_free(vkctx, &s->e);
+    ff_vk_shader_free(vkctx, &s->shd_hor);
+    ff_vk_shader_free(vkctx, &s->shd_ver);
+    ff_vk_free_buf(vkctx, &s->params_hor);
+    ff_vk_free_buf(vkctx, &s->params_ver);
+
+    ff_vk_uninit(&s->vkctx);
+
+    s->initialized = 0;
+}
+
+static int gblur_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
+{
+    int err;
+    AVFrame *tmp = NULL, *out = NULL;
+    AVFilterContext *ctx = link->dst;
+    GBlurVulkanContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+
+    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!out) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    tmp = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!tmp) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    if (!s->initialized)
+        RET(init_filter(ctx, in));
+
+    RET(ff_vk_filter_process_2pass(&s->vkctx, &s->e,
+                                   (FFVulkanShader *[2]){ &s->shd_hor, &s->shd_ver },
+                                   out, tmp, in, VK_NULL_HANDLE, NULL, 0));
+
+    err = av_frame_copy_props(out, in);
+    if (err < 0)
+        goto fail;
+
+    av_frame_free(&in);
+    av_frame_free(&tmp);
+
+    return ff_filter_frame(outlink, out);
+
+fail:
+    av_frame_free(&in);
+    av_frame_free(&tmp);
+    av_frame_free(&out);
+    return err;
+}
+
+#define OFFSET(x) offsetof(GBlurVulkanContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
+static const AVOption gblur_vulkan_options[] = {
+    { "sigma",  "Set sigma",                OFFSET(sigma),  AV_OPT_TYPE_FLOAT, { .dbl = 0.5 }, 0.01, 1024.0,                FLAGS },
+    { "sigmaV", "Set vertical sigma",       OFFSET(sigmaV), AV_OPT_TYPE_FLOAT, { .dbl = 0   }, 0.0,  1024.0,                FLAGS },
+    { "planes", "Set planes to filter",     OFFSET(planes), AV_OPT_TYPE_INT,   { .i64 = 0xF }, 0,    0xF,                   FLAGS },
+    { "size",   "Set kernel size",          OFFSET(size),   AV_OPT_TYPE_INT,   { .i64 = 19  }, 1,    GBLUR_MAX_KERNEL_SIZE, FLAGS },
+    { "sizeV",  "Set vertical kernel size", OFFSET(sizeV),  AV_OPT_TYPE_INT,   { .i64 = 0   }, 0,    GBLUR_MAX_KERNEL_SIZE, FLAGS },
+    { NULL },
+};
+
+AVFILTER_DEFINE_CLASS(gblur_vulkan);
+
+static const AVFilterPad gblur_vulkan_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = &gblur_vulkan_filter_frame,
+        .config_props = &ff_vk_filter_config_input,
+    }
+};
+
+static const AVFilterPad gblur_vulkan_outputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = &ff_vk_filter_config_output,
+    }
+};
+
+const FFFilter ff_vf_gblur_vulkan = {
+    .p.name         = "gblur_vulkan",
+    .p.description  = NULL_IF_CONFIG_SMALL("Gaussian Blur in Vulkan"),
+    .p.priv_class   = &gblur_vulkan_class,
+    .p.flags        = AVFILTER_FLAG_HWDEVICE,
+    .priv_size      = sizeof(GBlurVulkanContext),
+    .init           = &ff_vk_filter_init,
+    .uninit         = &gblur_vulkan_uninit,
+    FILTER_INPUTS(gblur_vulkan_inputs),
+    FILTER_OUTPUTS(gblur_vulkan_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};
-- 
2.49.1


From e1e9ccec4903a48739ce0770f3fe5ed271ef02cd Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:54:59 +0000
Subject: [PATCH 015/118] Changing vulkan file directory

---
 libavfilter/vf_interlace_vulkan.c | 321 ------------------------------
 1 file changed, 321 deletions(-)
 delete mode 100644 libavfilter/vf_interlace_vulkan.c

diff --git a/libavfilter/vf_interlace_vulkan.c b/libavfilter/vf_interlace_vulkan.c
deleted file mode 100644
index 7afb30c2d7..0000000000
--- a/libavfilter/vf_interlace_vulkan.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright 2025 (c) Niklas Haas
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/vulkan_spirv.h"
-#include "libavutil/opt.h"
-#include "vulkan_filter.h"
-
-#include "tinterlace.h"
-#include "filters.h"
-#include "video.h"
-
-typedef struct InterlaceVulkanContext {
-    FFVulkanContext vkctx;
-
-    int initialized;
-    FFVkExecPool e;
-    AVVulkanDeviceQueueFamily *qf;
-    VkSampler sampler;
-    FFVulkanShader shd;
-
-    int mode;
-    int lowpass;
-
-    AVFrame *cur; /* first frame in pair */
-} InterlaceVulkanContext;
-
-static const char lowpass_off[] = {
-    C(0, vec4 get_line(sampler2D tex, const vec2 pos)                         )
-    C(0, {                                                                    )
-    C(1,     return texture(tex, pos);                                        )
-    C(0, }                                                                    )
-};
-
-static const char lowpass_lin[] = {
-    C(0, vec4 get_line(sampler2D tex, const vec2 pos)                         )
-    C(0, {                                                                    )
-    C(1,     return 0.50 * texture(tex, pos) +                                )
-    C(1,            0.25 * texture(tex, pos - ivec2(0, 1)) +                  )
-    C(1,            0.25 * texture(tex, pos + ivec2(0, 1));                   )
-    C(0, }                                                                    )
-};
-
-static const char lowpass_complex[] = {
-    C(0, vec4 get_line(sampler2D tex, const vec2 pos)                         )
-    C(0, {                                                                    )
-    C(1,     return  0.75  * texture(tex, pos) +                              )
-    C(1,             0.25  * texture(tex, pos - ivec2(0, 1)) +                )
-    C(1,             0.25  * texture(tex, pos + ivec2(0, 1)) +                )
-    C(1,            -0.125 * texture(tex, pos - ivec2(0, 2)) +                )
-    C(1,            -0.125 * texture(tex, pos + ivec2(0, 2));                 )
-    C(0, }                                                                    )
-};
-
-static av_cold int init_filter(AVFilterContext *ctx)
-{
-    int err;
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    InterlaceVulkanContext *s = ctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
-    FFVulkanShader *shd;
-    FFVkSPIRVCompiler *spv;
-    FFVulkanDescriptorSetBinding *desc;
-
-    spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
-    if (!s->qf) {
-        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
-        err = AVERROR(ENOTSUP);
-        goto fail;
-    }
-
-    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
-    RET(ff_vk_init_sampler(vkctx, &s->sampler, 1,
-                           s->lowpass == VLPF_OFF ? VK_FILTER_NEAREST
-                                                  : VK_FILTER_LINEAR));
-    RET(ff_vk_shader_init(vkctx, &s->shd, "interlace",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          NULL, 0,
-                          32, 32, 1,
-                          0));
-    shd = &s->shd;
-
-    desc = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name       = "top_field",
-            .type       = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-            .samplers   = DUP_SAMPLER(s->sampler),
-        },
-        {
-            .name       = "bot_field",
-            .type       = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-            .samplers   = DUP_SAMPLER(s->sampler),
-        },
-        {
-            .name       = "output_img",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "writeonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 3, 0, 0));
-
-    switch (s->lowpass) {
-    case VLPF_OFF:
-        GLSLD(lowpass_off);
-        break;
-    case VLPF_LIN:
-        GLSLD(lowpass_lin);
-        break;
-    case VLPF_CMP:
-        GLSLD(lowpass_complex);
-        break;
-    }
-
-    GLSLC(0, void main()                                                  );
-    GLSLC(0, {                                                            );
-    GLSLC(1,     vec4 res;                                                );
-    GLSLC(1,     ivec2 size;                                              );
-    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);       );
-    GLSLC(1,     const vec2 ipos = pos + vec2(0.5);                       );
-    for (int i = 0; i < planes; i++) {
-        GLSLC(0,                                                          );
-        GLSLF(1,  size = imageSize(output_img[%i]);                     ,i);
-        GLSLC(1,  if (!IS_WITHIN(pos, size))                              );
-        GLSLC(2,      return;                                             );
-        GLSLC(1,  if (pos.y %% 2 == 0)                                    );
-        GLSLF(1,      res = get_line(top_field[%i], ipos);              ,i);
-        GLSLC(1,  else                                                    );
-        GLSLF(1,      res = get_line(bot_field[%i], ipos);              ,i);
-        GLSLF(1,  imageStore(output_img[%i], pos, res);                 ,i);
-    }
-    GLSLC(0, }                                                            );
-
-    RET(spv->compile_shader(vkctx, spv, &s->shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(vkctx, &s->shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
-
-    s->initialized = 1;
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-    if (spv)
-        spv->uninit(&spv);
-
-    return err;
-}
-
-static int interlace_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
-{
-    int err;
-    AVFrame *out = NULL, *input_top, *input_bot;
-    AVFilterContext *ctx = link->dst;
-    InterlaceVulkanContext *s = ctx->priv;
-    const AVFilterLink *inlink = ctx->inputs[0];
-    AVFilterLink *outlink = ctx->outputs[0];
-    FilterLink *l = ff_filter_link(outlink);
-
-    if (!s->initialized)
-        RET(init_filter(ctx));
-
-    /* Need both frames to filter */
-    if (!s->cur) {
-        s->cur = in;
-        return 0;
-    }
-
-    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-    if (!out) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    if (s->mode == MODE_TFF) {
-        input_top = s->cur;
-        input_bot = in;
-    } else {
-        input_top = in;
-        input_bot = s->cur;
-    }
-
-    RET(ff_vk_filter_process_Nin(&s->vkctx, &s->e, &s->shd,
-                                 out, (AVFrame *[]){ input_top, input_bot }, 2,
-                                 s->sampler, NULL, 0));
-
-    err = av_frame_copy_props(out, s->cur);
-    if (err < 0)
-        goto fail;
-
-    out->flags |= AV_FRAME_FLAG_INTERLACED;
-    if (s->mode == MODE_TFF)
-        out->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST;
-
-    out->pts = av_rescale_q(out->pts, inlink->time_base, outlink->time_base);
-    out->duration = av_rescale_q(1, av_inv_q(l->frame_rate), outlink->time_base);
-
-    av_frame_free(&s->cur);
-    av_frame_free(&in);
-
-    return ff_filter_frame(outlink, out);
-
-fail:
-    av_frame_free(&s->cur);
-    av_frame_free(&in);
-    av_frame_free(&out);
-    return err;
-}
-
-static void interlace_vulkan_uninit(AVFilterContext *avctx)
-{
-    InterlaceVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    FFVulkanFunctions *vk = &vkctx->vkfn;
-
-    av_frame_free(&s->cur);
-
-    ff_vk_exec_pool_free(vkctx, &s->e);
-    ff_vk_shader_free(vkctx, &s->shd);
-
-    if (s->sampler)
-        vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler,
-                           vkctx->hwctx->alloc);
-
-    ff_vk_uninit(&s->vkctx);
-
-    s->initialized = 0;
-}
-
-static int config_out_props(AVFilterLink *outlink)
-{
-    AVFilterLink *inlink = outlink->src->inputs[0];
-    const FilterLink *il = ff_filter_link(inlink);
-    FilterLink *ol = ff_filter_link(outlink);
-
-    ol->frame_rate = av_mul_q(il->frame_rate, av_make_q(1, 2));
-    outlink->time_base = av_mul_q(inlink->time_base, av_make_q(2, 1));
-    return ff_vk_filter_config_output(outlink);
-}
-
-#define OFFSET(x) offsetof(InterlaceVulkanContext, x)
-#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
-static const AVOption interlace_vulkan_options[] = {
-    { "scan",              "scanning mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = MODE_TFF}, 0, 1, FLAGS, .unit = "mode"},
-    { "tff",               "top field first",                              0, AV_OPT_TYPE_CONST, {.i64 = MODE_TFF}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"},
-    { "bff",               "bottom field first",                           0, AV_OPT_TYPE_CONST, {.i64 = MODE_BFF}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"},
-    { "lowpass",           "set vertical low-pass filter", OFFSET(lowpass), AV_OPT_TYPE_INT,   {.i64 = VLPF_LIN}, 0, 2, FLAGS, .unit = "lowpass" },
-    {     "off",           "disable vertical low-pass filter",             0, AV_OPT_TYPE_CONST, {.i64 = VLPF_OFF}, INT_MIN, INT_MAX, FLAGS, .unit = "lowpass" },
-    {     "linear",        "linear vertical low-pass filter",              0, AV_OPT_TYPE_CONST, {.i64 = VLPF_LIN}, INT_MIN, INT_MAX, FLAGS, .unit = "lowpass" },
-    {     "complex",       "complex vertical low-pass filter",             0, AV_OPT_TYPE_CONST, {.i64 = VLPF_CMP}, INT_MIN, INT_MAX, FLAGS, .unit = "lowpass" },
-    { NULL },
-};
-
-AVFILTER_DEFINE_CLASS(interlace_vulkan);
-
-static const AVFilterPad interlace_vulkan_inputs[] = {
-    {
-        .name         = "default",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame = &interlace_vulkan_filter_frame,
-        .config_props = &ff_vk_filter_config_input,
-    },
-};
-
-static const AVFilterPad interlace_vulkan_outputs[] = {
-    {
-        .name = "default",
-        .type = AVMEDIA_TYPE_VIDEO,
-        .config_props = &config_out_props,
-    },
-};
-
-const FFFilter ff_vf_interlace_vulkan = {
-    .p.name         = "interlace_vulkan",
-    .p.description  = NULL_IF_CONFIG_SMALL("Convert progressive video into interlaced."),
-    .p.priv_class   = &interlace_vulkan_class,
-    .p.flags        = AVFILTER_FLAG_HWDEVICE,
-    .priv_size      = sizeof(InterlaceVulkanContext),
-    .init           = &ff_vk_filter_init,
-    .uninit         = &interlace_vulkan_uninit,
-    FILTER_INPUTS(interlace_vulkan_inputs),
-    FILTER_OUTPUTS(interlace_vulkan_outputs),
-    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
-    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
-};
-- 
2.49.1


From b7f37d411ca2afb5aacc5514ecf208a5567c9c43 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:56:39 +0000
Subject: [PATCH 016/118] Changing vulkan file directory

---
 libavfilter/vulkan/vf_interlace_vulkan.c | 321 +++++++++++++++++++++++
 1 file changed, 321 insertions(+)
 create mode 100644 libavfilter/vulkan/vf_interlace_vulkan.c

diff --git a/libavfilter/vulkan/vf_interlace_vulkan.c b/libavfilter/vulkan/vf_interlace_vulkan.c
new file mode 100644
index 0000000000..948497a7f0
--- /dev/null
+++ b/libavfilter/vulkan/vf_interlace_vulkan.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright 2025 (c) Niklas Haas
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+#include "libavutil/opt.h"
+#include "vulkan_filter.h"
+
+#include "libavfilter/tinterlace.h"
+#include "libavfilter/filters.h"
+#include "libavfilter/video.h"
+
+typedef struct InterlaceVulkanContext {
+    FFVulkanContext vkctx;
+
+    int initialized;
+    FFVkExecPool e;
+    AVVulkanDeviceQueueFamily *qf;
+    VkSampler sampler;
+    FFVulkanShader shd;
+
+    int mode;
+    int lowpass;
+
+    AVFrame *cur; /* first frame in pair */
+} InterlaceVulkanContext;
+
+static const char lowpass_off[] = {
+    C(0, vec4 get_line(sampler2D tex, const vec2 pos)                         )
+    C(0, {                                                                    )
+    C(1,     return texture(tex, pos);                                        )
+    C(0, }                                                                    )
+};
+
+static const char lowpass_lin[] = {
+    C(0, vec4 get_line(sampler2D tex, const vec2 pos)                         )
+    C(0, {                                                                    )
+    C(1,     return 0.50 * texture(tex, pos) +                                )
+    C(1,            0.25 * texture(tex, pos - ivec2(0, 1)) +                  )
+    C(1,            0.25 * texture(tex, pos + ivec2(0, 1));                   )
+    C(0, }                                                                    )
+};
+
+static const char lowpass_complex[] = {
+    C(0, vec4 get_line(sampler2D tex, const vec2 pos)                         )
+    C(0, {                                                                    )
+    C(1,     return  0.75  * texture(tex, pos) +                              )
+    C(1,             0.25  * texture(tex, pos - ivec2(0, 1)) +                )
+    C(1,             0.25  * texture(tex, pos + ivec2(0, 1)) +                )
+    C(1,            -0.125 * texture(tex, pos - ivec2(0, 2)) +                )
+    C(1,            -0.125 * texture(tex, pos + ivec2(0, 2));                 )
+    C(0, }                                                                    )
+};
+
+static av_cold int init_filter(AVFilterContext *ctx)
+{
+    int err;
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    InterlaceVulkanContext *s = ctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
+    FFVulkanShader *shd;
+    FFVkSPIRVCompiler *spv;
+    FFVulkanDescriptorSetBinding *desc;
+
+    spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
+    if (!s->qf) {
+        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
+        err = AVERROR(ENOTSUP);
+        goto fail;
+    }
+
+    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
+    RET(ff_vk_init_sampler(vkctx, &s->sampler, 1,
+                           s->lowpass == VLPF_OFF ? VK_FILTER_NEAREST
+                                                  : VK_FILTER_LINEAR));
+    RET(ff_vk_shader_init(vkctx, &s->shd, "interlace",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          NULL, 0,
+                          32, 32, 1,
+                          0));
+    shd = &s->shd;
+
+    desc = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name       = "top_field",
+            .type       = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+            .samplers   = DUP_SAMPLER(s->sampler),
+        },
+        {
+            .name       = "bot_field",
+            .type       = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+            .samplers   = DUP_SAMPLER(s->sampler),
+        },
+        {
+            .name       = "output_img",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "writeonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 3, 0, 0));
+
+    switch (s->lowpass) {
+    case VLPF_OFF:
+        GLSLD(lowpass_off);
+        break;
+    case VLPF_LIN:
+        GLSLD(lowpass_lin);
+        break;
+    case VLPF_CMP:
+        GLSLD(lowpass_complex);
+        break;
+    }
+
+    GLSLC(0, void main()                                                  );
+    GLSLC(0, {                                                            );
+    GLSLC(1,     vec4 res;                                                );
+    GLSLC(1,     ivec2 size;                                              );
+    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);       );
+    GLSLC(1,     const vec2 ipos = pos + vec2(0.5);                       );
+    for (int i = 0; i < planes; i++) {
+        GLSLC(0,                                                          );
+        GLSLF(1,  size = imageSize(output_img[%i]);                     ,i);
+        GLSLC(1,  if (!IS_WITHIN(pos, size))                              );
+        GLSLC(2,      return;                                             );
+        GLSLC(1,  if (pos.y %% 2 == 0)                                    );
+        GLSLF(1,      res = get_line(top_field[%i], ipos);              ,i);
+        GLSLC(1,  else                                                    );
+        GLSLF(1,      res = get_line(bot_field[%i], ipos);              ,i);
+        GLSLF(1,  imageStore(output_img[%i], pos, res);                 ,i);
+    }
+    GLSLC(0, }                                                            );
+
+    RET(spv->compile_shader(vkctx, spv, &s->shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(vkctx, &s->shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
+
+    s->initialized = 1;
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+    if (spv)
+        spv->uninit(&spv);
+
+    return err;
+}
+
+static int interlace_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
+{
+    int err;
+    AVFrame *out = NULL, *input_top, *input_bot;
+    AVFilterContext *ctx = link->dst;
+    InterlaceVulkanContext *s = ctx->priv;
+    const AVFilterLink *inlink = ctx->inputs[0];
+    AVFilterLink *outlink = ctx->outputs[0];
+    FilterLink *l = ff_filter_link(outlink);
+
+    if (!s->initialized)
+        RET(init_filter(ctx));
+
+    /* Need both frames to filter */
+    if (!s->cur) {
+        s->cur = in;
+        return 0;
+    }
+
+    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!out) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    if (s->mode == MODE_TFF) {
+        input_top = s->cur;
+        input_bot = in;
+    } else {
+        input_top = in;
+        input_bot = s->cur;
+    }
+
+    RET(ff_vk_filter_process_Nin(&s->vkctx, &s->e, &s->shd,
+                                 out, (AVFrame *[]){ input_top, input_bot }, 2,
+                                 s->sampler, NULL, 0));
+
+    err = av_frame_copy_props(out, s->cur);
+    if (err < 0)
+        goto fail;
+
+    out->flags |= AV_FRAME_FLAG_INTERLACED;
+    if (s->mode == MODE_TFF)
+        out->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST;
+
+    out->pts = av_rescale_q(out->pts, inlink->time_base, outlink->time_base);
+    out->duration = av_rescale_q(1, av_inv_q(l->frame_rate), outlink->time_base);
+
+    av_frame_free(&s->cur);
+    av_frame_free(&in);
+
+    return ff_filter_frame(outlink, out);
+
+fail:
+    av_frame_free(&s->cur);
+    av_frame_free(&in);
+    av_frame_free(&out);
+    return err;
+}
+
+static void interlace_vulkan_uninit(AVFilterContext *avctx)
+{
+    InterlaceVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    FFVulkanFunctions *vk = &vkctx->vkfn;
+
+    av_frame_free(&s->cur);
+
+    ff_vk_exec_pool_free(vkctx, &s->e);
+    ff_vk_shader_free(vkctx, &s->shd);
+
+    if (s->sampler)
+        vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler,
+                           vkctx->hwctx->alloc);
+
+    ff_vk_uninit(&s->vkctx);
+
+    s->initialized = 0;
+}
+
+static int config_out_props(AVFilterLink *outlink)
+{
+    AVFilterLink *inlink = outlink->src->inputs[0];
+    const FilterLink *il = ff_filter_link(inlink);
+    FilterLink *ol = ff_filter_link(outlink);
+
+    ol->frame_rate = av_mul_q(il->frame_rate, av_make_q(1, 2));
+    outlink->time_base = av_mul_q(inlink->time_base, av_make_q(2, 1));
+    return ff_vk_filter_config_output(outlink);
+}
+
+#define OFFSET(x) offsetof(InterlaceVulkanContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
+static const AVOption interlace_vulkan_options[] = {
+    { "scan",              "scanning mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = MODE_TFF}, 0, 1, FLAGS, .unit = "mode"},
+    { "tff",               "top field first",                              0, AV_OPT_TYPE_CONST, {.i64 = MODE_TFF}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"},
+    { "bff",               "bottom field first",                           0, AV_OPT_TYPE_CONST, {.i64 = MODE_BFF}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"},
+    { "lowpass",           "set vertical low-pass filter", OFFSET(lowpass), AV_OPT_TYPE_INT,   {.i64 = VLPF_LIN}, 0, 2, FLAGS, .unit = "lowpass" },
+    {     "off",           "disable vertical low-pass filter",             0, AV_OPT_TYPE_CONST, {.i64 = VLPF_OFF}, INT_MIN, INT_MAX, FLAGS, .unit = "lowpass" },
+    {     "linear",        "linear vertical low-pass filter",              0, AV_OPT_TYPE_CONST, {.i64 = VLPF_LIN}, INT_MIN, INT_MAX, FLAGS, .unit = "lowpass" },
+    {     "complex",       "complex vertical low-pass filter",             0, AV_OPT_TYPE_CONST, {.i64 = VLPF_CMP}, INT_MIN, INT_MAX, FLAGS, .unit = "lowpass" },
+    { NULL },
+};
+
+AVFILTER_DEFINE_CLASS(interlace_vulkan);
+
+static const AVFilterPad interlace_vulkan_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = &interlace_vulkan_filter_frame,
+        .config_props = &ff_vk_filter_config_input,
+    },
+};
+
+static const AVFilterPad interlace_vulkan_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_VIDEO,
+        .config_props = &config_out_props,
+    },
+};
+
+const FFFilter ff_vf_interlace_vulkan = {
+    .p.name         = "interlace_vulkan",
+    .p.description  = NULL_IF_CONFIG_SMALL("Convert progressive video into interlaced."),
+    .p.priv_class   = &interlace_vulkan_class,
+    .p.flags        = AVFILTER_FLAG_HWDEVICE,
+    .priv_size      = sizeof(InterlaceVulkanContext),
+    .init           = &ff_vk_filter_init,
+    .uninit         = &interlace_vulkan_uninit,
+    FILTER_INPUTS(interlace_vulkan_inputs),
+    FILTER_OUTPUTS(interlace_vulkan_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};
-- 
2.49.1


From 37420dbbb910355e3424882ce34cd419213db9c1 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:57:37 +0000
Subject: [PATCH 017/118] Changing vulkan file directory

---
 libavfilter/vf_nlmeans_vulkan.c | 1120 -------------------------------
 1 file changed, 1120 deletions(-)
 delete mode 100644 libavfilter/vf_nlmeans_vulkan.c

diff --git a/libavfilter/vf_nlmeans_vulkan.c b/libavfilter/vf_nlmeans_vulkan.c
deleted file mode 100644
index 22a2a73eae..0000000000
--- a/libavfilter/vf_nlmeans_vulkan.c
+++ /dev/null
@@ -1,1120 +0,0 @@
-/*
- * Copyright (c) Lynne
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/mem.h"
-#include "libavutil/random_seed.h"
-#include "libavutil/vulkan_spirv.h"
-#include "libavutil/opt.h"
-#include "vulkan_filter.h"
-
-#include "filters.h"
-#include "video.h"
-
-#define TYPE_NAME  "vec4"
-#define TYPE_ELEMS 4
-#define TYPE_SIZE  (TYPE_ELEMS*4)
-
-typedef struct NLMeansVulkanContext {
-    FFVulkanContext vkctx;
-
-    int initialized;
-    FFVkExecPool e;
-    AVVulkanDeviceQueueFamily *qf;
-
-    AVBufferPool *integral_buf_pool;
-    AVBufferPool *ws_buf_pool;
-
-    FFVkBuffer xyoffsets_buf;
-
-    int pl_weights_rows;
-    FFVulkanShader shd_weights;
-    FFVulkanShader shd_denoise;
-
-    int *xoffsets;
-    int *yoffsets;
-    int nb_offsets;
-    float strength[4];
-    int patch[4];
-
-    struct nlmeans_opts {
-        int r;
-        double s;
-        double sc[4];
-        int p;
-        int pc[4];
-        int t;
-    } opts;
-} NLMeansVulkanContext;
-
-static void insert_first(FFVulkanShader *shd, int r, const char *off, int horiz, int plane, int comp)
-{
-    GLSLF(4, s1    = imageLoad(input_img[%i], pos + ivec2(%i + %s, %i + %s))[%i];
-          ,plane, horiz ? r : 0, horiz ? off : "0", !horiz ? r : 0, !horiz ? off : "0", comp);
-
-    GLSLF(4, s2[0] = imageLoad(input_img[%i], pos + offs[0] + ivec2(%i + %s, %i + %s))[%i];
-          ,plane, horiz ? r : 0, horiz ? off : "0", !horiz ? r : 0, !horiz ? off : "0", comp);
-    GLSLF(4, s2[1] = imageLoad(input_img[%i], pos + offs[1] + ivec2(%i + %s, %i + %s))[%i];
-          ,plane, horiz ? r : 0, horiz ? off : "0", !horiz ? r : 0, !horiz ? off : "0", comp);
-    GLSLF(4, s2[2] = imageLoad(input_img[%i], pos + offs[2] + ivec2(%i + %s, %i + %s))[%i];
-          ,plane, horiz ? r : 0, horiz ? off : "0", !horiz ? r : 0, !horiz ? off : "0", comp);
-    GLSLF(4, s2[3] = imageLoad(input_img[%i], pos + offs[3] + ivec2(%i + %s, %i + %s))[%i];
-          ,plane, horiz ? r : 0, horiz ? off : "0", !horiz ? r : 0, !horiz ? off : "0", comp);
-
-    GLSLC(4, s2 = (s1 - s2) * (s1 - s2);                                                    );
-}
-
-static void insert_horizontal_pass(FFVulkanShader *shd, int nb_rows, int first, int plane, int comp)
-{
-    GLSLF(1, pos.y = int(gl_GlobalInvocationID.x) * %i;                           ,nb_rows);
-    if (!first)
-        GLSLC(1, barrier();                                                       );
-    GLSLC(0,                                                                      );
-    GLSLF(1, if (pos.y < height[%i]) {                                            ,plane);
-    GLSLC(2,     #pragma unroll(1)                                                );
-    GLSLF(2,     for (r = 0; r < %i; r++) {                                       ,nb_rows);
-    GLSLC(3,         prefix_sum = DTYPE(0);                                       );
-    GLSLC(3,         offset = int_stride * uint64_t(pos.y + r);                   );
-    GLSLC(3,         dst = DataBuffer(uint64_t(integral_data) + offset);          );
-    GLSLC(0,                                                                      );
-    GLSLF(3,         for (pos.x = 0; pos.x < width[%i]; pos.x++) {                ,plane);
-    if (first)
-        insert_first(shd, 0, "r", 0, plane, comp);
-    else
-        GLSLC(4,         s2 = dst.v[pos.x];                                       );
-    GLSLC(4,             dst.v[pos.x] = s2 + prefix_sum;                          );
-    GLSLC(4,             prefix_sum += s2;                                        );
-    GLSLC(3,         }                                                            );
-    GLSLC(2,     }                                                                );
-    GLSLC(1, }                                                                    );
-    GLSLC(0,                                                                      );
-}
-
-static void insert_vertical_pass(FFVulkanShader *shd, int nb_rows, int first, int plane, int comp)
-{
-    GLSLF(1, pos.x = int(gl_GlobalInvocationID.x) * %i;                           ,nb_rows);
-    GLSLC(1, #pragma unroll(1)                                                    );
-    GLSLF(1, for (r = 0; r < %i; r++)                                             ,nb_rows);
-    GLSLC(2,     psum[r] = DTYPE(0);                                              );
-    GLSLC(0,                                                                      );
-    if (!first)
-        GLSLC(1, barrier();                                                       );
-    GLSLC(0,                                                                      );
-    GLSLF(1, if (pos.x < width[%i]) {                                             ,plane);
-    GLSLF(2,     for (pos.y = 0; pos.y < height[%i]; pos.y++) {                   ,plane);
-    GLSLC(3,         offset = int_stride * uint64_t(pos.y);                       );
-    GLSLC(3,         dst = DataBuffer(uint64_t(integral_data) + offset);          );
-    GLSLC(0,                                                                      );
-    GLSLC(3,         #pragma unroll(1)                                            );
-    GLSLF(3,         for (r = 0; r < %i; r++) {                                   ,nb_rows);
-    if (first)
-        insert_first(shd, 0, "r", 1, plane, comp);
-    else
-        GLSLC(4,         s2 = dst.v[pos.x + r];                                   );
-    GLSLC(4,             dst.v[pos.x + r] = s2 + psum[r];                         );
-    GLSLC(4,             psum[r] += s2;                                           );
-    GLSLC(3,         }                                                            );
-    GLSLC(2,     }                                                                );
-    GLSLC(1, }                                                                    );
-    GLSLC(0,                                                                      );
-}
-
-static void insert_weights_pass(FFVulkanShader *shd, int nb_rows, int vert,
-                                int t, int dst_comp, int plane, int comp)
-{
-    GLSLF(1, p = patch_size[%i];                                              ,dst_comp);
-    GLSLC(0,                                                                  );
-    GLSLC(1, barrier();                                                       );
-    GLSLC(0,                                                                  );
-    if (!vert) {
-        GLSLF(1, for (pos.y = 0; pos.y < height[%i]; pos.y++) {               ,plane);
-        GLSLF(2,     if (gl_GlobalInvocationID.x*%i >= width[%i])             ,nb_rows, plane);
-        GLSLC(3,         break;                                               );
-        GLSLF(2,     for (r = 0; r < %i; r++) {                               ,nb_rows);
-        GLSLF(3,         pos.x = int(gl_GlobalInvocationID.x) * %i + r;       ,nb_rows);
-    } else {
-        GLSLF(1, for (pos.x = 0; pos.x < width[%i]; pos.x++) {                ,plane);
-        GLSLF(2,     if (gl_GlobalInvocationID.x*%i >= height[%i])            ,nb_rows, plane);
-        GLSLC(3,         break;                                               );
-        GLSLF(2,     for (r = 0; r < %i; r++) {                               ,nb_rows);
-        GLSLF(3,         pos.y = int(gl_GlobalInvocationID.x) * %i + r;       ,nb_rows);
-    }
-    GLSLC(0,                                                                  );
-    GLSLC(3,         a = DTYPE(0);                                            );
-    GLSLC(3,         b = DTYPE(0);                                            );
-    GLSLC(3,         c = DTYPE(0);                                            );
-    GLSLC(3,         d = DTYPE(0);                                            );
-    GLSLC(0,                                                                  );
-    GLSLC(3,         lt = ((pos.x - p) < 0) || ((pos.y - p) < 0);             );
-    GLSLC(0,                                                                  );
-    GLSLF(3,         src[0] = imageLoad(input_img[%i], pos + offs[0])[%i];    ,plane, comp);
-    GLSLF(3,         src[1] = imageLoad(input_img[%i], pos + offs[1])[%i];    ,plane, comp);
-    GLSLF(3,         src[2] = imageLoad(input_img[%i], pos + offs[2])[%i];    ,plane, comp);
-    GLSLF(3,         src[3] = imageLoad(input_img[%i], pos + offs[3])[%i];    ,plane, comp);
-    GLSLC(0,                                                                  );
-    GLSLC(3,         if (lt == false) {                                       );
-    GLSLC(3,             offset = int_stride * uint64_t(pos.y - p);           );
-    GLSLC(3,             dst = DataBuffer(uint64_t(integral_data) + offset);  );
-    GLSLC(4,             a = dst.v[pos.x - p];                                );
-    GLSLC(4,             c = dst.v[pos.x + p];                                );
-    GLSLC(3,             offset = int_stride * uint64_t(pos.y + p);           );
-    GLSLC(3,             dst = DataBuffer(uint64_t(integral_data) + offset);  );
-    GLSLC(4,             b = dst.v[pos.x - p];                                );
-    GLSLC(4,             d = dst.v[pos.x + p];                                );
-    GLSLC(3,         }                                                        );
-    GLSLC(0,                                                                  );
-    GLSLC(3,         patch_diff = d + a - b - c;                              );
-    GLSLF(3,         w = exp(patch_diff * strength[%i]);                      ,dst_comp);
-    GLSLC(3,         w_sum = w[0] + w[1] + w[2] + w[3];                       );
-    GLSLC(3,         sum = dot(w, src*255);                                   );
-    GLSLC(0,                                                                  );
-    if (t > 1) {
-        GLSLF(3,         atomicAdd(weights_%i[pos.y*ws_stride[%i] + pos.x], w_sum);   ,dst_comp, dst_comp);
-        GLSLF(3,         atomicAdd(sums_%i[pos.y*ws_stride[%i] + pos.x], sum);        ,dst_comp, dst_comp);
-    } else {
-        GLSLF(3,         weights_%i[pos.y*ws_stride[%i] + pos.x] += w_sum;            ,dst_comp, dst_comp);
-        GLSLF(3,         sums_%i[pos.y*ws_stride[%i] + pos.x] += sum;                 ,dst_comp, dst_comp);
-    }
-    GLSLC(2,     }                                                            );
-    GLSLC(1, }                                                                );
-}
-
-typedef struct HorizontalPushData {
-    uint32_t width[4];
-    uint32_t height[4];
-    uint32_t ws_stride[4];
-    int32_t  patch_size[4];
-    float    strength[4];
-    VkDeviceAddress integral_base;
-    uint64_t integral_size;
-    uint64_t int_stride;
-    uint32_t xyoffs_start;
-} HorizontalPushData;
-
-static av_cold int init_weights_pipeline(FFVulkanContext *vkctx, FFVkExecPool *exec,
-                                         FFVulkanShader *shd,
-                                         FFVkSPIRVCompiler *spv,
-                                         int width, int height, int t,
-                                         const AVPixFmtDescriptor *desc,
-                                         int planes, int *nb_rows)
-{
-    int err;
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    FFVulkanDescriptorSetBinding *desc_set;
-    int max_dim = FFMAX(width, height);
-    uint32_t max_wg = vkctx->props.properties.limits.maxComputeWorkGroupSize[0];
-    int wg_size, wg_rows;
-
-    /* Round the max workgroup size to the previous power of two */
-    wg_size = max_wg;
-    wg_rows = 1;
-
-    if (max_wg > max_dim) {
-        wg_size = max_dim;
-    } else if (max_wg < max_dim) {
-        /* Make it fit */
-        while (wg_size*wg_rows < max_dim)
-            wg_rows++;
-    }
-
-    RET(ff_vk_shader_init(vkctx, shd, "nlmeans_weights",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          (const char *[]) { "GL_EXT_buffer_reference",
-                                             "GL_EXT_buffer_reference2" }, 2,
-                          wg_size, 1, 1,
-                          0));
-
-    *nb_rows = wg_rows;
-
-    if (t > 1)
-        GLSLC(0, #extension GL_EXT_shader_atomic_float : require              );
-    GLSLC(0, #extension GL_ARB_gpu_shader_int64 : require                     );
-    GLSLC(0,                                                                  );
-    GLSLF(0, #define DTYPE %s                                                 ,TYPE_NAME);
-    GLSLF(0, #define T_ALIGN %i                                               ,TYPE_SIZE);
-    GLSLC(0,                                                                  );
-    GLSLC(0, layout(buffer_reference, buffer_reference_align = T_ALIGN) buffer DataBuffer {  );
-    GLSLC(1,     DTYPE v[];                                                   );
-    GLSLC(0, };                                                               );
-    GLSLC(0,                                                                  );
-    GLSLC(0, layout(push_constant, std430) uniform pushConstants {            );
-    GLSLC(1,     uvec4 width;                                                 );
-    GLSLC(1,     uvec4 height;                                                );
-    GLSLC(1,     uvec4 ws_stride;                                             );
-    GLSLC(1,     ivec4 patch_size;                                            );
-    GLSLC(1,     vec4 strength;                                               );
-    GLSLC(1,     DataBuffer integral_base;                                    );
-    GLSLC(1,     uint64_t integral_size;                                      );
-    GLSLC(1,     uint64_t int_stride;                                         );
-    GLSLC(1,     uint xyoffs_start;                                           );
-    GLSLC(0, };                                                               );
-    GLSLC(0,                                                                  );
-
-    ff_vk_shader_add_push_const(shd, 0, sizeof(HorizontalPushData),
-                                VK_SHADER_STAGE_COMPUTE_BIT);
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name       = "input_img",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(vkctx->input_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "readonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-        {
-            .name        = "weights_buffer_0",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "float weights_0[];",
-        },
-        {
-            .name        = "sums_buffer_0",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "float sums_0[];",
-        },
-        {
-            .name        = "weights_buffer_1",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "float weights_1[];",
-        },
-        {
-            .name        = "sums_buffer_1",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "float sums_1[];",
-        },
-        {
-            .name        = "weights_buffer_2",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "float weights_2[];",
-        },
-        {
-            .name        = "sums_buffer_2",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "float sums_2[];",
-        },
-        {
-            .name        = "weights_buffer_3",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "float weights_3[];",
-        },
-        {
-            .name        = "sums_buffer_3",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "float sums_3[];",
-        },
-    };
-    RET(ff_vk_shader_add_descriptor_set(vkctx, shd, desc_set, 1 + 2*desc->nb_components, 0, 0));
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "xyoffsets_buffer",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .mem_quali   = "readonly",
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "ivec2 xyoffsets[];",
-        },
-    };
-    RET(ff_vk_shader_add_descriptor_set(vkctx, shd, desc_set, 1, 1, 0));
-
-    GLSLC(0,                                                                     );
-    GLSLC(0, void main()                                                         );
-    GLSLC(0, {                                                                   );
-    GLSLC(1,     uint64_t offset;                                                );
-    GLSLC(1,     DataBuffer dst;                                                 );
-    GLSLC(1,     float s1;                                                       );
-    GLSLC(1,     DTYPE s2;                                                       );
-    GLSLC(1,     DTYPE prefix_sum;                                               );
-    GLSLF(1,     DTYPE psum[%i];                                                 ,*nb_rows);
-    GLSLC(1,     int r;                                                          );
-    GLSLC(1,     ivec2 pos;                                                      );
-    GLSLC(1,     int p;                                                          );
-    GLSLC(0,                                                                     );
-    GLSLC(1,     DataBuffer integral_data;                                       );
-    GLSLF(1,     ivec2 offs[%i];                                                 ,TYPE_ELEMS);
-    GLSLC(0,                                                                     );
-    GLSLC(1,     int invoc_idx = int(gl_WorkGroupID.z);                          );
-    GLSLC(0,                                                                     );
-    GLSLC(1,     offset = integral_size * invoc_idx;                             );
-    GLSLC(1,     integral_data = DataBuffer(uint64_t(integral_base) + offset);   );
-    for (int i = 0; i < TYPE_ELEMS; i++)
-        GLSLF(1, offs[%i] = xyoffsets[xyoffs_start + %i*invoc_idx + %i];         ,i,TYPE_ELEMS,i);
-    GLSLC(0,                                                                     );
-    GLSLC(1,     DTYPE a;                                                        );
-    GLSLC(1,     DTYPE b;                                                        );
-    GLSLC(1,     DTYPE c;                                                        );
-    GLSLC(1,     DTYPE d;                                                        );
-    GLSLC(0,                                                                     );
-    GLSLC(1,     DTYPE patch_diff;                                               );
-    if (TYPE_ELEMS == 4) {
-        GLSLC(1, vec4 src;                                                       );
-        GLSLC(1, vec4 w;                                                         );
-    } else {
-        GLSLC(1, vec4 src[4];                                                    );
-        GLSLC(1, vec4 w[4];                                                      );
-    }
-    GLSLC(1,     float w_sum;                                                    );
-    GLSLC(1,     float sum;                                                      );
-    GLSLC(0,                                                                     );
-    GLSLC(1,     bool lt;                                                        );
-    GLSLC(1,     bool gt;                                                        );
-    GLSLC(0,                                                                     );
-
-    for (int i = 0; i < desc->nb_components; i++) {
-        int off = desc->comp[i].offset / (FFALIGN(desc->comp[i].depth, 8)/8);
-        if (width >= height) {
-            insert_horizontal_pass(shd, *nb_rows, 1, desc->comp[i].plane, off);
-            insert_vertical_pass(shd, *nb_rows, 0, desc->comp[i].plane, off);
-            insert_weights_pass(shd, *nb_rows, 0, t, i, desc->comp[i].plane, off);
-        } else {
-            insert_vertical_pass(shd, *nb_rows, 1, desc->comp[i].plane, off);
-            insert_horizontal_pass(shd, *nb_rows, 0, desc->comp[i].plane, off);
-            insert_weights_pass(shd, *nb_rows, 1, t, i, desc->comp[i].plane, off);
-        }
-    }
-
-    GLSLC(0, }                                                                   );
-
-    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main", &spv_opaque));
-    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(vkctx, exec, shd));
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-
-    return err;
-}
-
-typedef struct DenoisePushData {
-    uint32_t ws_stride[4];
-} DenoisePushData;
-
-static av_cold int init_denoise_pipeline(FFVulkanContext *vkctx, FFVkExecPool *exec,
-                                         FFVulkanShader *shd, FFVkSPIRVCompiler *spv,
-                                         const AVPixFmtDescriptor *desc, int planes)
-{
-    int err;
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    FFVulkanDescriptorSetBinding *desc_set;
-
-    RET(ff_vk_shader_init(vkctx, shd, "nlmeans_denoise",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          (const char *[]) { "GL_EXT_buffer_reference",
-                                             "GL_EXT_buffer_reference2" }, 2,
-                          32, 32, 1,
-                          0));
-
-    GLSLC(0, layout(push_constant, std430) uniform pushConstants {        );
-    GLSLC(1,    uvec4 ws_stride;                                          );
-    GLSLC(0, };                                                           );
-
-    ff_vk_shader_add_push_const(shd, 0, sizeof(DenoisePushData),
-                                VK_SHADER_STAGE_COMPUTE_BIT);
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "input_img",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout  = ff_vk_shader_rep_fmt(vkctx->input_format, FF_VK_REP_FLOAT),
-            .mem_quali   = "readonly",
-            .dimensions  = 2,
-            .elems       = planes,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-        {
-            .name        = "output_img",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout  = ff_vk_shader_rep_fmt(vkctx->output_format, FF_VK_REP_FLOAT),
-            .mem_quali   = "writeonly",
-            .dimensions  = 2,
-            .elems       = planes,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-    };
-    RET(ff_vk_shader_add_descriptor_set(vkctx, shd, desc_set, 2, 0, 0));
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "weights_buffer_0",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .mem_quali   = "readonly",
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "float weights_0[];",
-        },
-        {
-            .name        = "sums_buffer_0",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .mem_quali   = "readonly",
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "float sums_0[];",
-        },
-        {
-            .name        = "weights_buffer_1",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .mem_quali   = "readonly",
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "float weights_1[];",
-        },
-        {
-            .name        = "sums_buffer_1",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .mem_quali   = "readonly",
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "float sums_1[];",
-        },
-        {
-            .name        = "weights_buffer_2",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .mem_quali   = "readonly",
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "float weights_2[];",
-        },
-        {
-            .name        = "sums_buffer_2",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .mem_quali   = "readonly",
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "float sums_2[];",
-        },
-        {
-            .name        = "weights_buffer_3",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .mem_quali   = "readonly",
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "float weights_3[];",
-        },
-        {
-            .name        = "sums_buffer_3",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .mem_quali   = "readonly",
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "float sums_3[];",
-        },
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(vkctx, shd, desc_set, 2*desc->nb_components, 0, 0));
-
-    GLSLC(0, void main()                                                      );
-    GLSLC(0, {                                                                );
-    GLSLC(1,     ivec2 size;                                                  );
-    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);           );
-    GLSLC(1,     const uint plane = uint(gl_WorkGroupID.z);                   );
-    GLSLC(0,                                                                  );
-    GLSLC(1,     float w_sum;                                                 );
-    GLSLC(1,     float sum;                                                   );
-    GLSLC(1,     vec4 src;                                                    );
-    GLSLC(1,     vec4 r;                                                      );
-    GLSLC(0,                                                                  );
-    GLSLC(1,     size = imageSize(output_img[plane]);                         );
-    GLSLC(1,     if (!IS_WITHIN(pos, size))                                   );
-    GLSLC(2,         return;                                                  );
-    GLSLC(0,                                                                  );
-    GLSLC(1,     src = imageLoad(input_img[plane], pos);                      );
-    GLSLC(0,                                                                  );
-    for (int c = 0; c < desc->nb_components; c++) {
-        int off = desc->comp[c].offset / (FFALIGN(desc->comp[c].depth, 8)/8);
-        GLSLF(1, if (plane == %i) {                                              ,desc->comp[c].plane);
-        GLSLF(2,     w_sum = weights_%i[pos.y*ws_stride[%i] + pos.x];                           ,c, c);
-        GLSLF(2,     sum = sums_%i[pos.y*ws_stride[%i] + pos.x];                                ,c, c);
-        GLSLF(2,     r[%i] = (sum + src[%i]*255) / (1.0 + w_sum) / 255;                     ,off, off);
-        GLSLC(1, }                                                                                   );
-        GLSLC(0,                                                                                     );
-    }
-    GLSLC(1, imageStore(output_img[plane], pos, r);                           );
-    GLSLC(0, }                                                                );
-
-    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main", &spv_opaque));
-    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(vkctx, exec, shd));
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-
-    return err;
-}
-
-static av_cold int init_filter(AVFilterContext *ctx)
-{
-    int rad, err;
-    int xcnt = 0, ycnt = 0;
-    NLMeansVulkanContext *s = ctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
-    FFVkSPIRVCompiler *spv = NULL;
-    int *offsets_buf;
-    int offsets_dispatched = 0, nb_dispatches = 0;
-
-    const AVPixFmtDescriptor *desc;
-    desc = av_pix_fmt_desc_get(vkctx->output_format);
-    if (!desc)
-        return AVERROR(EINVAL);
-
-    if (!(s->opts.r & 1)) {
-        s->opts.r |= 1;
-        av_log(ctx, AV_LOG_WARNING, "Research size should be odd, setting to %i",
-               s->opts.r);
-    }
-
-    if (!(s->opts.p & 1)) {
-        s->opts.p |= 1;
-        av_log(ctx, AV_LOG_WARNING, "Patch size should be odd, setting to %i",
-               s->opts.p);
-    }
-
-    for (int i = 0; i < 4; i++) {
-        double str = (s->opts.sc[i] > 1.0) ? s->opts.sc[i] : s->opts.s;
-        int ps = (s->opts.pc[i] ? s->opts.pc[i] : s->opts.p);
-        str  = 10.0f*str;
-        str *= -str;
-        str  = 255.0*255.0 / str;
-        s->strength[i] = str;
-        if (!(ps & 1)) {
-            ps |= 1;
-            av_log(ctx, AV_LOG_WARNING, "Patch size should be odd, setting to %i",
-                   ps);
-        }
-        s->patch[i] = ps / 2;
-    }
-
-    rad = s->opts.r/2;
-    s->nb_offsets = (2*rad + 1)*(2*rad + 1) - 1;
-    s->xoffsets = av_malloc(s->nb_offsets*sizeof(*s->xoffsets));
-    s->yoffsets = av_malloc(s->nb_offsets*sizeof(*s->yoffsets));
-    s->nb_offsets = 0;
-
-    for (int x = -rad; x <= rad; x++) {
-        for (int y = -rad; y <= rad; y++) {
-            if (!x && !y)
-                continue;
-
-            s->xoffsets[xcnt++] = x;
-            s->yoffsets[ycnt++] = y;
-            s->nb_offsets++;
-        }
-    }
-
-    RET(ff_vk_create_buf(&s->vkctx, &s->xyoffsets_buf, 2*s->nb_offsets*sizeof(int32_t), NULL, NULL,
-                         VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
-                         VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
-                         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
-                         VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
-    RET(ff_vk_map_buffer(&s->vkctx, &s->xyoffsets_buf, (uint8_t **)&offsets_buf, 0));
-
-    for (int i = 0; i < 2*s->nb_offsets; i += 2) {
-        offsets_buf[i + 0] = s->xoffsets[i >> 1];
-        offsets_buf[i + 1] = s->yoffsets[i >> 1];
-    }
-
-    RET(ff_vk_unmap_buffer(&s->vkctx, &s->xyoffsets_buf, 1));
-
-    s->opts.t = FFMIN(s->opts.t, (FFALIGN(s->nb_offsets, TYPE_ELEMS) / TYPE_ELEMS));
-    if (!vkctx->atomic_float_feats.shaderBufferFloat32AtomicAdd) {
-        av_log(ctx, AV_LOG_WARNING, "Device doesn't support atomic float adds, "
-               "disabling dispatch parallelism\n");
-        s->opts.t = 1;
-    }
-
-    spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
-    if (!s->qf) {
-        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
-        err = AVERROR(ENOTSUP);
-        goto fail;
-    }
-
-    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, 1, 0, 0, 0, NULL));
-
-    RET(init_weights_pipeline(vkctx, &s->e, &s->shd_weights,
-                              spv, s->vkctx.output_width, s->vkctx.output_height,
-                              s->opts.t, desc, planes, &s->pl_weights_rows));
-
-    RET(init_denoise_pipeline(vkctx, &s->e, &s->shd_denoise,
-                              spv, desc, planes));
-
-    RET(ff_vk_shader_update_desc_buffer(vkctx, &s->e.contexts[0], &s->shd_weights,
-                                        1, 0, 0,
-                                    &s->xyoffsets_buf, 0, s->xyoffsets_buf.size,
-                                    VK_FORMAT_UNDEFINED));
-
-    do {
-        int wg_invoc = FFMIN((s->nb_offsets - offsets_dispatched)/TYPE_ELEMS, s->opts.t);
-        wg_invoc = FFMIN(wg_invoc, vkctx->props.properties.limits.maxComputeWorkGroupCount[2]);
-        offsets_dispatched += wg_invoc * TYPE_ELEMS;
-        nb_dispatches++;
-    } while (offsets_dispatched < s->nb_offsets);
-
-    av_log(ctx, AV_LOG_VERBOSE, "Filter initialized, %i x/y offsets, %i dispatches\n",
-           s->nb_offsets, nb_dispatches);
-
-    s->initialized = 1;
-
-fail:
-    if (spv)
-        spv->uninit(&spv);
-
-    return err;
-}
-
-static int denoise_pass(NLMeansVulkanContext *s, FFVkExecContext *exec,
-                        FFVkBuffer *ws_vk, uint32_t ws_stride[4])
-{
-    FFVulkanContext *vkctx = &s->vkctx;
-    FFVulkanFunctions *vk = &vkctx->vkfn;
-    VkBufferMemoryBarrier2 buf_bar[8];
-    int nb_buf_bar = 0;
-
-    DenoisePushData pd = {
-        { ws_stride[0], ws_stride[1], ws_stride[2], ws_stride[3] },
-    };
-
-    /* Denoise pass pipeline */
-    ff_vk_exec_bind_shader(vkctx, exec, &s->shd_denoise);
-
-    /* Push data */
-    ff_vk_shader_update_push_const(vkctx, exec, &s->shd_denoise,
-                                   VK_SHADER_STAGE_COMPUTE_BIT,
-                                   0, sizeof(pd), &pd);
-
-    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
-        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-        .srcStageMask = ws_vk->stage,
-        .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-        .srcAccessMask = ws_vk->access,
-        .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT,
-        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .buffer = ws_vk->buf,
-        .size = ws_vk->size,
-        .offset = 0,
-    };
-
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-            .pBufferMemoryBarriers = buf_bar,
-            .bufferMemoryBarrierCount = nb_buf_bar,
-        });
-    ws_vk->stage = buf_bar[0].dstStageMask;
-    ws_vk->access = buf_bar[0].dstAccessMask;
-
-    /* End of denoise pass */
-    vk->CmdDispatch(exec->buf,
-                    FFALIGN(vkctx->output_width,  s->shd_denoise.lg_size[0])/s->shd_denoise.lg_size[0],
-                    FFALIGN(vkctx->output_height, s->shd_denoise.lg_size[1])/s->shd_denoise.lg_size[1],
-                    av_pix_fmt_count_planes(s->vkctx.output_format));
-
-    return 0;
-}
-
-static int nlmeans_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
-{
-    int err;
-    AVFrame *out = NULL;
-    AVFilterContext *ctx = link->dst;
-    NLMeansVulkanContext *s = ctx->priv;
-    AVFilterLink *outlink = ctx->outputs[0];
-    FFVulkanContext *vkctx = &s->vkctx;
-    FFVulkanFunctions *vk = &vkctx->vkfn;
-
-    const AVPixFmtDescriptor *desc;
-    int plane_widths[4];
-    int plane_heights[4];
-
-    int offsets_dispatched = 0;
-
-    /* Integral */
-    AVBufferRef *integral_buf = NULL;
-    FFVkBuffer *integral_vk;
-    size_t int_stride;
-    size_t int_size;
-
-    /* Weights/sums */
-    AVBufferRef *ws_buf = NULL;
-    FFVkBuffer *ws_vk;
-    VkDeviceSize weights_offs[4];
-    VkDeviceSize sums_offs[4];
-    uint32_t ws_stride[4];
-    size_t ws_size[4];
-    size_t ws_total_size = 0;
-
-    FFVkExecContext *exec;
-    VkImageView in_views[AV_NUM_DATA_POINTERS];
-    VkImageView out_views[AV_NUM_DATA_POINTERS];
-    VkImageMemoryBarrier2 img_bar[8];
-    int nb_img_bar = 0;
-    VkBufferMemoryBarrier2 buf_bar[8];
-    int nb_buf_bar = 0;
-
-    if (!s->initialized)
-        RET(init_filter(ctx));
-
-    desc = av_pix_fmt_desc_get(vkctx->output_format);
-    if (!desc)
-        return AVERROR(EINVAL);
-
-    /* Integral image */
-    int_stride = s->shd_weights.lg_size[0]*s->pl_weights_rows*TYPE_SIZE;
-    int_size = s->shd_weights.lg_size[0]*s->pl_weights_rows*int_stride;
-
-    /* Plane dimensions */
-    for (int i = 0; i < desc->nb_components; i++) {
-        plane_widths[i] = !i || (i == 3) ? vkctx->output_width : AV_CEIL_RSHIFT(vkctx->output_width, desc->log2_chroma_w);
-        plane_heights[i] = !i || (i == 3) ? vkctx->output_height : AV_CEIL_RSHIFT(vkctx->output_height, desc->log2_chroma_w);
-        plane_widths[i]  = FFALIGN(plane_widths[i],  s->shd_denoise.lg_size[0]);
-        plane_heights[i] = FFALIGN(plane_heights[i], s->shd_denoise.lg_size[1]);
-
-        ws_stride[i] = plane_widths[i];
-        ws_size[i] = ws_stride[i] * plane_heights[i] * sizeof(float);
-        ws_total_size += ws_size[i];
-    }
-
-    /* Buffers */
-    err = ff_vk_get_pooled_buffer(&s->vkctx, &s->integral_buf_pool, &integral_buf,
-                                  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
-                                  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
-                                  NULL,
-                                  s->opts.t * int_size,
-                                  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
-    if (err < 0)
-        return err;
-    integral_vk = (FFVkBuffer *)integral_buf->data;
-
-    err = ff_vk_get_pooled_buffer(&s->vkctx, &s->ws_buf_pool, &ws_buf,
-                                  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
-                                  VK_BUFFER_USAGE_TRANSFER_DST_BIT |
-                                  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
-                                  NULL,
-                                  ws_total_size * 2,
-                                  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
-    if (err < 0)
-        return err;
-    ws_vk = (FFVkBuffer *)ws_buf->data;
-
-    weights_offs[0] = 0;
-    sums_offs[0] = ws_total_size;
-    for (int i = 1; i < desc->nb_components; i++) {
-        weights_offs[i] = weights_offs[i - 1] + ws_size[i - 1];
-        sums_offs[i] = sums_offs[i - 1] + ws_size[i - 1];
-    }
-
-    /* Output frame */
-    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-    if (!out) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    /* Execution context */
-    exec = ff_vk_exec_get(&s->vkctx, &s->e);
-    ff_vk_exec_start(vkctx, exec);
-
-    /* Dependencies */
-    RET(ff_vk_exec_add_dep_frame(vkctx, exec, in,
-                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
-    RET(ff_vk_exec_add_dep_frame(vkctx, exec, out,
-                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
-
-    RET(ff_vk_exec_add_dep_buf(vkctx, exec, &integral_buf, 1, 0));
-    integral_buf = NULL;
-
-    RET(ff_vk_exec_add_dep_buf(vkctx, exec, &ws_buf,       1, 0));
-    ws_buf = NULL;
-
-    /* Input frame prep */
-    RET(ff_vk_create_imageviews(vkctx, exec, in_views, in, FF_VK_REP_FLOAT));
-    ff_vk_frame_barrier(vkctx, exec, in, img_bar, &nb_img_bar,
-                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                        VK_ACCESS_SHADER_READ_BIT,
-                        VK_IMAGE_LAYOUT_GENERAL,
-                        VK_QUEUE_FAMILY_IGNORED);
-
-    /* Output frame prep */
-    RET(ff_vk_create_imageviews(vkctx, exec, out_views, out, FF_VK_REP_FLOAT));
-    ff_vk_frame_barrier(vkctx, exec, out, img_bar, &nb_img_bar,
-                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                        VK_ACCESS_SHADER_WRITE_BIT,
-                        VK_IMAGE_LAYOUT_GENERAL,
-                        VK_QUEUE_FAMILY_IGNORED);
-
-    nb_buf_bar = 0;
-    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
-        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-        .srcStageMask = ws_vk->stage,
-        .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
-        .srcAccessMask = ws_vk->access,
-        .dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
-        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .buffer = ws_vk->buf,
-        .size = ws_vk->size,
-        .offset = 0,
-    };
-    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
-        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-        .srcStageMask = integral_vk->stage,
-        .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-        .srcAccessMask = integral_vk->access,
-        .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
-                         VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
-        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .buffer = integral_vk->buf,
-        .size = integral_vk->size,
-        .offset = 0,
-    };
-
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-            .pImageMemoryBarriers = img_bar,
-            .imageMemoryBarrierCount = nb_img_bar,
-            .pBufferMemoryBarriers = buf_bar,
-            .bufferMemoryBarrierCount = nb_buf_bar,
-        });
-    ws_vk->stage = buf_bar[0].dstStageMask;
-    ws_vk->access = buf_bar[0].dstAccessMask;
-    integral_vk->stage = buf_bar[1].dstStageMask;
-    integral_vk->access = buf_bar[1].dstAccessMask;
-
-    /* Buffer zeroing */
-    vk->CmdFillBuffer(exec->buf, ws_vk->buf, 0, ws_vk->size, 0x0);
-
-    nb_buf_bar = 0;
-    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
-        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-        .srcStageMask = ws_vk->stage,
-        .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-        .srcAccessMask = ws_vk->access,
-        .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
-                         VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
-        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .buffer = ws_vk->buf,
-        .size = ws_vk->size,
-        .offset = 0,
-    };
-
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-            .pBufferMemoryBarriers = buf_bar,
-            .bufferMemoryBarrierCount = nb_buf_bar,
-        });
-    ws_vk->stage = buf_bar[0].dstStageMask;
-    ws_vk->access = buf_bar[0].dstAccessMask;
-
-    /* Update weights descriptors */
-    ff_vk_shader_update_img_array(vkctx, exec, &s->shd_weights, in, in_views, 0, 0,
-                                  VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
-    for (int i = 0; i < desc->nb_components; i++) {
-        RET(ff_vk_shader_update_desc_buffer(&s->vkctx, exec, &s->shd_weights, 0, 1 + i*2 + 0, 0,
-                                            ws_vk, weights_offs[i], ws_size[i],
-                                            VK_FORMAT_UNDEFINED));
-        RET(ff_vk_shader_update_desc_buffer(&s->vkctx, exec, &s->shd_weights, 0, 1 + i*2 + 1, 0,
-                                            ws_vk, sums_offs[i], ws_size[i],
-                                            VK_FORMAT_UNDEFINED));
-    }
-
-    /* Update denoise descriptors */
-    ff_vk_shader_update_img_array(vkctx, exec, &s->shd_denoise, in, in_views, 0, 0,
-                                  VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
-    ff_vk_shader_update_img_array(vkctx, exec, &s->shd_denoise, out, out_views, 0, 1,
-                                  VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
-    for (int i = 0; i < desc->nb_components; i++) {
-        RET(ff_vk_shader_update_desc_buffer(&s->vkctx, exec, &s->shd_denoise, 1, i*2 + 0, 0,
-                                            ws_vk, weights_offs[i], ws_size[i],
-                                            VK_FORMAT_UNDEFINED));
-        RET(ff_vk_shader_update_desc_buffer(&s->vkctx, exec, &s->shd_denoise, 1, i*2 + 1, 0,
-                                            ws_vk, sums_offs[i], ws_size[i],
-                                            VK_FORMAT_UNDEFINED));
-    }
-
-    /* Weights pipeline */
-    ff_vk_exec_bind_shader(vkctx, exec, &s->shd_weights);
-
-    do {
-        int wg_invoc;
-        HorizontalPushData pd = {
-            { plane_widths[0], plane_widths[1], plane_widths[2], plane_widths[3] },
-            { plane_heights[0], plane_heights[1], plane_heights[2], plane_heights[3] },
-            { ws_stride[0], ws_stride[1], ws_stride[2], ws_stride[3] },
-            { s->patch[0], s->patch[1], s->patch[2], s->patch[3] },
-            { s->strength[0], s->strength[1], s->strength[2], s->strength[2], },
-            integral_vk->address,
-            (uint64_t)int_size,
-            (uint64_t)int_stride,
-            offsets_dispatched,
-        };
-
-        /* Push data */
-        ff_vk_shader_update_push_const(vkctx, exec, &s->shd_weights,
-                                       VK_SHADER_STAGE_COMPUTE_BIT,
-                                       0, sizeof(pd), &pd);
-
-        if (offsets_dispatched) {
-            nb_buf_bar = 0;
-            buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
-                .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-                .srcStageMask = integral_vk->stage,
-                .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                .srcAccessMask = integral_vk->access,
-                .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
-                                 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
-                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-                .buffer = integral_vk->buf,
-                .size = integral_vk->size,
-                .offset = 0,
-            };
-
-            vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-                    .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-                    .pBufferMemoryBarriers = buf_bar,
-                    .bufferMemoryBarrierCount = nb_buf_bar,
-                });
-            integral_vk->stage = buf_bar[1].dstStageMask;
-            integral_vk->access = buf_bar[1].dstAccessMask;
-        }
-
-        wg_invoc = FFMIN((s->nb_offsets - offsets_dispatched)/TYPE_ELEMS, s->opts.t);
-        wg_invoc = FFMIN(wg_invoc, vkctx->props.properties.limits.maxComputeWorkGroupCount[2]);
-
-        /* End of horizontal pass */
-        vk->CmdDispatch(exec->buf, 1, 1, wg_invoc);
-
-        offsets_dispatched += wg_invoc * TYPE_ELEMS;
-    } while (offsets_dispatched < s->nb_offsets);
-
-    RET(denoise_pass(s, exec, ws_vk, ws_stride));
-
-    err = ff_vk_exec_submit(vkctx, exec);
-    if (err < 0)
-        return err;
-
-    err = av_frame_copy_props(out, in);
-    if (err < 0)
-        goto fail;
-
-    av_frame_free(&in);
-
-    return ff_filter_frame(outlink, out);
-
-fail:
-    av_buffer_unref(&integral_buf);
-    av_buffer_unref(&ws_buf);
-    av_frame_free(&in);
-    av_frame_free(&out);
-    return err;
-}
-
-static void nlmeans_vulkan_uninit(AVFilterContext *avctx)
-{
-    NLMeansVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-
-    ff_vk_exec_pool_free(vkctx, &s->e);
-    ff_vk_shader_free(vkctx, &s->shd_weights);
-    ff_vk_shader_free(vkctx, &s->shd_denoise);
-
-    av_buffer_pool_uninit(&s->integral_buf_pool);
-    av_buffer_pool_uninit(&s->ws_buf_pool);
-
-    ff_vk_uninit(&s->vkctx);
-
-    av_freep(&s->xoffsets);
-    av_freep(&s->yoffsets);
-
-    s->initialized = 0;
-}
-
-#define OFFSET(x) offsetof(NLMeansVulkanContext, x)
-#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
-static const AVOption nlmeans_vulkan_options[] = {
-    { "s",  "denoising strength for all components", OFFSET(opts.s), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 1.0, 100.0, FLAGS },
-    { "p",  "patch size for all components", OFFSET(opts.p), AV_OPT_TYPE_INT, { .i64 = 3*2+1 }, 0, 99, FLAGS },
-    { "r",  "research window radius", OFFSET(opts.r), AV_OPT_TYPE_INT, { .i64 = 7*2+1 }, 0, 99, FLAGS },
-    { "t",  "parallelism", OFFSET(opts.t), AV_OPT_TYPE_INT, { .i64 = 36 }, 1, 168, FLAGS },
-
-    { "s1", "denoising strength for component 1", OFFSET(opts.sc[0]), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 1.0, 100.0, FLAGS },
-    { "s2", "denoising strength for component 2", OFFSET(opts.sc[1]), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 1.0, 100.0, FLAGS },
-    { "s3", "denoising strength for component 3", OFFSET(opts.sc[2]), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 1.0, 100.0, FLAGS },
-    { "s4", "denoising strength for component 4", OFFSET(opts.sc[3]), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 1.0, 100.0, FLAGS },
-
-    { "p1", "patch size for component 1", OFFSET(opts.pc[0]), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 99, FLAGS },
-    { "p2", "patch size for component 2", OFFSET(opts.pc[1]), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 99, FLAGS },
-    { "p3", "patch size for component 3", OFFSET(opts.pc[2]), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 99, FLAGS },
-    { "p4", "patch size for component 4", OFFSET(opts.pc[3]), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 99, FLAGS },
-
-    { NULL }
-};
-
-AVFILTER_DEFINE_CLASS(nlmeans_vulkan);
-
-static const AVFilterPad nlmeans_vulkan_inputs[] = {
-    {
-        .name         = "default",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame = &nlmeans_vulkan_filter_frame,
-        .config_props = &ff_vk_filter_config_input,
-    },
-};
-
-static const AVFilterPad nlmeans_vulkan_outputs[] = {
-    {
-        .name = "default",
-        .type = AVMEDIA_TYPE_VIDEO,
-        .config_props = &ff_vk_filter_config_output,
-    },
-};
-
-const FFFilter ff_vf_nlmeans_vulkan = {
-    .p.name         = "nlmeans_vulkan",
-    .p.description  = NULL_IF_CONFIG_SMALL("Non-local means denoiser (Vulkan)"),
-    .p.priv_class   = &nlmeans_vulkan_class,
-    .p.flags        = AVFILTER_FLAG_HWDEVICE,
-    .priv_size      = sizeof(NLMeansVulkanContext),
-    .init           = &ff_vk_filter_init,
-    .uninit         = &nlmeans_vulkan_uninit,
-    FILTER_INPUTS(nlmeans_vulkan_inputs),
-    FILTER_OUTPUTS(nlmeans_vulkan_outputs),
-    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
-    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
-};
-- 
2.49.1


From ccafec6505a2853ff27071328806911f6529971c Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:58:11 +0000
Subject: [PATCH 018/118] Changing vulkan file directory

---
 libavfilter/vulkan/vf_nlmeans_vulkan.c | 1120 ++++++++++++++++++++++++
 1 file changed, 1120 insertions(+)
 create mode 100644 libavfilter/vulkan/vf_nlmeans_vulkan.c

diff --git a/libavfilter/vulkan/vf_nlmeans_vulkan.c b/libavfilter/vulkan/vf_nlmeans_vulkan.c
new file mode 100644
index 0000000000..6c86206829
--- /dev/null
+++ b/libavfilter/vulkan/vf_nlmeans_vulkan.c
@@ -0,0 +1,1120 @@
+/*
+ * Copyright (c) Lynne
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/mem.h"
+#include "libavutil/random_seed.h"
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+#include "libavutil/opt.h"
+#include "vulkan_filter.h"
+
+#include "libavfilter/filters.h"
+#include "libavfilter/video.h"
+
+#define TYPE_NAME  "vec4"
+#define TYPE_ELEMS 4
+#define TYPE_SIZE  (TYPE_ELEMS*4)
+
+typedef struct NLMeansVulkanContext {
+    FFVulkanContext vkctx;
+
+    int initialized;
+    FFVkExecPool e;
+    AVVulkanDeviceQueueFamily *qf;
+
+    AVBufferPool *integral_buf_pool;
+    AVBufferPool *ws_buf_pool;
+
+    FFVkBuffer xyoffsets_buf;
+
+    int pl_weights_rows;
+    FFVulkanShader shd_weights;
+    FFVulkanShader shd_denoise;
+
+    int *xoffsets;
+    int *yoffsets;
+    int nb_offsets;
+    float strength[4];
+    int patch[4];
+
+    struct nlmeans_opts {
+        int r;
+        double s;
+        double sc[4];
+        int p;
+        int pc[4];
+        int t;
+    } opts;
+} NLMeansVulkanContext;
+
+static void insert_first(FFVulkanShader *shd, int r, const char *off, int horiz, int plane, int comp)
+{
+    GLSLF(4, s1    = imageLoad(input_img[%i], pos + ivec2(%i + %s, %i + %s))[%i];
+          ,plane, horiz ? r : 0, horiz ? off : "0", !horiz ? r : 0, !horiz ? off : "0", comp);
+
+    GLSLF(4, s2[0] = imageLoad(input_img[%i], pos + offs[0] + ivec2(%i + %s, %i + %s))[%i];
+          ,plane, horiz ? r : 0, horiz ? off : "0", !horiz ? r : 0, !horiz ? off : "0", comp);
+    GLSLF(4, s2[1] = imageLoad(input_img[%i], pos + offs[1] + ivec2(%i + %s, %i + %s))[%i];
+          ,plane, horiz ? r : 0, horiz ? off : "0", !horiz ? r : 0, !horiz ? off : "0", comp);
+    GLSLF(4, s2[2] = imageLoad(input_img[%i], pos + offs[2] + ivec2(%i + %s, %i + %s))[%i];
+          ,plane, horiz ? r : 0, horiz ? off : "0", !horiz ? r : 0, !horiz ? off : "0", comp);
+    GLSLF(4, s2[3] = imageLoad(input_img[%i], pos + offs[3] + ivec2(%i + %s, %i + %s))[%i];
+          ,plane, horiz ? r : 0, horiz ? off : "0", !horiz ? r : 0, !horiz ? off : "0", comp);
+
+    GLSLC(4, s2 = (s1 - s2) * (s1 - s2);                                                    );
+}
+
+static void insert_horizontal_pass(FFVulkanShader *shd, int nb_rows, int first, int plane, int comp)
+{
+    GLSLF(1, pos.y = int(gl_GlobalInvocationID.x) * %i;                           ,nb_rows);
+    if (!first)
+        GLSLC(1, barrier();                                                       );
+    GLSLC(0,                                                                      );
+    GLSLF(1, if (pos.y < height[%i]) {                                            ,plane);
+    GLSLC(2,     #pragma unroll(1)                                                );
+    GLSLF(2,     for (r = 0; r < %i; r++) {                                       ,nb_rows);
+    GLSLC(3,         prefix_sum = DTYPE(0);                                       );
+    GLSLC(3,         offset = int_stride * uint64_t(pos.y + r);                   );
+    GLSLC(3,         dst = DataBuffer(uint64_t(integral_data) + offset);          );
+    GLSLC(0,                                                                      );
+    GLSLF(3,         for (pos.x = 0; pos.x < width[%i]; pos.x++) {                ,plane);
+    if (first)
+        insert_first(shd, 0, "r", 0, plane, comp);
+    else
+        GLSLC(4,         s2 = dst.v[pos.x];                                       );
+    GLSLC(4,             dst.v[pos.x] = s2 + prefix_sum;                          );
+    GLSLC(4,             prefix_sum += s2;                                        );
+    GLSLC(3,         }                                                            );
+    GLSLC(2,     }                                                                );
+    GLSLC(1, }                                                                    );
+    GLSLC(0,                                                                      );
+}
+
+static void insert_vertical_pass(FFVulkanShader *shd, int nb_rows, int first, int plane, int comp)
+{
+    GLSLF(1, pos.x = int(gl_GlobalInvocationID.x) * %i;                           ,nb_rows);
+    GLSLC(1, #pragma unroll(1)                                                    );
+    GLSLF(1, for (r = 0; r < %i; r++)                                             ,nb_rows);
+    GLSLC(2,     psum[r] = DTYPE(0);                                              );
+    GLSLC(0,                                                                      );
+    if (!first)
+        GLSLC(1, barrier();                                                       );
+    GLSLC(0,                                                                      );
+    GLSLF(1, if (pos.x < width[%i]) {                                             ,plane);
+    GLSLF(2,     for (pos.y = 0; pos.y < height[%i]; pos.y++) {                   ,plane);
+    GLSLC(3,         offset = int_stride * uint64_t(pos.y);                       );
+    GLSLC(3,         dst = DataBuffer(uint64_t(integral_data) + offset);          );
+    GLSLC(0,                                                                      );
+    GLSLC(3,         #pragma unroll(1)                                            );
+    GLSLF(3,         for (r = 0; r < %i; r++) {                                   ,nb_rows);
+    if (first)
+        insert_first(shd, 0, "r", 1, plane, comp);
+    else
+        GLSLC(4,         s2 = dst.v[pos.x + r];                                   );
+    GLSLC(4,             dst.v[pos.x + r] = s2 + psum[r];                         );
+    GLSLC(4,             psum[r] += s2;                                           );
+    GLSLC(3,         }                                                            );
+    GLSLC(2,     }                                                                );
+    GLSLC(1, }                                                                    );
+    GLSLC(0,                                                                      );
+}
+
+static void insert_weights_pass(FFVulkanShader *shd, int nb_rows, int vert,
+                                int t, int dst_comp, int plane, int comp)
+{
+    GLSLF(1, p = patch_size[%i];                                              ,dst_comp);
+    GLSLC(0,                                                                  );
+    GLSLC(1, barrier();                                                       );
+    GLSLC(0,                                                                  );
+    if (!vert) {
+        GLSLF(1, for (pos.y = 0; pos.y < height[%i]; pos.y++) {               ,plane);
+        GLSLF(2,     if (gl_GlobalInvocationID.x*%i >= width[%i])             ,nb_rows, plane);
+        GLSLC(3,         break;                                               );
+        GLSLF(2,     for (r = 0; r < %i; r++) {                               ,nb_rows);
+        GLSLF(3,         pos.x = int(gl_GlobalInvocationID.x) * %i + r;       ,nb_rows);
+    } else {
+        GLSLF(1, for (pos.x = 0; pos.x < width[%i]; pos.x++) {                ,plane);
+        GLSLF(2,     if (gl_GlobalInvocationID.x*%i >= height[%i])            ,nb_rows, plane);
+        GLSLC(3,         break;                                               );
+        GLSLF(2,     for (r = 0; r < %i; r++) {                               ,nb_rows);
+        GLSLF(3,         pos.y = int(gl_GlobalInvocationID.x) * %i + r;       ,nb_rows);
+    }
+    GLSLC(0,                                                                  );
+    GLSLC(3,         a = DTYPE(0);                                            );
+    GLSLC(3,         b = DTYPE(0);                                            );
+    GLSLC(3,         c = DTYPE(0);                                            );
+    GLSLC(3,         d = DTYPE(0);                                            );
+    GLSLC(0,                                                                  );
+    GLSLC(3,         lt = ((pos.x - p) < 0) || ((pos.y - p) < 0);             );
+    GLSLC(0,                                                                  );
+    GLSLF(3,         src[0] = imageLoad(input_img[%i], pos + offs[0])[%i];    ,plane, comp);
+    GLSLF(3,         src[1] = imageLoad(input_img[%i], pos + offs[1])[%i];    ,plane, comp);
+    GLSLF(3,         src[2] = imageLoad(input_img[%i], pos + offs[2])[%i];    ,plane, comp);
+    GLSLF(3,         src[3] = imageLoad(input_img[%i], pos + offs[3])[%i];    ,plane, comp);
+    GLSLC(0,                                                                  );
+    GLSLC(3,         if (lt == false) {                                       );
+    GLSLC(3,             offset = int_stride * uint64_t(pos.y - p);           );
+    GLSLC(3,             dst = DataBuffer(uint64_t(integral_data) + offset);  );
+    GLSLC(4,             a = dst.v[pos.x - p];                                );
+    GLSLC(4,             c = dst.v[pos.x + p];                                );
+    GLSLC(3,             offset = int_stride * uint64_t(pos.y + p);           );
+    GLSLC(3,             dst = DataBuffer(uint64_t(integral_data) + offset);  );
+    GLSLC(4,             b = dst.v[pos.x - p];                                );
+    GLSLC(4,             d = dst.v[pos.x + p];                                );
+    GLSLC(3,         }                                                        );
+    GLSLC(0,                                                                  );
+    GLSLC(3,         patch_diff = d + a - b - c;                              );
+    GLSLF(3,         w = exp(patch_diff * strength[%i]);                      ,dst_comp);
+    GLSLC(3,         w_sum = w[0] + w[1] + w[2] + w[3];                       );
+    GLSLC(3,         sum = dot(w, src*255);                                   );
+    GLSLC(0,                                                                  );
+    if (t > 1) {
+        GLSLF(3,         atomicAdd(weights_%i[pos.y*ws_stride[%i] + pos.x], w_sum);   ,dst_comp, dst_comp);
+        GLSLF(3,         atomicAdd(sums_%i[pos.y*ws_stride[%i] + pos.x], sum);        ,dst_comp, dst_comp);
+    } else {
+        GLSLF(3,         weights_%i[pos.y*ws_stride[%i] + pos.x] += w_sum;            ,dst_comp, dst_comp);
+        GLSLF(3,         sums_%i[pos.y*ws_stride[%i] + pos.x] += sum;                 ,dst_comp, dst_comp);
+    }
+    GLSLC(2,     }                                                            );
+    GLSLC(1, }                                                                );
+}
+
+typedef struct HorizontalPushData {
+    uint32_t width[4];
+    uint32_t height[4];
+    uint32_t ws_stride[4];
+    int32_t  patch_size[4];
+    float    strength[4];
+    VkDeviceAddress integral_base;
+    uint64_t integral_size;
+    uint64_t int_stride;
+    uint32_t xyoffs_start;
+} HorizontalPushData;
+
+static av_cold int init_weights_pipeline(FFVulkanContext *vkctx, FFVkExecPool *exec,
+                                         FFVulkanShader *shd,
+                                         FFVkSPIRVCompiler *spv,
+                                         int width, int height, int t,
+                                         const AVPixFmtDescriptor *desc,
+                                         int planes, int *nb_rows)
+{
+    int err;
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    FFVulkanDescriptorSetBinding *desc_set;
+    int max_dim = FFMAX(width, height);
+    uint32_t max_wg = vkctx->props.properties.limits.maxComputeWorkGroupSize[0];
+    int wg_size, wg_rows;
+
+    /* Round the max workgroup size to the previous power of two */
+    wg_size = max_wg;
+    wg_rows = 1;
+
+    if (max_wg > max_dim) {
+        wg_size = max_dim;
+    } else if (max_wg < max_dim) {
+        /* Make it fit */
+        while (wg_size*wg_rows < max_dim)
+            wg_rows++;
+    }
+
+    RET(ff_vk_shader_init(vkctx, shd, "nlmeans_weights",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          (const char *[]) { "GL_EXT_buffer_reference",
+                                             "GL_EXT_buffer_reference2" }, 2,
+                          wg_size, 1, 1,
+                          0));
+
+    *nb_rows = wg_rows;
+
+    if (t > 1)
+        GLSLC(0, #extension GL_EXT_shader_atomic_float : require              );
+    GLSLC(0, #extension GL_ARB_gpu_shader_int64 : require                     );
+    GLSLC(0,                                                                  );
+    GLSLF(0, #define DTYPE %s                                                 ,TYPE_NAME);
+    GLSLF(0, #define T_ALIGN %i                                               ,TYPE_SIZE);
+    GLSLC(0,                                                                  );
+    GLSLC(0, layout(buffer_reference, buffer_reference_align = T_ALIGN) buffer DataBuffer {  );
+    GLSLC(1,     DTYPE v[];                                                   );
+    GLSLC(0, };                                                               );
+    GLSLC(0,                                                                  );
+    GLSLC(0, layout(push_constant, std430) uniform pushConstants {            );
+    GLSLC(1,     uvec4 width;                                                 );
+    GLSLC(1,     uvec4 height;                                                );
+    GLSLC(1,     uvec4 ws_stride;                                             );
+    GLSLC(1,     ivec4 patch_size;                                            );
+    GLSLC(1,     vec4 strength;                                               );
+    GLSLC(1,     DataBuffer integral_base;                                    );
+    GLSLC(1,     uint64_t integral_size;                                      );
+    GLSLC(1,     uint64_t int_stride;                                         );
+    GLSLC(1,     uint xyoffs_start;                                           );
+    GLSLC(0, };                                                               );
+    GLSLC(0,                                                                  );
+
+    ff_vk_shader_add_push_const(shd, 0, sizeof(HorizontalPushData),
+                                VK_SHADER_STAGE_COMPUTE_BIT);
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name       = "input_img",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(vkctx->input_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "readonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+        {
+            .name        = "weights_buffer_0",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "float weights_0[];",
+        },
+        {
+            .name        = "sums_buffer_0",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "float sums_0[];",
+        },
+        {
+            .name        = "weights_buffer_1",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "float weights_1[];",
+        },
+        {
+            .name        = "sums_buffer_1",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "float sums_1[];",
+        },
+        {
+            .name        = "weights_buffer_2",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "float weights_2[];",
+        },
+        {
+            .name        = "sums_buffer_2",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "float sums_2[];",
+        },
+        {
+            .name        = "weights_buffer_3",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "float weights_3[];",
+        },
+        {
+            .name        = "sums_buffer_3",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "float sums_3[];",
+        },
+    };
+    RET(ff_vk_shader_add_descriptor_set(vkctx, shd, desc_set, 1 + 2*desc->nb_components, 0, 0));
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "xyoffsets_buffer",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .mem_quali   = "readonly",
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "ivec2 xyoffsets[];",
+        },
+    };
+    RET(ff_vk_shader_add_descriptor_set(vkctx, shd, desc_set, 1, 1, 0));
+
+    GLSLC(0,                                                                     );
+    GLSLC(0, void main()                                                         );
+    GLSLC(0, {                                                                   );
+    GLSLC(1,     uint64_t offset;                                                );
+    GLSLC(1,     DataBuffer dst;                                                 );
+    GLSLC(1,     float s1;                                                       );
+    GLSLC(1,     DTYPE s2;                                                       );
+    GLSLC(1,     DTYPE prefix_sum;                                               );
+    GLSLF(1,     DTYPE psum[%i];                                                 ,*nb_rows);
+    GLSLC(1,     int r;                                                          );
+    GLSLC(1,     ivec2 pos;                                                      );
+    GLSLC(1,     int p;                                                          );
+    GLSLC(0,                                                                     );
+    GLSLC(1,     DataBuffer integral_data;                                       );
+    GLSLF(1,     ivec2 offs[%i];                                                 ,TYPE_ELEMS);
+    GLSLC(0,                                                                     );
+    GLSLC(1,     int invoc_idx = int(gl_WorkGroupID.z);                          );
+    GLSLC(0,                                                                     );
+    GLSLC(1,     offset = integral_size * invoc_idx;                             );
+    GLSLC(1,     integral_data = DataBuffer(uint64_t(integral_base) + offset);   );
+    for (int i = 0; i < TYPE_ELEMS; i++)
+        GLSLF(1, offs[%i] = xyoffsets[xyoffs_start + %i*invoc_idx + %i];         ,i,TYPE_ELEMS,i);
+    GLSLC(0,                                                                     );
+    GLSLC(1,     DTYPE a;                                                        );
+    GLSLC(1,     DTYPE b;                                                        );
+    GLSLC(1,     DTYPE c;                                                        );
+    GLSLC(1,     DTYPE d;                                                        );
+    GLSLC(0,                                                                     );
+    GLSLC(1,     DTYPE patch_diff;                                               );
+    if (TYPE_ELEMS == 4) {
+        GLSLC(1, vec4 src;                                                       );
+        GLSLC(1, vec4 w;                                                         );
+    } else {
+        GLSLC(1, vec4 src[4];                                                    );
+        GLSLC(1, vec4 w[4];                                                      );
+    }
+    GLSLC(1,     float w_sum;                                                    );
+    GLSLC(1,     float sum;                                                      );
+    GLSLC(0,                                                                     );
+    GLSLC(1,     bool lt;                                                        );
+    GLSLC(1,     bool gt;                                                        );
+    GLSLC(0,                                                                     );
+
+    for (int i = 0; i < desc->nb_components; i++) {
+        int off = desc->comp[i].offset / (FFALIGN(desc->comp[i].depth, 8)/8);
+        if (width >= height) {
+            insert_horizontal_pass(shd, *nb_rows, 1, desc->comp[i].plane, off);
+            insert_vertical_pass(shd, *nb_rows, 0, desc->comp[i].plane, off);
+            insert_weights_pass(shd, *nb_rows, 0, t, i, desc->comp[i].plane, off);
+        } else {
+            insert_vertical_pass(shd, *nb_rows, 1, desc->comp[i].plane, off);
+            insert_horizontal_pass(shd, *nb_rows, 0, desc->comp[i].plane, off);
+            insert_weights_pass(shd, *nb_rows, 1, t, i, desc->comp[i].plane, off);
+        }
+    }
+
+    GLSLC(0, }                                                                   );
+
+    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main", &spv_opaque));
+    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(vkctx, exec, shd));
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+
+    return err;
+}
+
+typedef struct DenoisePushData {
+    uint32_t ws_stride[4];
+} DenoisePushData;
+
+static av_cold int init_denoise_pipeline(FFVulkanContext *vkctx, FFVkExecPool *exec,
+                                         FFVulkanShader *shd, FFVkSPIRVCompiler *spv,
+                                         const AVPixFmtDescriptor *desc, int planes)
+{
+    int err;
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    FFVulkanDescriptorSetBinding *desc_set;
+
+    RET(ff_vk_shader_init(vkctx, shd, "nlmeans_denoise",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          (const char *[]) { "GL_EXT_buffer_reference",
+                                             "GL_EXT_buffer_reference2" }, 2,
+                          32, 32, 1,
+                          0));
+
+    GLSLC(0, layout(push_constant, std430) uniform pushConstants {        );
+    GLSLC(1,    uvec4 ws_stride;                                          );
+    GLSLC(0, };                                                           );
+
+    ff_vk_shader_add_push_const(shd, 0, sizeof(DenoisePushData),
+                                VK_SHADER_STAGE_COMPUTE_BIT);
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "input_img",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout  = ff_vk_shader_rep_fmt(vkctx->input_format, FF_VK_REP_FLOAT),
+            .mem_quali   = "readonly",
+            .dimensions  = 2,
+            .elems       = planes,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+        {
+            .name        = "output_img",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout  = ff_vk_shader_rep_fmt(vkctx->output_format, FF_VK_REP_FLOAT),
+            .mem_quali   = "writeonly",
+            .dimensions  = 2,
+            .elems       = planes,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+    };
+    RET(ff_vk_shader_add_descriptor_set(vkctx, shd, desc_set, 2, 0, 0));
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "weights_buffer_0",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .mem_quali   = "readonly",
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "float weights_0[];",
+        },
+        {
+            .name        = "sums_buffer_0",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .mem_quali   = "readonly",
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "float sums_0[];",
+        },
+        {
+            .name        = "weights_buffer_1",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .mem_quali   = "readonly",
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "float weights_1[];",
+        },
+        {
+            .name        = "sums_buffer_1",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .mem_quali   = "readonly",
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "float sums_1[];",
+        },
+        {
+            .name        = "weights_buffer_2",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .mem_quali   = "readonly",
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "float weights_2[];",
+        },
+        {
+            .name        = "sums_buffer_2",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .mem_quali   = "readonly",
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "float sums_2[];",
+        },
+        {
+            .name        = "weights_buffer_3",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .mem_quali   = "readonly",
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "float weights_3[];",
+        },
+        {
+            .name        = "sums_buffer_3",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .mem_quali   = "readonly",
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "float sums_3[];",
+        },
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(vkctx, shd, desc_set, 2*desc->nb_components, 0, 0));
+
+    GLSLC(0, void main()                                                      );
+    GLSLC(0, {                                                                );
+    GLSLC(1,     ivec2 size;                                                  );
+    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);           );
+    GLSLC(1,     const uint plane = uint(gl_WorkGroupID.z);                   );
+    GLSLC(0,                                                                  );
+    GLSLC(1,     float w_sum;                                                 );
+    GLSLC(1,     float sum;                                                   );
+    GLSLC(1,     vec4 src;                                                    );
+    GLSLC(1,     vec4 r;                                                      );
+    GLSLC(0,                                                                  );
+    GLSLC(1,     size = imageSize(output_img[plane]);                         );
+    GLSLC(1,     if (!IS_WITHIN(pos, size))                                   );
+    GLSLC(2,         return;                                                  );
+    GLSLC(0,                                                                  );
+    GLSLC(1,     src = imageLoad(input_img[plane], pos);                      );
+    GLSLC(0,                                                                  );
+    for (int c = 0; c < desc->nb_components; c++) {
+        int off = desc->comp[c].offset / (FFALIGN(desc->comp[c].depth, 8)/8);
+        GLSLF(1, if (plane == %i) {                                              ,desc->comp[c].plane);
+        GLSLF(2,     w_sum = weights_%i[pos.y*ws_stride[%i] + pos.x];                           ,c, c);
+        GLSLF(2,     sum = sums_%i[pos.y*ws_stride[%i] + pos.x];                                ,c, c);
+        GLSLF(2,     r[%i] = (sum + src[%i]*255) / (1.0 + w_sum) / 255;                     ,off, off);
+        GLSLC(1, }                                                                                   );
+        GLSLC(0,                                                                                     );
+    }
+    GLSLC(1, imageStore(output_img[plane], pos, r);                           );
+    GLSLC(0, }                                                                );
+
+    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main", &spv_opaque));
+    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(vkctx, exec, shd));
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+
+    return err;
+}
+
+static av_cold int init_filter(AVFilterContext *ctx)
+{
+    int rad, err;
+    int xcnt = 0, ycnt = 0;
+    NLMeansVulkanContext *s = ctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
+    FFVkSPIRVCompiler *spv = NULL;
+    int *offsets_buf;
+    int offsets_dispatched = 0, nb_dispatches = 0;
+
+    const AVPixFmtDescriptor *desc;
+    desc = av_pix_fmt_desc_get(vkctx->output_format);
+    if (!desc)
+        return AVERROR(EINVAL);
+
+    if (!(s->opts.r & 1)) {
+        s->opts.r |= 1;
+        av_log(ctx, AV_LOG_WARNING, "Research size should be odd, setting to %i",
+               s->opts.r);
+    }
+
+    if (!(s->opts.p & 1)) {
+        s->opts.p |= 1;
+        av_log(ctx, AV_LOG_WARNING, "Patch size should be odd, setting to %i",
+               s->opts.p);
+    }
+
+    for (int i = 0; i < 4; i++) {
+        double str = (s->opts.sc[i] > 1.0) ? s->opts.sc[i] : s->opts.s;
+        int ps = (s->opts.pc[i] ? s->opts.pc[i] : s->opts.p);
+        str  = 10.0f*str;
+        str *= -str;
+        str  = 255.0*255.0 / str;
+        s->strength[i] = str;
+        if (!(ps & 1)) {
+            ps |= 1;
+            av_log(ctx, AV_LOG_WARNING, "Patch size should be odd, setting to %i",
+                   ps);
+        }
+        s->patch[i] = ps / 2;
+    }
+
+    rad = s->opts.r/2;
+    s->nb_offsets = (2*rad + 1)*(2*rad + 1) - 1;
+    s->xoffsets = av_malloc(s->nb_offsets*sizeof(*s->xoffsets));
+    s->yoffsets = av_malloc(s->nb_offsets*sizeof(*s->yoffsets));
+    s->nb_offsets = 0;
+
+    for (int x = -rad; x <= rad; x++) {
+        for (int y = -rad; y <= rad; y++) {
+            if (!x && !y)
+                continue;
+
+            s->xoffsets[xcnt++] = x;
+            s->yoffsets[ycnt++] = y;
+            s->nb_offsets++;
+        }
+    }
+
+    RET(ff_vk_create_buf(&s->vkctx, &s->xyoffsets_buf, 2*s->nb_offsets*sizeof(int32_t), NULL, NULL,
+                         VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
+                         VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+                         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+                         VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
+    RET(ff_vk_map_buffer(&s->vkctx, &s->xyoffsets_buf, (uint8_t **)&offsets_buf, 0));
+
+    for (int i = 0; i < 2*s->nb_offsets; i += 2) {
+        offsets_buf[i + 0] = s->xoffsets[i >> 1];
+        offsets_buf[i + 1] = s->yoffsets[i >> 1];
+    }
+
+    RET(ff_vk_unmap_buffer(&s->vkctx, &s->xyoffsets_buf, 1));
+
+    s->opts.t = FFMIN(s->opts.t, (FFALIGN(s->nb_offsets, TYPE_ELEMS) / TYPE_ELEMS));
+    if (!vkctx->atomic_float_feats.shaderBufferFloat32AtomicAdd) {
+        av_log(ctx, AV_LOG_WARNING, "Device doesn't support atomic float adds, "
+               "disabling dispatch parallelism\n");
+        s->opts.t = 1;
+    }
+
+    spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
+    if (!s->qf) {
+        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
+        err = AVERROR(ENOTSUP);
+        goto fail;
+    }
+
+    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, 1, 0, 0, 0, NULL));
+
+    RET(init_weights_pipeline(vkctx, &s->e, &s->shd_weights,
+                              spv, s->vkctx.output_width, s->vkctx.output_height,
+                              s->opts.t, desc, planes, &s->pl_weights_rows));
+
+    RET(init_denoise_pipeline(vkctx, &s->e, &s->shd_denoise,
+                              spv, desc, planes));
+
+    RET(ff_vk_shader_update_desc_buffer(vkctx, &s->e.contexts[0], &s->shd_weights,
+                                        1, 0, 0,
+                                    &s->xyoffsets_buf, 0, s->xyoffsets_buf.size,
+                                    VK_FORMAT_UNDEFINED));
+
+    do {
+        int wg_invoc = FFMIN((s->nb_offsets - offsets_dispatched)/TYPE_ELEMS, s->opts.t);
+        wg_invoc = FFMIN(wg_invoc, vkctx->props.properties.limits.maxComputeWorkGroupCount[2]);
+        offsets_dispatched += wg_invoc * TYPE_ELEMS;
+        nb_dispatches++;
+    } while (offsets_dispatched < s->nb_offsets);
+
+    av_log(ctx, AV_LOG_VERBOSE, "Filter initialized, %i x/y offsets, %i dispatches\n",
+           s->nb_offsets, nb_dispatches);
+
+    s->initialized = 1;
+
+fail:
+    if (spv)
+        spv->uninit(&spv);
+
+    return err;
+}
+
+static int denoise_pass(NLMeansVulkanContext *s, FFVkExecContext *exec,
+                        FFVkBuffer *ws_vk, uint32_t ws_stride[4])
+{
+    FFVulkanContext *vkctx = &s->vkctx;
+    FFVulkanFunctions *vk = &vkctx->vkfn;
+    VkBufferMemoryBarrier2 buf_bar[8];
+    int nb_buf_bar = 0;
+
+    DenoisePushData pd = {
+        { ws_stride[0], ws_stride[1], ws_stride[2], ws_stride[3] },
+    };
+
+    /* Denoise pass pipeline */
+    ff_vk_exec_bind_shader(vkctx, exec, &s->shd_denoise);
+
+    /* Push data */
+    ff_vk_shader_update_push_const(vkctx, exec, &s->shd_denoise,
+                                   VK_SHADER_STAGE_COMPUTE_BIT,
+                                   0, sizeof(pd), &pd);
+
+    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
+        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+        .srcStageMask = ws_vk->stage,
+        .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+        .srcAccessMask = ws_vk->access,
+        .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT,
+        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .buffer = ws_vk->buf,
+        .size = ws_vk->size,
+        .offset = 0,
+    };
+
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+            .pBufferMemoryBarriers = buf_bar,
+            .bufferMemoryBarrierCount = nb_buf_bar,
+        });
+    ws_vk->stage = buf_bar[0].dstStageMask;
+    ws_vk->access = buf_bar[0].dstAccessMask;
+
+    /* End of denoise pass */
+    vk->CmdDispatch(exec->buf,
+                    FFALIGN(vkctx->output_width,  s->shd_denoise.lg_size[0])/s->shd_denoise.lg_size[0],
+                    FFALIGN(vkctx->output_height, s->shd_denoise.lg_size[1])/s->shd_denoise.lg_size[1],
+                    av_pix_fmt_count_planes(s->vkctx.output_format));
+
+    return 0;
+}
+
+static int nlmeans_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
+{
+    int err;
+    AVFrame *out = NULL;
+    AVFilterContext *ctx = link->dst;
+    NLMeansVulkanContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+    FFVulkanContext *vkctx = &s->vkctx;
+    FFVulkanFunctions *vk = &vkctx->vkfn;
+
+    const AVPixFmtDescriptor *desc;
+    int plane_widths[4];
+    int plane_heights[4];
+
+    int offsets_dispatched = 0;
+
+    /* Integral */
+    AVBufferRef *integral_buf = NULL;
+    FFVkBuffer *integral_vk;
+    size_t int_stride;
+    size_t int_size;
+
+    /* Weights/sums */
+    AVBufferRef *ws_buf = NULL;
+    FFVkBuffer *ws_vk;
+    VkDeviceSize weights_offs[4];
+    VkDeviceSize sums_offs[4];
+    uint32_t ws_stride[4];
+    size_t ws_size[4];
+    size_t ws_total_size = 0;
+
+    FFVkExecContext *exec;
+    VkImageView in_views[AV_NUM_DATA_POINTERS];
+    VkImageView out_views[AV_NUM_DATA_POINTERS];
+    VkImageMemoryBarrier2 img_bar[8];
+    int nb_img_bar = 0;
+    VkBufferMemoryBarrier2 buf_bar[8];
+    int nb_buf_bar = 0;
+
+    if (!s->initialized)
+        RET(init_filter(ctx));
+
+    desc = av_pix_fmt_desc_get(vkctx->output_format);
+    if (!desc)
+        return AVERROR(EINVAL);
+
+    /* Integral image */
+    int_stride = s->shd_weights.lg_size[0]*s->pl_weights_rows*TYPE_SIZE;
+    int_size = s->shd_weights.lg_size[0]*s->pl_weights_rows*int_stride;
+
+    /* Plane dimensions */
+    for (int i = 0; i < desc->nb_components; i++) {
+        plane_widths[i] = !i || (i == 3) ? vkctx->output_width : AV_CEIL_RSHIFT(vkctx->output_width, desc->log2_chroma_w);
+        plane_heights[i] = !i || (i == 3) ? vkctx->output_height : AV_CEIL_RSHIFT(vkctx->output_height, desc->log2_chroma_w);
+        plane_widths[i]  = FFALIGN(plane_widths[i],  s->shd_denoise.lg_size[0]);
+        plane_heights[i] = FFALIGN(plane_heights[i], s->shd_denoise.lg_size[1]);
+
+        ws_stride[i] = plane_widths[i];
+        ws_size[i] = ws_stride[i] * plane_heights[i] * sizeof(float);
+        ws_total_size += ws_size[i];
+    }
+
+    /* Buffers */
+    err = ff_vk_get_pooled_buffer(&s->vkctx, &s->integral_buf_pool, &integral_buf,
+                                  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
+                                  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
+                                  NULL,
+                                  s->opts.t * int_size,
+                                  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+    if (err < 0)
+        return err;
+    integral_vk = (FFVkBuffer *)integral_buf->data;
+
+    err = ff_vk_get_pooled_buffer(&s->vkctx, &s->ws_buf_pool, &ws_buf,
+                                  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
+                                  VK_BUFFER_USAGE_TRANSFER_DST_BIT |
+                                  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
+                                  NULL,
+                                  ws_total_size * 2,
+                                  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+    if (err < 0)
+        return err;
+    ws_vk = (FFVkBuffer *)ws_buf->data;
+
+    weights_offs[0] = 0;
+    sums_offs[0] = ws_total_size;
+    for (int i = 1; i < desc->nb_components; i++) {
+        weights_offs[i] = weights_offs[i - 1] + ws_size[i - 1];
+        sums_offs[i] = sums_offs[i - 1] + ws_size[i - 1];
+    }
+
+    /* Output frame */
+    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!out) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    /* Execution context */
+    exec = ff_vk_exec_get(&s->vkctx, &s->e);
+    ff_vk_exec_start(vkctx, exec);
+
+    /* Dependencies */
+    RET(ff_vk_exec_add_dep_frame(vkctx, exec, in,
+                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
+    RET(ff_vk_exec_add_dep_frame(vkctx, exec, out,
+                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
+
+    RET(ff_vk_exec_add_dep_buf(vkctx, exec, &integral_buf, 1, 0));
+    integral_buf = NULL;
+
+    RET(ff_vk_exec_add_dep_buf(vkctx, exec, &ws_buf,       1, 0));
+    ws_buf = NULL;
+
+    /* Input frame prep */
+    RET(ff_vk_create_imageviews(vkctx, exec, in_views, in, FF_VK_REP_FLOAT));
+    ff_vk_frame_barrier(vkctx, exec, in, img_bar, &nb_img_bar,
+                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                        VK_ACCESS_SHADER_READ_BIT,
+                        VK_IMAGE_LAYOUT_GENERAL,
+                        VK_QUEUE_FAMILY_IGNORED);
+
+    /* Output frame prep */
+    RET(ff_vk_create_imageviews(vkctx, exec, out_views, out, FF_VK_REP_FLOAT));
+    ff_vk_frame_barrier(vkctx, exec, out, img_bar, &nb_img_bar,
+                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                        VK_ACCESS_SHADER_WRITE_BIT,
+                        VK_IMAGE_LAYOUT_GENERAL,
+                        VK_QUEUE_FAMILY_IGNORED);
+
+    nb_buf_bar = 0;
+    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
+        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+        .srcStageMask = ws_vk->stage,
+        .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
+        .srcAccessMask = ws_vk->access,
+        .dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
+        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .buffer = ws_vk->buf,
+        .size = ws_vk->size,
+        .offset = 0,
+    };
+    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
+        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+        .srcStageMask = integral_vk->stage,
+        .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+        .srcAccessMask = integral_vk->access,
+        .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
+                         VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
+        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .buffer = integral_vk->buf,
+        .size = integral_vk->size,
+        .offset = 0,
+    };
+
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+            .pImageMemoryBarriers = img_bar,
+            .imageMemoryBarrierCount = nb_img_bar,
+            .pBufferMemoryBarriers = buf_bar,
+            .bufferMemoryBarrierCount = nb_buf_bar,
+        });
+    ws_vk->stage = buf_bar[0].dstStageMask;
+    ws_vk->access = buf_bar[0].dstAccessMask;
+    integral_vk->stage = buf_bar[1].dstStageMask;
+    integral_vk->access = buf_bar[1].dstAccessMask;
+
+    /* Buffer zeroing */
+    vk->CmdFillBuffer(exec->buf, ws_vk->buf, 0, ws_vk->size, 0x0);
+
+    nb_buf_bar = 0;
+    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
+        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+        .srcStageMask = ws_vk->stage,
+        .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+        .srcAccessMask = ws_vk->access,
+        .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
+                         VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
+        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .buffer = ws_vk->buf,
+        .size = ws_vk->size,
+        .offset = 0,
+    };
+
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+            .pBufferMemoryBarriers = buf_bar,
+            .bufferMemoryBarrierCount = nb_buf_bar,
+        });
+    ws_vk->stage = buf_bar[0].dstStageMask;
+    ws_vk->access = buf_bar[0].dstAccessMask;
+
+    /* Update weights descriptors */
+    ff_vk_shader_update_img_array(vkctx, exec, &s->shd_weights, in, in_views, 0, 0,
+                                  VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
+    for (int i = 0; i < desc->nb_components; i++) {
+        RET(ff_vk_shader_update_desc_buffer(&s->vkctx, exec, &s->shd_weights, 0, 1 + i*2 + 0, 0,
+                                            ws_vk, weights_offs[i], ws_size[i],
+                                            VK_FORMAT_UNDEFINED));
+        RET(ff_vk_shader_update_desc_buffer(&s->vkctx, exec, &s->shd_weights, 0, 1 + i*2 + 1, 0,
+                                            ws_vk, sums_offs[i], ws_size[i],
+                                            VK_FORMAT_UNDEFINED));
+    }
+
+    /* Update denoise descriptors */
+    ff_vk_shader_update_img_array(vkctx, exec, &s->shd_denoise, in, in_views, 0, 0,
+                                  VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
+    ff_vk_shader_update_img_array(vkctx, exec, &s->shd_denoise, out, out_views, 0, 1,
+                                  VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
+    for (int i = 0; i < desc->nb_components; i++) {
+        RET(ff_vk_shader_update_desc_buffer(&s->vkctx, exec, &s->shd_denoise, 1, i*2 + 0, 0,
+                                            ws_vk, weights_offs[i], ws_size[i],
+                                            VK_FORMAT_UNDEFINED));
+        RET(ff_vk_shader_update_desc_buffer(&s->vkctx, exec, &s->shd_denoise, 1, i*2 + 1, 0,
+                                            ws_vk, sums_offs[i], ws_size[i],
+                                            VK_FORMAT_UNDEFINED));
+    }
+
+    /* Weights pipeline */
+    ff_vk_exec_bind_shader(vkctx, exec, &s->shd_weights);
+
+    do {
+        int wg_invoc;
+        HorizontalPushData pd = {
+            { plane_widths[0], plane_widths[1], plane_widths[2], plane_widths[3] },
+            { plane_heights[0], plane_heights[1], plane_heights[2], plane_heights[3] },
+            { ws_stride[0], ws_stride[1], ws_stride[2], ws_stride[3] },
+            { s->patch[0], s->patch[1], s->patch[2], s->patch[3] },
+            { s->strength[0], s->strength[1], s->strength[2], s->strength[2], },
+            integral_vk->address,
+            (uint64_t)int_size,
+            (uint64_t)int_stride,
+            offsets_dispatched,
+        };
+
+        /* Push data */
+        ff_vk_shader_update_push_const(vkctx, exec, &s->shd_weights,
+                                       VK_SHADER_STAGE_COMPUTE_BIT,
+                                       0, sizeof(pd), &pd);
+
+        if (offsets_dispatched) {
+            nb_buf_bar = 0;
+            buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
+                .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+                .srcStageMask = integral_vk->stage,
+                .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                .srcAccessMask = integral_vk->access,
+                .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
+                                 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
+                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                .buffer = integral_vk->buf,
+                .size = integral_vk->size,
+                .offset = 0,
+            };
+
+            vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+                    .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+                    .pBufferMemoryBarriers = buf_bar,
+                    .bufferMemoryBarrierCount = nb_buf_bar,
+                });
+            integral_vk->stage = buf_bar[1].dstStageMask;
+            integral_vk->access = buf_bar[1].dstAccessMask;
+        }
+
+        wg_invoc = FFMIN((s->nb_offsets - offsets_dispatched)/TYPE_ELEMS, s->opts.t);
+        wg_invoc = FFMIN(wg_invoc, vkctx->props.properties.limits.maxComputeWorkGroupCount[2]);
+
+        /* End of horizontal pass */
+        vk->CmdDispatch(exec->buf, 1, 1, wg_invoc);
+
+        offsets_dispatched += wg_invoc * TYPE_ELEMS;
+    } while (offsets_dispatched < s->nb_offsets);
+
+    RET(denoise_pass(s, exec, ws_vk, ws_stride));
+
+    err = ff_vk_exec_submit(vkctx, exec);
+    if (err < 0)
+        return err;
+
+    err = av_frame_copy_props(out, in);
+    if (err < 0)
+        goto fail;
+
+    av_frame_free(&in);
+
+    return ff_filter_frame(outlink, out);
+
+fail:
+    av_buffer_unref(&integral_buf);
+    av_buffer_unref(&ws_buf);
+    av_frame_free(&in);
+    av_frame_free(&out);
+    return err;
+}
+
+static void nlmeans_vulkan_uninit(AVFilterContext *avctx)
+{
+    NLMeansVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+
+    ff_vk_exec_pool_free(vkctx, &s->e);
+    ff_vk_shader_free(vkctx, &s->shd_weights);
+    ff_vk_shader_free(vkctx, &s->shd_denoise);
+
+    av_buffer_pool_uninit(&s->integral_buf_pool);
+    av_buffer_pool_uninit(&s->ws_buf_pool);
+
+    ff_vk_uninit(&s->vkctx);
+
+    av_freep(&s->xoffsets);
+    av_freep(&s->yoffsets);
+
+    s->initialized = 0;
+}
+
+#define OFFSET(x) offsetof(NLMeansVulkanContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
+static const AVOption nlmeans_vulkan_options[] = {
+    { "s",  "denoising strength for all components", OFFSET(opts.s), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 1.0, 100.0, FLAGS },
+    { "p",  "patch size for all components", OFFSET(opts.p), AV_OPT_TYPE_INT, { .i64 = 3*2+1 }, 0, 99, FLAGS },
+    { "r",  "research window radius", OFFSET(opts.r), AV_OPT_TYPE_INT, { .i64 = 7*2+1 }, 0, 99, FLAGS },
+    { "t",  "parallelism", OFFSET(opts.t), AV_OPT_TYPE_INT, { .i64 = 36 }, 1, 168, FLAGS },
+
+    { "s1", "denoising strength for component 1", OFFSET(opts.sc[0]), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 1.0, 100.0, FLAGS },
+    { "s2", "denoising strength for component 2", OFFSET(opts.sc[1]), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 1.0, 100.0, FLAGS },
+    { "s3", "denoising strength for component 3", OFFSET(opts.sc[2]), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 1.0, 100.0, FLAGS },
+    { "s4", "denoising strength for component 4", OFFSET(opts.sc[3]), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 1.0, 100.0, FLAGS },
+
+    { "p1", "patch size for component 1", OFFSET(opts.pc[0]), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 99, FLAGS },
+    { "p2", "patch size for component 2", OFFSET(opts.pc[1]), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 99, FLAGS },
+    { "p3", "patch size for component 3", OFFSET(opts.pc[2]), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 99, FLAGS },
+    { "p4", "patch size for component 4", OFFSET(opts.pc[3]), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 99, FLAGS },
+
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(nlmeans_vulkan);
+
+static const AVFilterPad nlmeans_vulkan_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = &nlmeans_vulkan_filter_frame,
+        .config_props = &ff_vk_filter_config_input,
+    },
+};
+
+static const AVFilterPad nlmeans_vulkan_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_VIDEO,
+        .config_props = &ff_vk_filter_config_output,
+    },
+};
+
+const FFFilter ff_vf_nlmeans_vulkan = {
+    .p.name         = "nlmeans_vulkan",
+    .p.description  = NULL_IF_CONFIG_SMALL("Non-local means denoiser (Vulkan)"),
+    .p.priv_class   = &nlmeans_vulkan_class,
+    .p.flags        = AVFILTER_FLAG_HWDEVICE,
+    .priv_size      = sizeof(NLMeansVulkanContext),
+    .init           = &ff_vk_filter_init,
+    .uninit         = &nlmeans_vulkan_uninit,
+    FILTER_INPUTS(nlmeans_vulkan_inputs),
+    FILTER_OUTPUTS(nlmeans_vulkan_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};
-- 
2.49.1


From dce5b25f4dc18874a41e6a56777ae09d2f459553 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:58:31 +0000
Subject: [PATCH 019/118] Changing vulkan file directory

---
 libavfilter/vf_overlay_vulkan.c | 347 --------------------------------
 1 file changed, 347 deletions(-)
 delete mode 100644 libavfilter/vf_overlay_vulkan.c

diff --git a/libavfilter/vf_overlay_vulkan.c b/libavfilter/vf_overlay_vulkan.c
deleted file mode 100644
index 1f9eed8e08..0000000000
--- a/libavfilter/vf_overlay_vulkan.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Copyright (c) Lynne
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/random_seed.h"
-#include "libavutil/opt.h"
-#include "libavutil/vulkan_spirv.h"
-#include "vulkan_filter.h"
-
-#include "filters.h"
-#include "framesync.h"
-#include "video.h"
-
-typedef struct OverlayVulkanContext {
-    FFVulkanContext vkctx;
-    FFFrameSync fs;
-
-    int initialized;
-    FFVkExecPool e;
-    AVVulkanDeviceQueueFamily *qf;
-    FFVulkanShader shd;
-
-    /* Push constants / options */
-    struct {
-        int32_t o_offset[2*3];
-        int32_t o_size[2*3];
-    } opts;
-
-    int overlay_x;
-    int overlay_y;
-    int overlay_w;
-    int overlay_h;
-} OverlayVulkanContext;
-
-static const char overlay_noalpha[] = {
-    C(0, void overlay_noalpha(int i, ivec2 pos)                                )
-    C(0, {                                                                     )
-    C(1,     if ((o_offset[i].x <= pos.x) && (o_offset[i].y <= pos.y) &&
-                 (pos.x < (o_offset[i].x + o_size[i].x)) &&
-                 (pos.y < (o_offset[i].y + o_size[i].y))) {                    )
-    C(2,         vec4 res = imageLoad(overlay_img[i], pos - o_offset[i]);      )
-    C(2,         imageStore(output_img[i], pos, res);                          )
-    C(1,     } else {                                                          )
-    C(2,         vec4 res = imageLoad(main_img[i], pos);                       )
-    C(2,         imageStore(output_img[i], pos, res);                          )
-    C(1,     }                                                                 )
-    C(0, }                                                                     )
-};
-
-static const char overlay_alpha[] = {
-    C(0, void overlay_alpha_opaque(int i, ivec2 pos)                           )
-    C(0, {                                                                     )
-    C(1,     vec4 res = imageLoad(main_img[i], pos);                           )
-    C(1,     if ((o_offset[i].x <= pos.x) && (o_offset[i].y <= pos.y) &&
-                 (pos.x < (o_offset[i].x + o_size[i].x)) &&
-                 (pos.y < (o_offset[i].y + o_size[i].y))) {                    )
-    C(2,         vec4 ovr = imageLoad(overlay_img[i], pos - o_offset[i]);      )
-    C(2,         res = ovr * ovr.a + res * (1.0f - ovr.a);                     )
-    C(2,         res.a = 1.0f;                                                 )
-    C(2,         imageStore(output_img[i], pos, res);                          )
-    C(1,     }                                                                 )
-    C(1,     imageStore(output_img[i], pos, res);                              )
-    C(0, }                                                                     )
-};
-
-static av_cold int init_filter(AVFilterContext *ctx)
-{
-    int err;
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    OverlayVulkanContext *s = ctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
-    const int ialpha = av_pix_fmt_desc_get(s->vkctx.input_format)->flags & AV_PIX_FMT_FLAG_ALPHA;
-    const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(s->vkctx.output_format);
-    FFVulkanShader *shd = &s->shd;
-    FFVkSPIRVCompiler *spv;
-    FFVulkanDescriptorSetBinding *desc;
-
-    spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
-    if (!s->qf) {
-        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
-        err = AVERROR(ENOTSUP);
-        goto fail;
-    }
-
-    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
-    RET(ff_vk_shader_init(vkctx, &s->shd, "overlay",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          NULL, 0,
-                          32, 32, 1,
-                          0));
-
-    GLSLC(0, layout(push_constant, std430) uniform pushConstants {        );
-    GLSLC(1,    ivec2 o_offset[3];                                        );
-    GLSLC(1,    ivec2 o_size[3];                                          );
-    GLSLC(0, };                                                           );
-    GLSLC(0,                                                              );
-
-    ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts),
-                                VK_SHADER_STAGE_COMPUTE_BIT);
-
-    desc = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name       = "main_img",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "readonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-        {
-            .name       = "overlay_img",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "readonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-        {
-            .name       = "output_img",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "writeonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 3, 0, 0));
-
-    GLSLD(   overlay_noalpha                                              );
-    GLSLD(   overlay_alpha                                                );
-    GLSLC(0, void main()                                                  );
-    GLSLC(0, {                                                            );
-    GLSLC(1,     ivec2 pos = ivec2(gl_GlobalInvocationID.xy);             );
-    GLSLF(1,     int planes = %i;                                  ,planes);
-    GLSLC(1,     for (int i = 0; i < planes; i++) {                       );
-    if (ialpha)
-        GLSLC(2,         overlay_alpha_opaque(i, pos);                    );
-    else
-        GLSLC(2,         overlay_noalpha(i, pos);                         );
-    GLSLC(1,     }                                                        );
-    GLSLC(0, }                                                            );
-
-    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
-
-    s->opts.o_offset[0] = s->overlay_x;
-    s->opts.o_offset[1] = s->overlay_y;
-    s->opts.o_offset[2] = s->opts.o_offset[0] >> pix_desc->log2_chroma_w;
-    s->opts.o_offset[3] = s->opts.o_offset[1] >> pix_desc->log2_chroma_h;
-    s->opts.o_offset[4] = s->opts.o_offset[0] >> pix_desc->log2_chroma_w;
-    s->opts.o_offset[5] = s->opts.o_offset[1] >> pix_desc->log2_chroma_h;
-
-    s->opts.o_size[0] = s->overlay_w;
-    s->opts.o_size[1] = s->overlay_h;
-    s->opts.o_size[2] = s->opts.o_size[0] >> pix_desc->log2_chroma_w;
-    s->opts.o_size[3] = s->opts.o_size[1] >> pix_desc->log2_chroma_h;
-    s->opts.o_size[4] = s->opts.o_size[0] >> pix_desc->log2_chroma_w;
-    s->opts.o_size[5] = s->opts.o_size[1] >> pix_desc->log2_chroma_h;
-
-    s->initialized = 1;
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-    if (spv)
-        spv->uninit(&spv);
-
-    return err;
-}
-
-static int overlay_vulkan_blend(FFFrameSync *fs)
-{
-    int err;
-    AVFilterContext *ctx = fs->parent;
-    OverlayVulkanContext *s = ctx->priv;
-    AVFilterLink *outlink = ctx->outputs[0];
-    AVFrame *input_main, *input_overlay, *out;
-
-    err = ff_framesync_get_frame(fs, 0, &input_main, 0);
-    if (err < 0)
-        goto fail;
-    err = ff_framesync_get_frame(fs, 1, &input_overlay, 0);
-    if (err < 0)
-        goto fail;
-
-    if (!input_main || !input_overlay)
-        return 0;
-
-    if (!s->initialized) {
-        AVHWFramesContext *main_fc = (AVHWFramesContext*)input_main->hw_frames_ctx->data;
-        AVHWFramesContext *overlay_fc = (AVHWFramesContext*)input_overlay->hw_frames_ctx->data;
-        if (main_fc->sw_format != overlay_fc->sw_format) {
-            av_log(ctx, AV_LOG_ERROR, "Mismatching sw formats!\n");
-            return AVERROR(EINVAL);
-        }
-
-        s->overlay_w = input_overlay->width;
-        s->overlay_h = input_overlay->height;
-
-        RET(init_filter(ctx));
-    }
-
-    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-    if (!out) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    RET(ff_vk_filter_process_Nin(&s->vkctx, &s->e, &s->shd,
-                                 out, (AVFrame *[]){ input_main, input_overlay }, 2,
-                                 VK_NULL_HANDLE, &s->opts, sizeof(s->opts)));
-
-    err = av_frame_copy_props(out, input_main);
-    if (err < 0)
-        goto fail;
-
-    return ff_filter_frame(outlink, out);
-
-fail:
-    av_frame_free(&out);
-    return err;
-}
-
-static int overlay_vulkan_config_output(AVFilterLink *outlink)
-{
-    int err;
-    AVFilterContext *avctx = outlink->src;
-    OverlayVulkanContext *s = avctx->priv;
-
-    err = ff_vk_filter_config_output(outlink);
-    if (err < 0)
-        return err;
-
-    err = ff_framesync_init_dualinput(&s->fs, avctx);
-    if (err < 0)
-        return err;
-
-    return ff_framesync_configure(&s->fs);
-}
-
-static int overlay_vulkan_activate(AVFilterContext *avctx)
-{
-    OverlayVulkanContext *s = avctx->priv;
-
-    return ff_framesync_activate(&s->fs);
-}
-
-static av_cold int overlay_vulkan_init(AVFilterContext *avctx)
-{
-    OverlayVulkanContext *s = avctx->priv;
-
-    s->fs.on_event = &overlay_vulkan_blend;
-
-    return ff_vk_filter_init(avctx);
-}
-
-static void overlay_vulkan_uninit(AVFilterContext *avctx)
-{
-    OverlayVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-
-    ff_vk_exec_pool_free(vkctx, &s->e);
-    ff_vk_shader_free(vkctx, &s->shd);
-
-    ff_vk_uninit(&s->vkctx);
-    ff_framesync_uninit(&s->fs);
-
-    s->initialized = 0;
-}
-
-#define OFFSET(x) offsetof(OverlayVulkanContext, x)
-#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
-static const AVOption overlay_vulkan_options[] = {
-    { "x", "Set horizontal offset", OFFSET(overlay_x), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, .flags = FLAGS },
-    { "y", "Set vertical offset",   OFFSET(overlay_y), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, .flags = FLAGS },
-    { NULL },
-};
-
-AVFILTER_DEFINE_CLASS(overlay_vulkan);
-
-static const AVFilterPad overlay_vulkan_inputs[] = {
-    {
-        .name         = "main",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .config_props = &ff_vk_filter_config_input,
-    },
-    {
-        .name         = "overlay",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .config_props = &ff_vk_filter_config_input,
-    },
-};
-
-static const AVFilterPad overlay_vulkan_outputs[] = {
-    {
-        .name = "default",
-        .type = AVMEDIA_TYPE_VIDEO,
-        .config_props = &overlay_vulkan_config_output,
-    },
-};
-
-const FFFilter ff_vf_overlay_vulkan = {
-    .p.name         = "overlay_vulkan",
-    .p.description  = NULL_IF_CONFIG_SMALL("Overlay a source on top of another"),
-    .p.priv_class   = &overlay_vulkan_class,
-    .p.flags        = AVFILTER_FLAG_HWDEVICE,
-    .priv_size      = sizeof(OverlayVulkanContext),
-    .init           = &overlay_vulkan_init,
-    .uninit         = &overlay_vulkan_uninit,
-    .activate       = &overlay_vulkan_activate,
-    FILTER_INPUTS(overlay_vulkan_inputs),
-    FILTER_OUTPUTS(overlay_vulkan_outputs),
-    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
-    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
-};
-- 
2.49.1


From 70bc9416a459885aa3a6bc8d5072126bc34ddb2a Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:59:04 +0000
Subject: [PATCH 020/118] Changing vulkan file directory

---
 libavfilter/vulkan/vf_overlay_vulkan.c | 347 +++++++++++++++++++++++++
 1 file changed, 347 insertions(+)
 create mode 100644 libavfilter/vulkan/vf_overlay_vulkan.c

diff --git a/libavfilter/vulkan/vf_overlay_vulkan.c b/libavfilter/vulkan/vf_overlay_vulkan.c
new file mode 100644
index 0000000000..05fc06c84e
--- /dev/null
+++ b/libavfilter/vulkan/vf_overlay_vulkan.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) Lynne
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/random_seed.h"
+#include "libavutil/opt.h"
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+#include "vulkan_filter.h"
+
+#include "libavfilter/filters.h"
+#include "libavfilter/framesync.h"
+#include "libavfilter/video.h"
+
+typedef struct OverlayVulkanContext {
+    FFVulkanContext vkctx;
+    FFFrameSync fs;
+
+    int initialized;
+    FFVkExecPool e;
+    AVVulkanDeviceQueueFamily *qf;
+    FFVulkanShader shd;
+
+    /* Push constants / options */
+    struct {
+        int32_t o_offset[2*3];
+        int32_t o_size[2*3];
+    } opts;
+
+    int overlay_x;
+    int overlay_y;
+    int overlay_w;
+    int overlay_h;
+} OverlayVulkanContext;
+
+static const char overlay_noalpha[] = {
+    C(0, void overlay_noalpha(int i, ivec2 pos)                                )
+    C(0, {                                                                     )
+    C(1,     if ((o_offset[i].x <= pos.x) && (o_offset[i].y <= pos.y) &&
+                 (pos.x < (o_offset[i].x + o_size[i].x)) &&
+                 (pos.y < (o_offset[i].y + o_size[i].y))) {                    )
+    C(2,         vec4 res = imageLoad(overlay_img[i], pos - o_offset[i]);      )
+    C(2,         imageStore(output_img[i], pos, res);                          )
+    C(1,     } else {                                                          )
+    C(2,         vec4 res = imageLoad(main_img[i], pos);                       )
+    C(2,         imageStore(output_img[i], pos, res);                          )
+    C(1,     }                                                                 )
+    C(0, }                                                                     )
+};
+
+static const char overlay_alpha[] = {
+    C(0, void overlay_alpha_opaque(int i, ivec2 pos)                           )
+    C(0, {                                                                     )
+    C(1,     vec4 res = imageLoad(main_img[i], pos);                           )
+    C(1,     if ((o_offset[i].x <= pos.x) && (o_offset[i].y <= pos.y) &&
+                 (pos.x < (o_offset[i].x + o_size[i].x)) &&
+                 (pos.y < (o_offset[i].y + o_size[i].y))) {                    )
+    C(2,         vec4 ovr = imageLoad(overlay_img[i], pos - o_offset[i]);      )
+    C(2,         res = ovr * ovr.a + res * (1.0f - ovr.a);                     )
+    C(2,         res.a = 1.0f;                                                 )
+    C(2,         imageStore(output_img[i], pos, res);                          )
+    C(1,     }                                                                 )
+    C(1,     imageStore(output_img[i], pos, res);                              )
+    C(0, }                                                                     )
+};
+
+static av_cold int init_filter(AVFilterContext *ctx)
+{
+    int err;
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    OverlayVulkanContext *s = ctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
+    const int ialpha = av_pix_fmt_desc_get(s->vkctx.input_format)->flags & AV_PIX_FMT_FLAG_ALPHA;
+    const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(s->vkctx.output_format);
+    FFVulkanShader *shd = &s->shd;
+    FFVkSPIRVCompiler *spv;
+    FFVulkanDescriptorSetBinding *desc;
+
+    spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
+    if (!s->qf) {
+        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
+        err = AVERROR(ENOTSUP);
+        goto fail;
+    }
+
+    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
+    RET(ff_vk_shader_init(vkctx, &s->shd, "overlay",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          NULL, 0,
+                          32, 32, 1,
+                          0));
+
+    GLSLC(0, layout(push_constant, std430) uniform pushConstants {        );
+    GLSLC(1,    ivec2 o_offset[3];                                        );
+    GLSLC(1,    ivec2 o_size[3];                                          );
+    GLSLC(0, };                                                           );
+    GLSLC(0,                                                              );
+
+    ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts),
+                                VK_SHADER_STAGE_COMPUTE_BIT);
+
+    desc = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name       = "main_img",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "readonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+        {
+            .name       = "overlay_img",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "readonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+        {
+            .name       = "output_img",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "writeonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 3, 0, 0));
+
+    GLSLD(   overlay_noalpha                                              );
+    GLSLD(   overlay_alpha                                                );
+    GLSLC(0, void main()                                                  );
+    GLSLC(0, {                                                            );
+    GLSLC(1,     ivec2 pos = ivec2(gl_GlobalInvocationID.xy);             );
+    GLSLF(1,     int planes = %i;                                  ,planes);
+    GLSLC(1,     for (int i = 0; i < planes; i++) {                       );
+    if (ialpha)
+        GLSLC(2,         overlay_alpha_opaque(i, pos);                    );
+    else
+        GLSLC(2,         overlay_noalpha(i, pos);                         );
+    GLSLC(1,     }                                                        );
+    GLSLC(0, }                                                            );
+
+    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
+
+    s->opts.o_offset[0] = s->overlay_x;
+    s->opts.o_offset[1] = s->overlay_y;
+    s->opts.o_offset[2] = s->opts.o_offset[0] >> pix_desc->log2_chroma_w;
+    s->opts.o_offset[3] = s->opts.o_offset[1] >> pix_desc->log2_chroma_h;
+    s->opts.o_offset[4] = s->opts.o_offset[0] >> pix_desc->log2_chroma_w;
+    s->opts.o_offset[5] = s->opts.o_offset[1] >> pix_desc->log2_chroma_h;
+
+    s->opts.o_size[0] = s->overlay_w;
+    s->opts.o_size[1] = s->overlay_h;
+    s->opts.o_size[2] = s->opts.o_size[0] >> pix_desc->log2_chroma_w;
+    s->opts.o_size[3] = s->opts.o_size[1] >> pix_desc->log2_chroma_h;
+    s->opts.o_size[4] = s->opts.o_size[0] >> pix_desc->log2_chroma_w;
+    s->opts.o_size[5] = s->opts.o_size[1] >> pix_desc->log2_chroma_h;
+
+    s->initialized = 1;
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+    if (spv)
+        spv->uninit(&spv);
+
+    return err;
+}
+
+static int overlay_vulkan_blend(FFFrameSync *fs)
+{
+    int err;
+    AVFilterContext *ctx = fs->parent;
+    OverlayVulkanContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+    AVFrame *input_main, *input_overlay, *out;
+
+    err = ff_framesync_get_frame(fs, 0, &input_main, 0);
+    if (err < 0)
+        goto fail;
+    err = ff_framesync_get_frame(fs, 1, &input_overlay, 0);
+    if (err < 0)
+        goto fail;
+
+    if (!input_main || !input_overlay)
+        return 0;
+
+    if (!s->initialized) {
+        AVHWFramesContext *main_fc = (AVHWFramesContext*)input_main->hw_frames_ctx->data;
+        AVHWFramesContext *overlay_fc = (AVHWFramesContext*)input_overlay->hw_frames_ctx->data;
+        if (main_fc->sw_format != overlay_fc->sw_format) {
+            av_log(ctx, AV_LOG_ERROR, "Mismatching sw formats!\n");
+            return AVERROR(EINVAL);
+        }
+
+        s->overlay_w = input_overlay->width;
+        s->overlay_h = input_overlay->height;
+
+        RET(init_filter(ctx));
+    }
+
+    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!out) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    RET(ff_vk_filter_process_Nin(&s->vkctx, &s->e, &s->shd,
+                                 out, (AVFrame *[]){ input_main, input_overlay }, 2,
+                                 VK_NULL_HANDLE, &s->opts, sizeof(s->opts)));
+
+    err = av_frame_copy_props(out, input_main);
+    if (err < 0)
+        goto fail;
+
+    return ff_filter_frame(outlink, out);
+
+fail:
+    av_frame_free(&out);
+    return err;
+}
+
+static int overlay_vulkan_config_output(AVFilterLink *outlink)
+{
+    int err;
+    AVFilterContext *avctx = outlink->src;
+    OverlayVulkanContext *s = avctx->priv;
+
+    err = ff_vk_filter_config_output(outlink);
+    if (err < 0)
+        return err;
+
+    err = ff_framesync_init_dualinput(&s->fs, avctx);
+    if (err < 0)
+        return err;
+
+    return ff_framesync_configure(&s->fs);
+}
+
+static int overlay_vulkan_activate(AVFilterContext *avctx)
+{
+    OverlayVulkanContext *s = avctx->priv;
+
+    return ff_framesync_activate(&s->fs);
+}
+
+static av_cold int overlay_vulkan_init(AVFilterContext *avctx)
+{
+    OverlayVulkanContext *s = avctx->priv;
+
+    s->fs.on_event = &overlay_vulkan_blend;
+
+    return ff_vk_filter_init(avctx);
+}
+
+static void overlay_vulkan_uninit(AVFilterContext *avctx)
+{
+    OverlayVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+
+    ff_vk_exec_pool_free(vkctx, &s->e);
+    ff_vk_shader_free(vkctx, &s->shd);
+
+    ff_vk_uninit(&s->vkctx);
+    ff_framesync_uninit(&s->fs);
+
+    s->initialized = 0;
+}
+
+#define OFFSET(x) offsetof(OverlayVulkanContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
+static const AVOption overlay_vulkan_options[] = {
+    { "x", "Set horizontal offset", OFFSET(overlay_x), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, .flags = FLAGS },
+    { "y", "Set vertical offset",   OFFSET(overlay_y), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, .flags = FLAGS },
+    { NULL },
+};
+
+AVFILTER_DEFINE_CLASS(overlay_vulkan);
+
+static const AVFilterPad overlay_vulkan_inputs[] = {
+    {
+        .name         = "main",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = &ff_vk_filter_config_input,
+    },
+    {
+        .name         = "overlay",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = &ff_vk_filter_config_input,
+    },
+};
+
+static const AVFilterPad overlay_vulkan_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_VIDEO,
+        .config_props = &overlay_vulkan_config_output,
+    },
+};
+
+const FFFilter ff_vf_overlay_vulkan = {
+    .p.name         = "overlay_vulkan",
+    .p.description  = NULL_IF_CONFIG_SMALL("Overlay a source on top of another"),
+    .p.priv_class   = &overlay_vulkan_class,
+    .p.flags        = AVFILTER_FLAG_HWDEVICE,
+    .priv_size      = sizeof(OverlayVulkanContext),
+    .init           = &overlay_vulkan_init,
+    .uninit         = &overlay_vulkan_uninit,
+    .activate       = &overlay_vulkan_activate,
+    FILTER_INPUTS(overlay_vulkan_inputs),
+    FILTER_OUTPUTS(overlay_vulkan_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};
-- 
2.49.1


From 8457b1cdc40e7fa03280de856b6c6ea526331b7e Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 12:59:52 +0000
Subject: [PATCH 021/118] Changing vulkan file directory

---
 libavfilter/vf_scale_vulkan.c | 508 ----------------------------------
 1 file changed, 508 deletions(-)
 delete mode 100644 libavfilter/vf_scale_vulkan.c

diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c
deleted file mode 100644
index c23cfe262f..0000000000
--- a/libavfilter/vf_scale_vulkan.c
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- * Copyright (c) Lynne
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/random_seed.h"
-#include "libavutil/opt.h"
-#include "libavutil/vulkan_spirv.h"
-#include "vulkan_filter.h"
-#include "scale_eval.h"
-#include "filters.h"
-#include "colorspace.h"
-#include "video.h"
-
-extern const char *ff_source_debayer_comp;
-
-enum ScalerFunc {
-    F_BILINEAR = 0,
-    F_NEAREST,
-
-    F_NB,
-};
-
-enum DebayerFunc {
-    DB_BILINEAR = 0,
-    DB_BILINEAR_HQ,
-
-    DB_NB,
-};
-
-typedef struct ScaleVulkanContext {
-    FFVulkanContext vkctx;
-
-    int initialized;
-    FFVkExecPool e;
-    AVVulkanDeviceQueueFamily *qf;
-    FFVulkanShader shd;
-    VkSampler sampler;
-
-    /* Push constants / options */
-    struct {
-        float yuv_matrix[4][4];
-        int crop_x;
-        int crop_y;
-        int crop_w;
-        int crop_h;
-    } opts;
-
-    char *out_format_string;
-    char *w_expr;
-    char *h_expr;
-
-    enum ScalerFunc scaler;
-    enum AVColorRange out_range;
-    enum DebayerFunc debayer;
-} ScaleVulkanContext;
-
-static const char scale_bilinear[] = {
-    C(0, vec4 scale_bilinear(int idx, ivec2 pos, vec2 crop_range, vec2 crop_off))
-    C(0, {                                                                      )
-    C(1,     vec2 npos = (vec2(pos) + 0.5f) / imageSize(output_img[idx]);       )
-    C(1,     npos *= crop_range;    /* Reduce the range */                      )
-    C(1,     npos += crop_off;      /* Offset the start */                      )
-    C(1,     return texture(input_img[idx], npos);                              )
-    C(0, }                                                                      )
-};
-
-static const char rgb2yuv[] = {
-    C(0, vec4 rgb2yuv(vec4 src, int fullrange)                                  )
-    C(0, {                                                                      )
-    C(1,     src *= yuv_matrix;                                                 )
-    C(1,     if (fullrange == 1) {                                              )
-    C(2,         src += vec4(0.0, 0.5, 0.5, 0.0);                               )
-    C(1,     } else {                                                           )
-    C(2,         src *= vec4(219.0 / 255.0, 224.0 / 255.0, 224.0 / 255.0, 1.0); )
-    C(2,         src += vec4(16.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0, 0.0);  )
-    C(1,     }                                                                  )
-    C(1,     return src;                                                        )
-    C(0, }                                                                      )
-};
-
-static const char write_nv12[] = {
-    C(0, void write_nv12(vec4 src, ivec2 pos)                                   )
-    C(0, {                                                                      )
-    C(1,     imageStore(output_img[0], pos, vec4(src.r, 0.0, 0.0, 0.0));        )
-    C(1,     pos /= ivec2(2);                                                   )
-    C(1,     imageStore(output_img[1], pos, vec4(src.g, src.b, 0.0, 0.0));      )
-    C(0, }                                                                      )
-};
-
-static const char write_420[] = {
-    C(0, void write_420(vec4 src, ivec2 pos)                                    )
-    C(0, {                                                                      )
-    C(1,     imageStore(output_img[0], pos, vec4(src.r, 0.0, 0.0, 0.0));        )
-    C(1,     pos /= ivec2(2);                                                   )
-    C(1,     imageStore(output_img[1], pos, vec4(src.g, 0.0, 0.0, 0.0));        )
-    C(1,     imageStore(output_img[2], pos, vec4(src.b, 0.0, 0.0, 0.0));        )
-    C(0, }                                                                      )
-};
-
-static const char write_444[] = {
-    C(0, void write_444(vec4 src, ivec2 pos)                                    )
-    C(0, {                                                                      )
-    C(1,     imageStore(output_img[0], pos, vec4(src.r, 0.0, 0.0, 0.0));        )
-    C(1,     imageStore(output_img[1], pos, vec4(src.g, 0.0, 0.0, 0.0));        )
-    C(1,     imageStore(output_img[2], pos, vec4(src.b, 0.0, 0.0, 0.0));        )
-    C(0, }                                                                      )
-};
-
-static int init_scale_shader(AVFilterContext *ctx, FFVulkanShader *shd,
-                             FFVulkanDescriptorSetBinding *desc, AVFrame *in)
-{
-    ScaleVulkanContext *s = ctx->priv;
-    GLSLD(   scale_bilinear                                                  );
-
-    if (s->vkctx.output_format != s->vkctx.input_format) {
-        GLSLD(   rgb2yuv                                                     );
-    }
-
-    switch (s->vkctx.output_format) {
-    case AV_PIX_FMT_NV12:    GLSLD(write_nv12); break;
-    case AV_PIX_FMT_YUV420P: GLSLD( write_420); break;
-    case AV_PIX_FMT_YUV444P: GLSLD( write_444); break;
-    default: break;
-    }
-
-    GLSLC(0, void main()                                                     );
-    GLSLC(0, {                                                               );
-    GLSLC(1,     ivec2 size;                                                 );
-    GLSLC(1,     ivec2 pos = ivec2(gl_GlobalInvocationID.xy);                );
-    GLSLF(1,     vec2 in_d = vec2(%i, %i);             ,in->width, in->height);
-    GLSLC(1,     vec2 c_r = vec2(crop_w, crop_h) / in_d;                     );
-    GLSLC(1,     vec2 c_o = vec2(crop_x, crop_y) / in_d;                     );
-    GLSLC(0,                                                                 );
-
-    if (s->vkctx.output_format == s->vkctx.input_format) {
-        for (int i = 0; i < desc[1].elems; i++) {
-            GLSLF(1,  size = imageSize(output_img[%i]);                    ,i);
-            GLSLC(1,  if (IS_WITHIN(pos, size)) {                            );
-            switch (s->scaler) {
-            case F_NEAREST:
-            case F_BILINEAR:
-                GLSLF(2, vec4 res = scale_bilinear(%i, pos, c_r, c_o);     ,i);
-                GLSLF(2, imageStore(output_img[%i], pos, res);             ,i);
-                break;
-            };
-            GLSLC(1, }                                                       );
-        }
-    } else {
-        GLSLC(1, vec4 res = scale_bilinear(0, pos, c_r, c_o);                );
-        GLSLF(1, res = rgb2yuv(res, %i);    ,s->out_range == AVCOL_RANGE_JPEG);
-        switch (s->vkctx.output_format) {
-        case AV_PIX_FMT_NV12:    GLSLC(1, write_nv12(res, pos); ); break;
-        case AV_PIX_FMT_YUV420P: GLSLC(1,  write_420(res, pos); ); break;
-        case AV_PIX_FMT_YUV444P: GLSLC(1,  write_444(res, pos); ); break;
-        default: return AVERROR(EINVAL);
-        }
-    }
-
-    GLSLC(0, }                                                               );
-
-    if (s->vkctx.output_format != s->vkctx.input_format) {
-        const AVLumaCoefficients *lcoeffs;
-        double tmp_mat[3][3];
-
-        lcoeffs = av_csp_luma_coeffs_from_avcsp(in->colorspace);
-        if (!lcoeffs) {
-            av_log(ctx, AV_LOG_ERROR, "Unsupported colorspace\n");
-            return AVERROR(EINVAL);
-        }
-
-        ff_fill_rgb2yuv_table(lcoeffs, tmp_mat);
-
-        for (int y = 0; y < 3; y++)
-            for (int x = 0; x < 3; x++)
-                s->opts.yuv_matrix[x][y] = tmp_mat[x][y];
-        s->opts.yuv_matrix[3][3] = 1.0;
-    }
-
-    return 0;
-}
-
-static int init_debayer_shader(ScaleVulkanContext *s, FFVulkanShader *shd,
-                               FFVulkanDescriptorSetBinding *desc, AVFrame *in)
-{
-    GLSLD(ff_source_debayer_comp);
-
-    GLSLC(0, void main(void));
-    GLSLC(0, {              );
-    if (s->debayer == DB_BILINEAR)
-        GLSLC(1, debayer_bilinear(););
-    else if (s->debayer == DB_BILINEAR_HQ)
-        GLSLC(1, debayer_bilinear_hq(););
-    GLSLC(0, }              );
-
-    shd->lg_size[0] <<= 1;
-    shd->lg_size[1] <<= 1;
-
-    return 0;
-}
-
-static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
-{
-    int err;
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    VkFilter sampler_mode;
-    ScaleVulkanContext *s = ctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    FFVulkanShader *shd = &s->shd;
-    FFVkSPIRVCompiler *spv;
-    FFVulkanDescriptorSetBinding *desc;
-
-    int debayer = s->vkctx.input_format == AV_PIX_FMT_BAYER_RGGB16;
-    int in_planes = av_pix_fmt_count_planes(s->vkctx.input_format);
-
-    switch (s->scaler) {
-    case F_NEAREST:
-        sampler_mode = VK_FILTER_NEAREST;
-        break;
-    case F_BILINEAR:
-        sampler_mode = VK_FILTER_LINEAR;
-        break;
-    };
-
-    spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
-    if (!s->qf) {
-        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
-        err = AVERROR(ENOTSUP);
-        goto fail;
-    }
-
-    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
-
-    if (!debayer)
-        RET(ff_vk_init_sampler(vkctx, &s->sampler, 0, sampler_mode));
-
-    RET(ff_vk_shader_init(vkctx, &s->shd, "scale",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          NULL, 0,
-                          32, 32, 1,
-                          0));
-
-    desc = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name       = "input_img",
-            .type       = debayer ?
-                          VK_DESCRIPTOR_TYPE_STORAGE_IMAGE :
-                          VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-            .mem_layout = debayer ?
-                          ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT) :
-                          NULL,
-            .mem_quali  = "readonly",
-            .dimensions = 2,
-            .elems      = in_planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-            .samplers   = DUP_SAMPLER(s->sampler),
-        },
-        {
-            .name       = "output_img",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "writeonly",
-            .dimensions = 2,
-            .elems      = av_pix_fmt_count_planes(s->vkctx.output_format),
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 2, 0, 0));
-
-    GLSLC(0, layout(push_constant, std430) uniform pushConstants {        );
-    GLSLC(1,    mat4 yuv_matrix;                                          );
-    GLSLC(1,    int crop_x;                                               );
-    GLSLC(1,    int crop_y;                                               );
-    GLSLC(1,    int crop_w;                                               );
-    GLSLC(1,    int crop_h;                                               );
-    GLSLC(0, };                                                           );
-    GLSLC(0,                                                              );
-
-    ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts),
-                                VK_SHADER_STAGE_COMPUTE_BIT);
-
-    if (debayer)
-        err = init_debayer_shader(s, shd, desc, in);
-    else
-        err = init_scale_shader(ctx, shd, desc, in);
-    if (err < 0)
-        goto fail;
-
-    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
-
-    s->initialized = 1;
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-    if (spv)
-        spv->uninit(&spv);
-
-    return err;
-}
-
-static int scale_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
-{
-    int err;
-    AVFilterContext *ctx = link->dst;
-    ScaleVulkanContext *s = ctx->priv;
-    AVFilterLink *outlink = ctx->outputs[0];
-
-    AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-    if (!out) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    if (!s->initialized)
-        RET(init_filter(ctx, in));
-
-    s->opts.crop_x = in->crop_left;
-    s->opts.crop_y = in->crop_top;
-    s->opts.crop_w = in->width - (in->crop_left + in->crop_right);
-    s->opts.crop_h = in->height - (in->crop_top + in->crop_bottom);
-
-    RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->shd, out, in,
-                                    s->sampler, &s->opts, sizeof(s->opts)));
-
-    err = av_frame_copy_props(out, in);
-    if (err < 0)
-        goto fail;
-
-    if (out->width != in->width || out->height != in->height) {
-        av_frame_side_data_remove_by_props(&out->side_data, &out->nb_side_data,
-                                           AV_SIDE_DATA_PROP_SIZE_DEPENDENT);
-    }
-
-    if (s->out_range != AVCOL_RANGE_UNSPECIFIED)
-        out->color_range = s->out_range;
-    if (s->vkctx.output_format != s->vkctx.input_format)
-        out->chroma_location = AVCHROMA_LOC_TOPLEFT;
-
-    av_frame_free(&in);
-
-    return ff_filter_frame(outlink, out);
-
-fail:
-    av_frame_free(&in);
-    av_frame_free(&out);
-    return err;
-}
-
-static int scale_vulkan_config_output(AVFilterLink *outlink)
-{
-    int err;
-    AVFilterContext *avctx = outlink->src;
-    ScaleVulkanContext *s  = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    AVFilterLink *inlink   = outlink->src->inputs[0];
-
-    err = ff_scale_eval_dimensions(s, s->w_expr, s->h_expr, inlink, outlink,
-                                   &vkctx->output_width,
-                                   &vkctx->output_height);
-    if (err < 0)
-        return err;
-
-    ff_scale_adjust_dimensions(inlink, &vkctx->output_width, &vkctx->output_height, 0, 1, 1.f);
-
-    outlink->w = vkctx->output_width;
-    outlink->h = vkctx->output_height;
-
-    if (s->out_format_string) {
-        s->vkctx.output_format = av_get_pix_fmt(s->out_format_string);
-        if (s->vkctx.output_format == AV_PIX_FMT_NONE) {
-            av_log(avctx, AV_LOG_ERROR, "Invalid output format.\n");
-            return AVERROR(EINVAL);
-        }
-    } else {
-        s->vkctx.output_format = s->vkctx.input_format;
-    }
-
-    if (s->vkctx.input_format == AV_PIX_FMT_BAYER_RGGB16) {
-        if (s->vkctx.output_format == s->vkctx.input_format) {
-            s->vkctx.output_format = AV_PIX_FMT_RGBA64;
-        } else if (!ff_vk_mt_is_np_rgb(s->vkctx.output_format)) {
-            av_log(avctx, AV_LOG_ERROR, "Unsupported output format for debayer\n");
-            return AVERROR(EINVAL);
-        }
-        if (inlink->w != outlink->w || inlink->w != outlink->w) {
-            av_log(avctx, AV_LOG_ERROR, "Scaling is not supported with debayering\n");
-            return AVERROR_PATCHWELCOME;
-        }
-    } else if (s->vkctx.output_format != s->vkctx.input_format) {
-        if (!ff_vk_mt_is_np_rgb(s->vkctx.input_format)) {
-            av_log(avctx, AV_LOG_ERROR, "Unsupported input format for conversion\n");
-            return AVERROR(EINVAL);
-        }
-        if (s->vkctx.output_format != AV_PIX_FMT_NV12 &&
-            s->vkctx.output_format != AV_PIX_FMT_YUV420P &&
-            s->vkctx.output_format != AV_PIX_FMT_YUV444P) {
-            av_log(avctx, AV_LOG_ERROR, "Unsupported output format\n");
-            return AVERROR(EINVAL);
-        }
-    } else if (s->out_range != AVCOL_RANGE_UNSPECIFIED) {
-        av_log(avctx, AV_LOG_ERROR, "Cannot change range without converting format\n");
-        return AVERROR(EINVAL);
-    }
-
-    return ff_vk_filter_config_output(outlink);
-}
-
-static void scale_vulkan_uninit(AVFilterContext *avctx)
-{
-    ScaleVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    FFVulkanFunctions *vk = &vkctx->vkfn;
-
-    ff_vk_exec_pool_free(vkctx, &s->e);
-    ff_vk_shader_free(vkctx, &s->shd);
-
-    if (s->sampler)
-        vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler,
-                           vkctx->hwctx->alloc);
-
-    ff_vk_uninit(&s->vkctx);
-
-    s->initialized = 0;
-}
-
-#define OFFSET(x) offsetof(ScaleVulkanContext, x)
-#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
-static const AVOption scale_vulkan_options[] = {
-    { "w", "Output video width",  OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = FLAGS },
-    { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = FLAGS },
-    { "scaler", "Scaler function", OFFSET(scaler), AV_OPT_TYPE_INT, {.i64 = F_BILINEAR}, 0, F_NB, .flags = FLAGS, .unit = "scaler" },
-        { "bilinear", "Bilinear interpolation (fastest)", 0, AV_OPT_TYPE_CONST, {.i64 = F_BILINEAR}, 0, 0, .flags = FLAGS, .unit = "scaler" },
-        { "nearest", "Nearest (useful for pixel art)", 0, AV_OPT_TYPE_CONST, {.i64 = F_NEAREST}, 0, 0, .flags = FLAGS, .unit = "scaler" },
-    { "debayer", "Debayer algorithm to use", OFFSET(debayer), AV_OPT_TYPE_INT, {.i64 = DB_BILINEAR_HQ}, 0, DB_NB, .flags = FLAGS, .unit = "debayer" },
-        { "bilinear", "Bilinear debayering (fastest)", 0, AV_OPT_TYPE_CONST, {.i64 = DB_BILINEAR}, 0, 0, .flags = FLAGS, .unit = "debayer" },
-        { "bilinear_hq", "Bilinear debayering (high quality)", 0, AV_OPT_TYPE_CONST, {.i64 = DB_BILINEAR_HQ}, 0, 0, .flags = FLAGS, .unit = "debayer" },
-    { "format", "Output video format (software format of hardware frames)", OFFSET(out_format_string), AV_OPT_TYPE_STRING, .flags = FLAGS },
-    { "out_range", "Output colour range (from 0 to 2) (default 0)", OFFSET(out_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED}, AVCOL_RANGE_UNSPECIFIED, AVCOL_RANGE_JPEG, .flags = FLAGS, .unit = "range" },
-        { "full", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, .unit = "range" },
-        { "limited", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, .unit = "range" },
-        { "jpeg", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, .unit = "range" },
-        { "mpeg", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, .unit = "range" },
-        { "tv", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, .unit = "range" },
-        { "pc", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, .unit = "range" },
-    { NULL },
-};
-
-AVFILTER_DEFINE_CLASS(scale_vulkan);
-
-static const AVFilterPad scale_vulkan_inputs[] = {
-    {
-        .name         = "default",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame = &scale_vulkan_filter_frame,
-        .config_props = &ff_vk_filter_config_input,
-    },
-};
-
-static const AVFilterPad scale_vulkan_outputs[] = {
-    {
-        .name = "default",
-        .type = AVMEDIA_TYPE_VIDEO,
-        .config_props = &scale_vulkan_config_output,
-    },
-};
-
-const FFFilter ff_vf_scale_vulkan = {
-    .p.name         = "scale_vulkan",
-    .p.description  = NULL_IF_CONFIG_SMALL("Scale Vulkan frames"),
-    .p.priv_class   = &scale_vulkan_class,
-    .p.flags        = AVFILTER_FLAG_HWDEVICE,
-    .priv_size      = sizeof(ScaleVulkanContext),
-    .init           = &ff_vk_filter_init,
-    .uninit         = &scale_vulkan_uninit,
-    FILTER_INPUTS(scale_vulkan_inputs),
-    FILTER_OUTPUTS(scale_vulkan_outputs),
-    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
-    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
-};
-- 
2.49.1


From 3d6bcf11ca8f29611ecd22fc1709bc5efd211eb0 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:00:26 +0000
Subject: [PATCH 022/118] Changing vulkan file directory

---
 libavfilter/vulkan/vf_scale_vulkan.c | 508 +++++++++++++++++++++++++++
 1 file changed, 508 insertions(+)
 create mode 100644 libavfilter/vulkan/vf_scale_vulkan.c

diff --git a/libavfilter/vulkan/vf_scale_vulkan.c b/libavfilter/vulkan/vf_scale_vulkan.c
new file mode 100644
index 0000000000..f7e1ed7408
--- /dev/null
+++ b/libavfilter/vulkan/vf_scale_vulkan.c
@@ -0,0 +1,508 @@
+/*
+ * Copyright (c) Lynne
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/random_seed.h"
+#include "libavutil/opt.h"
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+#include "vulkan_filter.h"
+#include "libavfilter/scale_eval.h"
+#include "libavfilter/filters.h"
+#include "libavfilter/colorspace.h"
+#include "libavfilter/video.h"
+
+extern const char *ff_source_debayer_comp;
+
+enum ScalerFunc {
+    F_BILINEAR = 0,
+    F_NEAREST,
+
+    F_NB,
+};
+
+enum DebayerFunc {
+    DB_BILINEAR = 0,
+    DB_BILINEAR_HQ,
+
+    DB_NB,
+};
+
+typedef struct ScaleVulkanContext {
+    FFVulkanContext vkctx;
+
+    int initialized;
+    FFVkExecPool e;
+    AVVulkanDeviceQueueFamily *qf;
+    FFVulkanShader shd;
+    VkSampler sampler;
+
+    /* Push constants / options */
+    struct {
+        float yuv_matrix[4][4];
+        int crop_x;
+        int crop_y;
+        int crop_w;
+        int crop_h;
+    } opts;
+
+    char *out_format_string;
+    char *w_expr;
+    char *h_expr;
+
+    enum ScalerFunc scaler;
+    enum AVColorRange out_range;
+    enum DebayerFunc debayer;
+} ScaleVulkanContext;
+
+static const char scale_bilinear[] = {
+    C(0, vec4 scale_bilinear(int idx, ivec2 pos, vec2 crop_range, vec2 crop_off))
+    C(0, {                                                                      )
+    C(1,     vec2 npos = (vec2(pos) + 0.5f) / imageSize(output_img[idx]);       )
+    C(1,     npos *= crop_range;    /* Reduce the range */                      )
+    C(1,     npos += crop_off;      /* Offset the start */                      )
+    C(1,     return texture(input_img[idx], npos);                              )
+    C(0, }                                                                      )
+};
+
+static const char rgb2yuv[] = {
+    C(0, vec4 rgb2yuv(vec4 src, int fullrange)                                  )
+    C(0, {                                                                      )
+    C(1,     src *= yuv_matrix;                                                 )
+    C(1,     if (fullrange == 1) {                                              )
+    C(2,         src += vec4(0.0, 0.5, 0.5, 0.0);                               )
+    C(1,     } else {                                                           )
+    C(2,         src *= vec4(219.0 / 255.0, 224.0 / 255.0, 224.0 / 255.0, 1.0); )
+    C(2,         src += vec4(16.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0, 0.0);  )
+    C(1,     }                                                                  )
+    C(1,     return src;                                                        )
+    C(0, }                                                                      )
+};
+
+static const char write_nv12[] = {
+    C(0, void write_nv12(vec4 src, ivec2 pos)                                   )
+    C(0, {                                                                      )
+    C(1,     imageStore(output_img[0], pos, vec4(src.r, 0.0, 0.0, 0.0));        )
+    C(1,     pos /= ivec2(2);                                                   )
+    C(1,     imageStore(output_img[1], pos, vec4(src.g, src.b, 0.0, 0.0));      )
+    C(0, }                                                                      )
+};
+
+static const char write_420[] = {
+    C(0, void write_420(vec4 src, ivec2 pos)                                    )
+    C(0, {                                                                      )
+    C(1,     imageStore(output_img[0], pos, vec4(src.r, 0.0, 0.0, 0.0));        )
+    C(1,     pos /= ivec2(2);                                                   )
+    C(1,     imageStore(output_img[1], pos, vec4(src.g, 0.0, 0.0, 0.0));        )
+    C(1,     imageStore(output_img[2], pos, vec4(src.b, 0.0, 0.0, 0.0));        )
+    C(0, }                                                                      )
+};
+
+static const char write_444[] = {
+    C(0, void write_444(vec4 src, ivec2 pos)                                    )
+    C(0, {                                                                      )
+    C(1,     imageStore(output_img[0], pos, vec4(src.r, 0.0, 0.0, 0.0));        )
+    C(1,     imageStore(output_img[1], pos, vec4(src.g, 0.0, 0.0, 0.0));        )
+    C(1,     imageStore(output_img[2], pos, vec4(src.b, 0.0, 0.0, 0.0));        )
+    C(0, }                                                                      )
+};
+
+static int init_scale_shader(AVFilterContext *ctx, FFVulkanShader *shd,
+                             FFVulkanDescriptorSetBinding *desc, AVFrame *in)
+{
+    ScaleVulkanContext *s = ctx->priv;
+    GLSLD(   scale_bilinear                                                  );
+
+    if (s->vkctx.output_format != s->vkctx.input_format) {
+        GLSLD(   rgb2yuv                                                     );
+    }
+
+    switch (s->vkctx.output_format) {
+    case AV_PIX_FMT_NV12:    GLSLD(write_nv12); break;
+    case AV_PIX_FMT_YUV420P: GLSLD( write_420); break;
+    case AV_PIX_FMT_YUV444P: GLSLD( write_444); break;
+    default: break;
+    }
+
+    GLSLC(0, void main()                                                     );
+    GLSLC(0, {                                                               );
+    GLSLC(1,     ivec2 size;                                                 );
+    GLSLC(1,     ivec2 pos = ivec2(gl_GlobalInvocationID.xy);                );
+    GLSLF(1,     vec2 in_d = vec2(%i, %i);             ,in->width, in->height);
+    GLSLC(1,     vec2 c_r = vec2(crop_w, crop_h) / in_d;                     );
+    GLSLC(1,     vec2 c_o = vec2(crop_x, crop_y) / in_d;                     );
+    GLSLC(0,                                                                 );
+
+    if (s->vkctx.output_format == s->vkctx.input_format) {
+        for (int i = 0; i < desc[1].elems; i++) {
+            GLSLF(1,  size = imageSize(output_img[%i]);                    ,i);
+            GLSLC(1,  if (IS_WITHIN(pos, size)) {                            );
+            switch (s->scaler) {
+            case F_NEAREST:
+            case F_BILINEAR:
+                GLSLF(2, vec4 res = scale_bilinear(%i, pos, c_r, c_o);     ,i);
+                GLSLF(2, imageStore(output_img[%i], pos, res);             ,i);
+                break;
+            };
+            GLSLC(1, }                                                       );
+        }
+    } else {
+        GLSLC(1, vec4 res = scale_bilinear(0, pos, c_r, c_o);                );
+        GLSLF(1, res = rgb2yuv(res, %i);    ,s->out_range == AVCOL_RANGE_JPEG);
+        switch (s->vkctx.output_format) {
+        case AV_PIX_FMT_NV12:    GLSLC(1, write_nv12(res, pos); ); break;
+        case AV_PIX_FMT_YUV420P: GLSLC(1,  write_420(res, pos); ); break;
+        case AV_PIX_FMT_YUV444P: GLSLC(1,  write_444(res, pos); ); break;
+        default: return AVERROR(EINVAL);
+        }
+    }
+
+    GLSLC(0, }                                                               );
+
+    if (s->vkctx.output_format != s->vkctx.input_format) {
+        const AVLumaCoefficients *lcoeffs;
+        double tmp_mat[3][3];
+
+        lcoeffs = av_csp_luma_coeffs_from_avcsp(in->colorspace);
+        if (!lcoeffs) {
+            av_log(ctx, AV_LOG_ERROR, "Unsupported colorspace\n");
+            return AVERROR(EINVAL);
+        }
+
+        ff_fill_rgb2yuv_table(lcoeffs, tmp_mat);
+
+        for (int y = 0; y < 3; y++)
+            for (int x = 0; x < 3; x++)
+                s->opts.yuv_matrix[x][y] = tmp_mat[x][y];
+        s->opts.yuv_matrix[3][3] = 1.0;
+    }
+
+    return 0;
+}
+
+static int init_debayer_shader(ScaleVulkanContext *s, FFVulkanShader *shd,
+                               FFVulkanDescriptorSetBinding *desc, AVFrame *in)
+{
+    GLSLD(ff_source_debayer_comp);
+
+    GLSLC(0, void main(void));
+    GLSLC(0, {              );
+    if (s->debayer == DB_BILINEAR)
+        GLSLC(1, debayer_bilinear(););
+    else if (s->debayer == DB_BILINEAR_HQ)
+        GLSLC(1, debayer_bilinear_hq(););
+    GLSLC(0, }              );
+
+    shd->lg_size[0] <<= 1;
+    shd->lg_size[1] <<= 1;
+
+    return 0;
+}
+
+static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
+{
+    int err;
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    VkFilter sampler_mode;
+    ScaleVulkanContext *s = ctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    FFVulkanShader *shd = &s->shd;
+    FFVkSPIRVCompiler *spv;
+    FFVulkanDescriptorSetBinding *desc;
+
+    int debayer = s->vkctx.input_format == AV_PIX_FMT_BAYER_RGGB16;
+    int in_planes = av_pix_fmt_count_planes(s->vkctx.input_format);
+
+    switch (s->scaler) {
+    case F_NEAREST:
+        sampler_mode = VK_FILTER_NEAREST;
+        break;
+    case F_BILINEAR:
+        sampler_mode = VK_FILTER_LINEAR;
+        break;
+    };
+
+    spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
+    if (!s->qf) {
+        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
+        err = AVERROR(ENOTSUP);
+        goto fail;
+    }
+
+    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
+
+    if (!debayer)
+        RET(ff_vk_init_sampler(vkctx, &s->sampler, 0, sampler_mode));
+
+    RET(ff_vk_shader_init(vkctx, &s->shd, "scale",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          NULL, 0,
+                          32, 32, 1,
+                          0));
+
+    desc = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name       = "input_img",
+            .type       = debayer ?
+                          VK_DESCRIPTOR_TYPE_STORAGE_IMAGE :
+                          VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+            .mem_layout = debayer ?
+                          ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT) :
+                          NULL,
+            .mem_quali  = "readonly",
+            .dimensions = 2,
+            .elems      = in_planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+            .samplers   = DUP_SAMPLER(s->sampler),
+        },
+        {
+            .name       = "output_img",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "writeonly",
+            .dimensions = 2,
+            .elems      = av_pix_fmt_count_planes(s->vkctx.output_format),
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 2, 0, 0));
+
+    GLSLC(0, layout(push_constant, std430) uniform pushConstants {        );
+    GLSLC(1,    mat4 yuv_matrix;                                          );
+    GLSLC(1,    int crop_x;                                               );
+    GLSLC(1,    int crop_y;                                               );
+    GLSLC(1,    int crop_w;                                               );
+    GLSLC(1,    int crop_h;                                               );
+    GLSLC(0, };                                                           );
+    GLSLC(0,                                                              );
+
+    ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts),
+                                VK_SHADER_STAGE_COMPUTE_BIT);
+
+    if (debayer)
+        err = init_debayer_shader(s, shd, desc, in);
+    else
+        err = init_scale_shader(ctx, shd, desc, in);
+    if (err < 0)
+        goto fail;
+
+    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
+
+    s->initialized = 1;
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+    if (spv)
+        spv->uninit(&spv);
+
+    return err;
+}
+
+static int scale_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
+{
+    int err;
+    AVFilterContext *ctx = link->dst;
+    ScaleVulkanContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+
+    AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!out) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    if (!s->initialized)
+        RET(init_filter(ctx, in));
+
+    s->opts.crop_x = in->crop_left;
+    s->opts.crop_y = in->crop_top;
+    s->opts.crop_w = in->width - (in->crop_left + in->crop_right);
+    s->opts.crop_h = in->height - (in->crop_top + in->crop_bottom);
+
+    RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->shd, out, in,
+                                    s->sampler, &s->opts, sizeof(s->opts)));
+
+    err = av_frame_copy_props(out, in);
+    if (err < 0)
+        goto fail;
+
+    if (out->width != in->width || out->height != in->height) {
+        av_frame_side_data_remove_by_props(&out->side_data, &out->nb_side_data,
+                                           AV_SIDE_DATA_PROP_SIZE_DEPENDENT);
+    }
+
+    if (s->out_range != AVCOL_RANGE_UNSPECIFIED)
+        out->color_range = s->out_range;
+    if (s->vkctx.output_format != s->vkctx.input_format)
+        out->chroma_location = AVCHROMA_LOC_TOPLEFT;
+
+    av_frame_free(&in);
+
+    return ff_filter_frame(outlink, out);
+
+fail:
+    av_frame_free(&in);
+    av_frame_free(&out);
+    return err;
+}
+
+static int scale_vulkan_config_output(AVFilterLink *outlink)
+{
+    int err;
+    AVFilterContext *avctx = outlink->src;
+    ScaleVulkanContext *s  = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    AVFilterLink *inlink   = outlink->src->inputs[0];
+
+    err = ff_scale_eval_dimensions(s, s->w_expr, s->h_expr, inlink, outlink,
+                                   &vkctx->output_width,
+                                   &vkctx->output_height);
+    if (err < 0)
+        return err;
+
+    ff_scale_adjust_dimensions(inlink, &vkctx->output_width, &vkctx->output_height, 0, 1, 1.f);
+
+    outlink->w = vkctx->output_width;
+    outlink->h = vkctx->output_height;
+
+    if (s->out_format_string) {
+        s->vkctx.output_format = av_get_pix_fmt(s->out_format_string);
+        if (s->vkctx.output_format == AV_PIX_FMT_NONE) {
+            av_log(avctx, AV_LOG_ERROR, "Invalid output format.\n");
+            return AVERROR(EINVAL);
+        }
+    } else {
+        s->vkctx.output_format = s->vkctx.input_format;
+    }
+
+    if (s->vkctx.input_format == AV_PIX_FMT_BAYER_RGGB16) {
+        if (s->vkctx.output_format == s->vkctx.input_format) {
+            s->vkctx.output_format = AV_PIX_FMT_RGBA64;
+        } else if (!ff_vk_mt_is_np_rgb(s->vkctx.output_format)) {
+            av_log(avctx, AV_LOG_ERROR, "Unsupported output format for debayer\n");
+            return AVERROR(EINVAL);
+        }
+        if (inlink->w != outlink->w || inlink->w != outlink->w) {
+            av_log(avctx, AV_LOG_ERROR, "Scaling is not supported with debayering\n");
+            return AVERROR_PATCHWELCOME;
+        }
+    } else if (s->vkctx.output_format != s->vkctx.input_format) {
+        if (!ff_vk_mt_is_np_rgb(s->vkctx.input_format)) {
+            av_log(avctx, AV_LOG_ERROR, "Unsupported input format for conversion\n");
+            return AVERROR(EINVAL);
+        }
+        if (s->vkctx.output_format != AV_PIX_FMT_NV12 &&
+            s->vkctx.output_format != AV_PIX_FMT_YUV420P &&
+            s->vkctx.output_format != AV_PIX_FMT_YUV444P) {
+            av_log(avctx, AV_LOG_ERROR, "Unsupported output format\n");
+            return AVERROR(EINVAL);
+        }
+    } else if (s->out_range != AVCOL_RANGE_UNSPECIFIED) {
+        av_log(avctx, AV_LOG_ERROR, "Cannot change range without converting format\n");
+        return AVERROR(EINVAL);
+    }
+
+    return ff_vk_filter_config_output(outlink);
+}
+
+static void scale_vulkan_uninit(AVFilterContext *avctx)
+{
+    ScaleVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    FFVulkanFunctions *vk = &vkctx->vkfn;
+
+    ff_vk_exec_pool_free(vkctx, &s->e);
+    ff_vk_shader_free(vkctx, &s->shd);
+
+    if (s->sampler)
+        vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler,
+                           vkctx->hwctx->alloc);
+
+    ff_vk_uninit(&s->vkctx);
+
+    s->initialized = 0;
+}
+
+#define OFFSET(x) offsetof(ScaleVulkanContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
+static const AVOption scale_vulkan_options[] = {
+    { "w", "Output video width",  OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = FLAGS },
+    { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = FLAGS },
+    { "scaler", "Scaler function", OFFSET(scaler), AV_OPT_TYPE_INT, {.i64 = F_BILINEAR}, 0, F_NB, .flags = FLAGS, .unit = "scaler" },
+        { "bilinear", "Bilinear interpolation (fastest)", 0, AV_OPT_TYPE_CONST, {.i64 = F_BILINEAR}, 0, 0, .flags = FLAGS, .unit = "scaler" },
+        { "nearest", "Nearest (useful for pixel art)", 0, AV_OPT_TYPE_CONST, {.i64 = F_NEAREST}, 0, 0, .flags = FLAGS, .unit = "scaler" },
+    { "debayer", "Debayer algorithm to use", OFFSET(debayer), AV_OPT_TYPE_INT, {.i64 = DB_BILINEAR_HQ}, 0, DB_NB, .flags = FLAGS, .unit = "debayer" },
+        { "bilinear", "Bilinear debayering (fastest)", 0, AV_OPT_TYPE_CONST, {.i64 = DB_BILINEAR}, 0, 0, .flags = FLAGS, .unit = "debayer" },
+        { "bilinear_hq", "Bilinear debayering (high quality)", 0, AV_OPT_TYPE_CONST, {.i64 = DB_BILINEAR_HQ}, 0, 0, .flags = FLAGS, .unit = "debayer" },
+    { "format", "Output video format (software format of hardware frames)", OFFSET(out_format_string), AV_OPT_TYPE_STRING, .flags = FLAGS },
+    { "out_range", "Output colour range (from 0 to 2) (default 0)", OFFSET(out_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED}, AVCOL_RANGE_UNSPECIFIED, AVCOL_RANGE_JPEG, .flags = FLAGS, .unit = "range" },
+        { "full", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, .unit = "range" },
+        { "limited", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, .unit = "range" },
+        { "jpeg", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, .unit = "range" },
+        { "mpeg", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, .unit = "range" },
+        { "tv", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, .unit = "range" },
+        { "pc", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, .unit = "range" },
+    { NULL },
+};
+
+AVFILTER_DEFINE_CLASS(scale_vulkan);
+
+static const AVFilterPad scale_vulkan_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = &scale_vulkan_filter_frame,
+        .config_props = &ff_vk_filter_config_input,
+    },
+};
+
+static const AVFilterPad scale_vulkan_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_VIDEO,
+        .config_props = &scale_vulkan_config_output,
+    },
+};
+
+const FFFilter ff_vf_scale_vulkan = {
+    .p.name         = "scale_vulkan",
+    .p.description  = NULL_IF_CONFIG_SMALL("Scale Vulkan frames"),
+    .p.priv_class   = &scale_vulkan_class,
+    .p.flags        = AVFILTER_FLAG_HWDEVICE,
+    .priv_size      = sizeof(ScaleVulkanContext),
+    .init           = &ff_vk_filter_init,
+    .uninit         = &scale_vulkan_uninit,
+    FILTER_INPUTS(scale_vulkan_inputs),
+    FILTER_OUTPUTS(scale_vulkan_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};
-- 
2.49.1


From 2095c9abde4bded42306b9cb8315a3b875448d08 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:01:11 +0000
Subject: [PATCH 023/118] Changing vulkan file directory

---
 libavfilter/vf_scdet_vulkan.c | 412 ----------------------------------
 1 file changed, 412 deletions(-)
 delete mode 100644 libavfilter/vf_scdet_vulkan.c

diff --git a/libavfilter/vf_scdet_vulkan.c b/libavfilter/vf_scdet_vulkan.c
deleted file mode 100644
index ee2bf248a2..0000000000
--- a/libavfilter/vf_scdet_vulkan.c
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * Copyright 2025 (c) Niklas Haas
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/avassert.h"
-#include "libavutil/vulkan_spirv.h"
-#include "libavutil/opt.h"
-#include "libavutil/timestamp.h"
-#include "vulkan_filter.h"
-
-#include "filters.h"
-
-typedef struct SceneDetectVulkanContext {
-    FFVulkanContext vkctx;
-
-    int initialized;
-    FFVkExecPool e;
-    AVVulkanDeviceQueueFamily *qf;
-    FFVulkanShader shd;
-    AVBufferPool *det_buf_pool;
-
-    double threshold;
-    int sc_pass;
-
-    int nb_planes;
-    double prev_mafd;
-    AVFrame *prev;
-    AVFrame *cur;
-} SceneDetectVulkanContext;
-
-typedef struct SceneDetectBuf {
-#define SLICES 16
-    uint32_t frame_sad[SLICES];
-} SceneDetectBuf;
-
-static av_cold int init_filter(AVFilterContext *ctx)
-{
-    int err;
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    SceneDetectVulkanContext *s = ctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    FFVulkanShader *shd;
-    FFVkSPIRVCompiler *spv;
-    FFVulkanDescriptorSetBinding *desc;
-
-    const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(s->vkctx.input_format);
-    const int lumaonly = !(pixdesc->flags & AV_PIX_FMT_FLAG_RGB) &&
-                         (pixdesc->flags & AV_PIX_FMT_FLAG_PLANAR);
-    s->nb_planes = lumaonly ? 1 : av_pix_fmt_count_planes(s->vkctx.input_format);
-
-    spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
-    if (!s->qf) {
-        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
-        err = AVERROR(ENOTSUP);
-        goto fail;
-    }
-
-    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
-    RET(ff_vk_shader_init(vkctx, &s->shd, "scdet",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          (const char *[]) { "GL_KHR_shader_subgroup_arithmetic" }, 1,
-                          32, 32, 1,
-                          0));
-    shd = &s->shd;
-
-    desc = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name       = "prev_img",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_UINT),
-            .mem_quali  = "readonly",
-            .dimensions = 2,
-            .elems      = av_pix_fmt_count_planes(s->vkctx.input_format),
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        }, {
-            .name       = "cur_img",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_UINT),
-            .mem_quali  = "readonly",
-            .dimensions = 2,
-            .elems      = av_pix_fmt_count_planes(s->vkctx.input_format),
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        }, {
-            .name        = "sad_buffer",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "uint frame_sad[];",
-        }
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 3, 0, 0));
-
-    GLSLC(0, shared uint wg_sum;                                              );
-    GLSLC(0, void main()                                                      );
-    GLSLC(0, {                                                                );
-    GLSLF(1,     const uint slice = gl_WorkGroupID.x %% %u;            ,SLICES);
-    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);           );
-    GLSLC(1,     wg_sum = 0;                                                  );
-    GLSLC(1,     barrier();                                                   );
-    for (int i = 0; i < s->nb_planes; i++) {
-        GLSLF(1, if (IS_WITHIN(pos, imageSize(cur_img[%d]))) {              ,i);
-        GLSLF(2,     uvec4 prev = imageLoad(prev_img[%d], pos);             ,i);
-        GLSLF(2,     uvec4 cur  = imageLoad(cur_img[%d],  pos);             ,i);
-        GLSLC(2,     uvec4 sad = abs(ivec4(cur) - ivec4(prev));               );
-        GLSLC(2,     uint sum = subgroupAdd(sad.x + sad.y + sad.z);           );
-        GLSLC(2,     if (subgroupElect())                                     );
-        GLSLC(3,         atomicAdd(wg_sum, sum);                              );
-        GLSLC(1, }                                                            );
-    }
-    GLSLC(1,     barrier();                                                   );
-    GLSLC(1,     if (gl_LocalInvocationIndex == 0)                            );
-    GLSLC(2,         atomicAdd(frame_sad[slice], wg_sum);                     );
-    GLSLC(0, }                                                                );
-
-    RET(spv->compile_shader(vkctx, spv, &s->shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(vkctx, &s->shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
-
-    s->initialized = 1;
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-    if (spv)
-        spv->uninit(&spv);
-
-    return err;
-}
-
-static double evaluate(AVFilterContext *ctx, const SceneDetectBuf *buf)
-{
-    SceneDetectVulkanContext *s = ctx->priv;
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->vkctx.input_format);
-    const AVFilterLink *inlink = ctx->inputs[0];
-    uint64_t count;
-    double mafd, diff;
-
-    uint64_t sad = 0;
-    for (int i = 0; i < SLICES; i++)
-        sad += buf->frame_sad[i];
-
-    av_assert2(s->nb_planes == 1 || !(desc->log2_chroma_w || desc->log2_chroma_h));
-    count = s->nb_planes * inlink->w * inlink->h;
-    mafd = (double) sad * 100.0 / count / (1ULL << desc->comp[0].depth);
-    diff = fabs(mafd - s->prev_mafd);
-    s->prev_mafd = mafd;
-
-    return av_clipf(FFMIN(mafd, diff), 0.0, 100.0);
-}
-
-static int scdet_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
-{
-    int err;
-    AVFilterContext *ctx = link->dst;
-    SceneDetectVulkanContext *s = ctx->priv;
-    AVFilterLink *outlink = ctx->outputs[0];
-
-    VkImageView prev_views[AV_NUM_DATA_POINTERS];
-    VkImageView cur_views[AV_NUM_DATA_POINTERS];
-    VkImageMemoryBarrier2 img_bar[8];
-    int nb_img_bar = 0;
-
-    FFVulkanContext *vkctx = &s->vkctx;
-    FFVulkanFunctions *vk = &vkctx->vkfn;
-    FFVkExecContext *exec = NULL;
-    AVBufferRef *buf = NULL;
-    FFVkBuffer *buf_vk;
-
-    SceneDetectBuf *sad;
-    double score = 0.0;
-    char str[64];
-
-    if (!s->initialized)
-        RET(init_filter(ctx));
-
-    av_frame_free(&s->prev);
-    s->prev = s->cur;
-    s->cur = av_frame_clone(in);
-    if (!s->prev)
-        goto done;
-
-    RET(ff_vk_get_pooled_buffer(vkctx, &s->det_buf_pool, &buf,
-                                VK_BUFFER_USAGE_TRANSFER_DST_BIT |
-                                VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
-                                NULL,
-                                sizeof(SceneDetectBuf),
-                                VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
-                                VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
-                                VK_MEMORY_PROPERTY_HOST_COHERENT_BIT));
-    buf_vk = (FFVkBuffer *)buf->data;
-    sad = (SceneDetectBuf *) buf_vk->mapped_mem;
-
-    exec = ff_vk_exec_get(vkctx, &s->e);
-    ff_vk_exec_start(vkctx, exec);
-
-    RET(ff_vk_exec_add_dep_frame(vkctx, exec, s->prev,
-                                 VK_PIPELINE_STAGE_2_NONE,
-                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
-    RET(ff_vk_create_imageviews(vkctx, exec, prev_views, s->prev, FF_VK_REP_UINT));
-
-    ff_vk_shader_update_img_array(vkctx, exec, &s->shd, s->prev, prev_views, 0, 0,
-                                  VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
-
-    ff_vk_frame_barrier(vkctx, exec, s->prev, img_bar, &nb_img_bar,
-                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                        VK_ACCESS_SHADER_READ_BIT,
-                        VK_IMAGE_LAYOUT_GENERAL,
-                        VK_QUEUE_FAMILY_IGNORED);
-
-    RET(ff_vk_exec_add_dep_frame(vkctx, exec, s->cur,
-                                 VK_PIPELINE_STAGE_2_NONE,
-                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
-    RET(ff_vk_create_imageviews(vkctx, exec, cur_views, s->cur, FF_VK_REP_UINT));
-
-    ff_vk_shader_update_img_array(vkctx, exec, &s->shd, s->cur, cur_views, 0, 1,
-                                  VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
-
-    ff_vk_frame_barrier(vkctx, exec, s->cur, img_bar, &nb_img_bar,
-                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                        VK_ACCESS_SHADER_READ_BIT,
-                        VK_IMAGE_LAYOUT_GENERAL,
-                        VK_QUEUE_FAMILY_IGNORED);
-
-    /* zero buffer */
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-            .pBufferMemoryBarriers = &(VkBufferMemoryBarrier2) {
-                .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-                .srcStageMask = VK_PIPELINE_STAGE_2_NONE,
-                .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
-                .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
-                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-                .buffer = buf_vk->buf,
-                .size = buf_vk->size,
-                .offset = 0,
-            },
-            .bufferMemoryBarrierCount = 1,
-        });
-
-    vk->CmdFillBuffer(exec->buf, buf_vk->buf, 0, buf_vk->size, 0x0);
-
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-            .pImageMemoryBarriers = img_bar,
-            .imageMemoryBarrierCount = nb_img_bar,
-            .pBufferMemoryBarriers = &(VkBufferMemoryBarrier2) {
-                .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-                .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
-                .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
-                .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
-                                 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
-                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-                .buffer = buf_vk->buf,
-                .size = buf_vk->size,
-                .offset = 0,
-            },
-            .bufferMemoryBarrierCount = 1,
-        });
-
-    RET(ff_vk_shader_update_desc_buffer(&s->vkctx, exec, &s->shd, 0, 2, 0,
-                                        buf_vk, 0, buf_vk->size,
-                                        VK_FORMAT_UNDEFINED));
-
-    ff_vk_exec_bind_shader(vkctx, exec, &s->shd);
-
-    vk->CmdDispatch(exec->buf,
-                    FFALIGN(in->width,  s->shd.lg_size[0]) / s->shd.lg_size[0],
-                    FFALIGN(in->height, s->shd.lg_size[1]) / s->shd.lg_size[1],
-                    s->shd.lg_size[2]);
-
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-            .pBufferMemoryBarriers = &(VkBufferMemoryBarrier2) {
-                .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-                .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                .dstStageMask = VK_PIPELINE_STAGE_2_HOST_BIT,
-                .srcAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
-                                 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
-                .dstAccessMask = VK_ACCESS_HOST_READ_BIT,
-                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-                .buffer = buf_vk->buf,
-                .size = buf_vk->size,
-                .offset = 0,
-            },
-            .bufferMemoryBarrierCount = 1,
-        });
-
-    RET(ff_vk_exec_submit(vkctx, exec));
-    ff_vk_exec_wait(vkctx, exec);
-    score = evaluate(ctx, sad);
-
-done:
-    snprintf(str, sizeof(str), "%0.3f", s->prev_mafd);
-    av_dict_set(&in->metadata, "lavfi.scd.mafd", str, 0);
-    snprintf(str, sizeof(str), "%0.3f", score);
-    av_dict_set(&in->metadata, "lavfi.scd.score", str, 0);
-
-    if (score >= s->threshold) {
-        const char *pts = av_ts2timestr(in->pts, &link->time_base);
-        av_dict_set(&in->metadata, "lavfi.scd.time", pts, 0);
-        av_log(ctx, AV_LOG_INFO, "lavfi.scd.score: %.3f, lavfi.scd.time: %s\n",
-               score, pts);
-    }
-
-    av_buffer_unref(&buf);
-    if (!s->sc_pass || score >= s->threshold)
-        return ff_filter_frame(outlink, in);
-    else {
-        av_frame_free(&in);
-        return 0;
-    }
-
-fail:
-    if (exec)
-        ff_vk_exec_discard_deps(&s->vkctx, exec);
-    av_frame_free(&in);
-    av_buffer_unref(&buf);
-    return err;
-}
-
-static void scdet_vulkan_uninit(AVFilterContext *avctx)
-{
-    SceneDetectVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-
-    av_frame_free(&s->prev);
-    av_frame_free(&s->cur);
-
-    ff_vk_exec_pool_free(vkctx, &s->e);
-    ff_vk_shader_free(vkctx, &s->shd);
-
-    av_buffer_pool_uninit(&s->det_buf_pool);
-
-    ff_vk_uninit(&s->vkctx);
-
-    s->initialized = 0;
-}
-
-#define OFFSET(x) offsetof(SceneDetectVulkanContext, x)
-#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
-static const AVOption scdet_vulkan_options[] = {
-    { "threshold",   "set scene change detect threshold",        OFFSET(threshold),  AV_OPT_TYPE_DOUBLE,   {.dbl = 10.},     0,  100., FLAGS },
-    { "t",           "set scene change detect threshold",        OFFSET(threshold),  AV_OPT_TYPE_DOUBLE,   {.dbl = 10.},     0,  100., FLAGS },
-    { "sc_pass",     "Set the flag to pass scene change frames", OFFSET(sc_pass),    AV_OPT_TYPE_BOOL,     {.i64 = 0  },     0,    1,  FLAGS },
-    { "s",           "Set the flag to pass scene change frames", OFFSET(sc_pass),    AV_OPT_TYPE_BOOL,     {.i64 = 0  },     0,    1,  FLAGS },
-    { NULL }
-};
-
-AVFILTER_DEFINE_CLASS(scdet_vulkan);
-
-static const AVFilterPad scdet_vulkan_inputs[] = {
-    {
-        .name         = "default",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame = &scdet_vulkan_filter_frame,
-        .config_props = &ff_vk_filter_config_input,
-    },
-};
-
-static const AVFilterPad scdet_vulkan_outputs[] = {
-    {
-        .name = "default",
-        .type = AVMEDIA_TYPE_VIDEO,
-        .config_props = &ff_vk_filter_config_output,
-    },
-};
-
-const FFFilter ff_vf_scdet_vulkan = {
-    .p.name         = "scdet_vulkan",
-    .p.description  = NULL_IF_CONFIG_SMALL("Detect video scene change"),
-    .p.priv_class   = &scdet_vulkan_class,
-    .p.flags        = AVFILTER_FLAG_HWDEVICE,
-    .priv_size      = sizeof(SceneDetectVulkanContext),
-    .init           = &ff_vk_filter_init,
-    .uninit         = &scdet_vulkan_uninit,
-    FILTER_INPUTS(scdet_vulkan_inputs),
-    FILTER_OUTPUTS(scdet_vulkan_outputs),
-    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
-    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
-};
-- 
2.49.1


From 9599b10a1242b06e66a0b0c595f69db4ee44fb78 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:02:05 +0000
Subject: [PATCH 024/118] Changing vulkan file directory

---
 libavfilter/vulkan/vf_scdet_vulkan.c | 412 +++++++++++++++++++++++++++
 1 file changed, 412 insertions(+)
 create mode 100644 libavfilter/vulkan/vf_scdet_vulkan.c

diff --git a/libavfilter/vulkan/vf_scdet_vulkan.c b/libavfilter/vulkan/vf_scdet_vulkan.c
new file mode 100644
index 0000000000..7b13a2936b
--- /dev/null
+++ b/libavfilter/vulkan/vf_scdet_vulkan.c
@@ -0,0 +1,412 @@
+/*
+ * Copyright 2025 (c) Niklas Haas
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/avassert.h"
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+#include "libavutil/opt.h"
+#include "libavutil/timestamp.h"
+#include "vulkan_filter.h"
+
+#include "libavfilter/filters.h"
+
+typedef struct SceneDetectVulkanContext {
+    FFVulkanContext vkctx;
+
+    int initialized;
+    FFVkExecPool e;
+    AVVulkanDeviceQueueFamily *qf;
+    FFVulkanShader shd;
+    AVBufferPool *det_buf_pool;
+
+    double threshold;
+    int sc_pass;
+
+    int nb_planes;
+    double prev_mafd;
+    AVFrame *prev;
+    AVFrame *cur;
+} SceneDetectVulkanContext;
+
+typedef struct SceneDetectBuf {
+#define SLICES 16
+    uint32_t frame_sad[SLICES];
+} SceneDetectBuf;
+
+static av_cold int init_filter(AVFilterContext *ctx)
+{
+    int err;
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    SceneDetectVulkanContext *s = ctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    FFVulkanShader *shd;
+    FFVkSPIRVCompiler *spv;
+    FFVulkanDescriptorSetBinding *desc;
+
+    const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(s->vkctx.input_format);
+    const int lumaonly = !(pixdesc->flags & AV_PIX_FMT_FLAG_RGB) &&
+                         (pixdesc->flags & AV_PIX_FMT_FLAG_PLANAR);
+    s->nb_planes = lumaonly ? 1 : av_pix_fmt_count_planes(s->vkctx.input_format);
+
+    spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
+    if (!s->qf) {
+        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
+        err = AVERROR(ENOTSUP);
+        goto fail;
+    }
+
+    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
+    RET(ff_vk_shader_init(vkctx, &s->shd, "scdet",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          (const char *[]) { "GL_KHR_shader_subgroup_arithmetic" }, 1,
+                          32, 32, 1,
+                          0));
+    shd = &s->shd;
+
+    desc = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name       = "prev_img",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_UINT),
+            .mem_quali  = "readonly",
+            .dimensions = 2,
+            .elems      = av_pix_fmt_count_planes(s->vkctx.input_format),
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        }, {
+            .name       = "cur_img",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_UINT),
+            .mem_quali  = "readonly",
+            .dimensions = 2,
+            .elems      = av_pix_fmt_count_planes(s->vkctx.input_format),
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        }, {
+            .name        = "sad_buffer",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "uint frame_sad[];",
+        }
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 3, 0, 0));
+
+    GLSLC(0, shared uint wg_sum;                                              );
+    GLSLC(0, void main()                                                      );
+    GLSLC(0, {                                                                );
+    GLSLF(1,     const uint slice = gl_WorkGroupID.x %% %u;            ,SLICES);
+    GLSLC(1,     const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);           );
+    GLSLC(1,     wg_sum = 0;                                                  );
+    GLSLC(1,     barrier();                                                   );
+    for (int i = 0; i < s->nb_planes; i++) {
+        GLSLF(1, if (IS_WITHIN(pos, imageSize(cur_img[%d]))) {              ,i);
+        GLSLF(2,     uvec4 prev = imageLoad(prev_img[%d], pos);             ,i);
+        GLSLF(2,     uvec4 cur  = imageLoad(cur_img[%d],  pos);             ,i);
+        GLSLC(2,     uvec4 sad = abs(ivec4(cur) - ivec4(prev));               );
+        GLSLC(2,     uint sum = subgroupAdd(sad.x + sad.y + sad.z);           );
+        GLSLC(2,     if (subgroupElect())                                     );
+        GLSLC(3,         atomicAdd(wg_sum, sum);                              );
+        GLSLC(1, }                                                            );
+    }
+    GLSLC(1,     barrier();                                                   );
+    GLSLC(1,     if (gl_LocalInvocationIndex == 0)                            );
+    GLSLC(2,         atomicAdd(frame_sad[slice], wg_sum);                     );
+    GLSLC(0, }                                                                );
+
+    RET(spv->compile_shader(vkctx, spv, &s->shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(vkctx, &s->shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
+
+    s->initialized = 1;
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+    if (spv)
+        spv->uninit(&spv);
+
+    return err;
+}
+
+static double evaluate(AVFilterContext *ctx, const SceneDetectBuf *buf)
+{
+    SceneDetectVulkanContext *s = ctx->priv;
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->vkctx.input_format);
+    const AVFilterLink *inlink = ctx->inputs[0];
+    uint64_t count;
+    double mafd, diff;
+
+    uint64_t sad = 0;
+    for (int i = 0; i < SLICES; i++)
+        sad += buf->frame_sad[i];
+
+    av_assert2(s->nb_planes == 1 || !(desc->log2_chroma_w || desc->log2_chroma_h));
+    count = s->nb_planes * inlink->w * inlink->h;
+    mafd = (double) sad * 100.0 / count / (1ULL << desc->comp[0].depth);
+    diff = fabs(mafd - s->prev_mafd);
+    s->prev_mafd = mafd;
+
+    return av_clipf(FFMIN(mafd, diff), 0.0, 100.0);
+}
+
+static int scdet_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
+{
+    int err;
+    AVFilterContext *ctx = link->dst;
+    SceneDetectVulkanContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+
+    VkImageView prev_views[AV_NUM_DATA_POINTERS];
+    VkImageView cur_views[AV_NUM_DATA_POINTERS];
+    VkImageMemoryBarrier2 img_bar[8];
+    int nb_img_bar = 0;
+
+    FFVulkanContext *vkctx = &s->vkctx;
+    FFVulkanFunctions *vk = &vkctx->vkfn;
+    FFVkExecContext *exec = NULL;
+    AVBufferRef *buf = NULL;
+    FFVkBuffer *buf_vk;
+
+    SceneDetectBuf *sad;
+    double score = 0.0;
+    char str[64];
+
+    if (!s->initialized)
+        RET(init_filter(ctx));
+
+    av_frame_free(&s->prev);
+    s->prev = s->cur;
+    s->cur = av_frame_clone(in);
+    if (!s->prev)
+        goto done;
+
+    RET(ff_vk_get_pooled_buffer(vkctx, &s->det_buf_pool, &buf,
+                                VK_BUFFER_USAGE_TRANSFER_DST_BIT |
+                                VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+                                NULL,
+                                sizeof(SceneDetectBuf),
+                                VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+                                VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+                                VK_MEMORY_PROPERTY_HOST_COHERENT_BIT));
+    buf_vk = (FFVkBuffer *)buf->data;
+    sad = (SceneDetectBuf *) buf_vk->mapped_mem;
+
+    exec = ff_vk_exec_get(vkctx, &s->e);
+    ff_vk_exec_start(vkctx, exec);
+
+    RET(ff_vk_exec_add_dep_frame(vkctx, exec, s->prev,
+                                 VK_PIPELINE_STAGE_2_NONE,
+                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
+    RET(ff_vk_create_imageviews(vkctx, exec, prev_views, s->prev, FF_VK_REP_UINT));
+
+    ff_vk_shader_update_img_array(vkctx, exec, &s->shd, s->prev, prev_views, 0, 0,
+                                  VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
+
+    ff_vk_frame_barrier(vkctx, exec, s->prev, img_bar, &nb_img_bar,
+                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                        VK_ACCESS_SHADER_READ_BIT,
+                        VK_IMAGE_LAYOUT_GENERAL,
+                        VK_QUEUE_FAMILY_IGNORED);
+
+    RET(ff_vk_exec_add_dep_frame(vkctx, exec, s->cur,
+                                 VK_PIPELINE_STAGE_2_NONE,
+                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
+    RET(ff_vk_create_imageviews(vkctx, exec, cur_views, s->cur, FF_VK_REP_UINT));
+
+    ff_vk_shader_update_img_array(vkctx, exec, &s->shd, s->cur, cur_views, 0, 1,
+                                  VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
+
+    ff_vk_frame_barrier(vkctx, exec, s->cur, img_bar, &nb_img_bar,
+                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                        VK_ACCESS_SHADER_READ_BIT,
+                        VK_IMAGE_LAYOUT_GENERAL,
+                        VK_QUEUE_FAMILY_IGNORED);
+
+    /* zero buffer */
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+            .pBufferMemoryBarriers = &(VkBufferMemoryBarrier2) {
+                .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+                .srcStageMask = VK_PIPELINE_STAGE_2_NONE,
+                .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
+                .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                .buffer = buf_vk->buf,
+                .size = buf_vk->size,
+                .offset = 0,
+            },
+            .bufferMemoryBarrierCount = 1,
+        });
+
+    vk->CmdFillBuffer(exec->buf, buf_vk->buf, 0, buf_vk->size, 0x0);
+
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+            .pImageMemoryBarriers = img_bar,
+            .imageMemoryBarrierCount = nb_img_bar,
+            .pBufferMemoryBarriers = &(VkBufferMemoryBarrier2) {
+                .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+                .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
+                .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+                .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
+                                 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
+                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                .buffer = buf_vk->buf,
+                .size = buf_vk->size,
+                .offset = 0,
+            },
+            .bufferMemoryBarrierCount = 1,
+        });
+
+    RET(ff_vk_shader_update_desc_buffer(&s->vkctx, exec, &s->shd, 0, 2, 0,
+                                        buf_vk, 0, buf_vk->size,
+                                        VK_FORMAT_UNDEFINED));
+
+    ff_vk_exec_bind_shader(vkctx, exec, &s->shd);
+
+    vk->CmdDispatch(exec->buf,
+                    FFALIGN(in->width,  s->shd.lg_size[0]) / s->shd.lg_size[0],
+                    FFALIGN(in->height, s->shd.lg_size[1]) / s->shd.lg_size[1],
+                    s->shd.lg_size[2]);
+
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+            .pBufferMemoryBarriers = &(VkBufferMemoryBarrier2) {
+                .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+                .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                .dstStageMask = VK_PIPELINE_STAGE_2_HOST_BIT,
+                .srcAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
+                                 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
+                .dstAccessMask = VK_ACCESS_HOST_READ_BIT,
+                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                .buffer = buf_vk->buf,
+                .size = buf_vk->size,
+                .offset = 0,
+            },
+            .bufferMemoryBarrierCount = 1,
+        });
+
+    RET(ff_vk_exec_submit(vkctx, exec));
+    ff_vk_exec_wait(vkctx, exec);
+    score = evaluate(ctx, sad);
+
+done:
+    snprintf(str, sizeof(str), "%0.3f", s->prev_mafd);
+    av_dict_set(&in->metadata, "lavfi.scd.mafd", str, 0);
+    snprintf(str, sizeof(str), "%0.3f", score);
+    av_dict_set(&in->metadata, "lavfi.scd.score", str, 0);
+
+    if (score >= s->threshold) {
+        const char *pts = av_ts2timestr(in->pts, &link->time_base);
+        av_dict_set(&in->metadata, "lavfi.scd.time", pts, 0);
+        av_log(ctx, AV_LOG_INFO, "lavfi.scd.score: %.3f, lavfi.scd.time: %s\n",
+               score, pts);
+    }
+
+    av_buffer_unref(&buf);
+    if (!s->sc_pass || score >= s->threshold)
+        return ff_filter_frame(outlink, in);
+    else {
+        av_frame_free(&in);
+        return 0;
+    }
+
+fail:
+    if (exec)
+        ff_vk_exec_discard_deps(&s->vkctx, exec);
+    av_frame_free(&in);
+    av_buffer_unref(&buf);
+    return err;
+}
+
+static void scdet_vulkan_uninit(AVFilterContext *avctx)
+{
+    SceneDetectVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+
+    av_frame_free(&s->prev);
+    av_frame_free(&s->cur);
+
+    ff_vk_exec_pool_free(vkctx, &s->e);
+    ff_vk_shader_free(vkctx, &s->shd);
+
+    av_buffer_pool_uninit(&s->det_buf_pool);
+
+    ff_vk_uninit(&s->vkctx);
+
+    s->initialized = 0;
+}
+
+#define OFFSET(x) offsetof(SceneDetectVulkanContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
+static const AVOption scdet_vulkan_options[] = {
+    { "threshold",   "set scene change detect threshold",        OFFSET(threshold),  AV_OPT_TYPE_DOUBLE,   {.dbl = 10.},     0,  100., FLAGS },
+    { "t",           "set scene change detect threshold",        OFFSET(threshold),  AV_OPT_TYPE_DOUBLE,   {.dbl = 10.},     0,  100., FLAGS },
+    { "sc_pass",     "Set the flag to pass scene change frames", OFFSET(sc_pass),    AV_OPT_TYPE_BOOL,     {.i64 = 0  },     0,    1,  FLAGS },
+    { "s",           "Set the flag to pass scene change frames", OFFSET(sc_pass),    AV_OPT_TYPE_BOOL,     {.i64 = 0  },     0,    1,  FLAGS },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(scdet_vulkan);
+
+static const AVFilterPad scdet_vulkan_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = &scdet_vulkan_filter_frame,
+        .config_props = &ff_vk_filter_config_input,
+    },
+};
+
+static const AVFilterPad scdet_vulkan_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_VIDEO,
+        .config_props = &ff_vk_filter_config_output,
+    },
+};
+
+const FFFilter ff_vf_scdet_vulkan = {
+    .p.name         = "scdet_vulkan",
+    .p.description  = NULL_IF_CONFIG_SMALL("Detect video scene change"),
+    .p.priv_class   = &scdet_vulkan_class,
+    .p.flags        = AVFILTER_FLAG_HWDEVICE,
+    .priv_size      = sizeof(SceneDetectVulkanContext),
+    .init           = &ff_vk_filter_init,
+    .uninit         = &scdet_vulkan_uninit,
+    FILTER_INPUTS(scdet_vulkan_inputs),
+    FILTER_OUTPUTS(scdet_vulkan_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};
-- 
2.49.1


From de8026b88035e5dc927e1a3c48b17ed03188e914 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:02:44 +0000
Subject: [PATCH 025/118] Changing vulkan file directory

---
 libavfilter/vf_transpose_vulkan.c | 275 ------------------------------
 1 file changed, 275 deletions(-)
 delete mode 100644 libavfilter/vf_transpose_vulkan.c

diff --git a/libavfilter/vf_transpose_vulkan.c b/libavfilter/vf_transpose_vulkan.c
deleted file mode 100644
index 3fe2d11cb2..0000000000
--- a/libavfilter/vf_transpose_vulkan.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * copyright (c) 2021 Wu Jianhua <jianhua.wu@intel.com>
- * Copyright (c) Lynne
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/random_seed.h"
-#include "libavutil/opt.h"
-#include "libavutil/vulkan_spirv.h"
-#include "vulkan_filter.h"
-
-#include "filters.h"
-#include "transpose.h"
-#include "video.h"
-
-typedef struct TransposeVulkanContext {
-    FFVulkanContext vkctx;
-
-    int initialized;
-    FFVkExecPool e;
-    AVVulkanDeviceQueueFamily *qf;
-    FFVulkanShader shd;
-
-    int dir;
-    int passthrough;
-} TransposeVulkanContext;
-
-static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
-{
-    int err;
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    TransposeVulkanContext *s = ctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-
-    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
-    FFVulkanShader *shd = &s->shd;
-    FFVkSPIRVCompiler *spv;
-    FFVulkanDescriptorSetBinding *desc;
-
-    spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
-    if (!s->qf) {
-        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
-        err = AVERROR(ENOTSUP);
-        goto fail;
-    }
-
-    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
-    RET(ff_vk_shader_init(vkctx, &s->shd, "transpose",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          NULL, 0,
-                          32, 1, 1,
-                          0));
-
-    desc = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name       = "input_images",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "readonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-        {
-            .name       = "output_images",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "writeonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 2, 0, 0));
-
-    GLSLC(0, void main()                                               );
-    GLSLC(0, {                                                         );
-    GLSLC(1,     ivec2 size;                                           );
-    GLSLC(1,     ivec2 pos = ivec2(gl_GlobalInvocationID.xy);          );
-    for (int i = 0; i < planes; i++) {
-        GLSLC(0,                                                       );
-        GLSLF(1, size = imageSize(output_images[%i]);                ,i);
-        GLSLC(1, if (IS_WITHIN(pos, size)) {                           );
-        if (s->dir == TRANSPOSE_CCLOCK)
-            GLSLF(2, vec4 res = imageLoad(input_images[%i], ivec2(size.y - pos.y, pos.x)); ,i);
-        else if (s->dir == TRANSPOSE_CLOCK_FLIP || s->dir == TRANSPOSE_CLOCK) {
-            GLSLF(2, vec4 res = imageLoad(input_images[%i], ivec2(size.yx - pos.yx));      ,i);
-            if (s->dir == TRANSPOSE_CLOCK)
-                GLSLC(2, pos = ivec2(pos.x, size.y - pos.y);           );
-        } else
-            GLSLF(2, vec4 res = imageLoad(input_images[%i], pos.yx);  ,i);
-        GLSLF(2,     imageStore(output_images[%i], pos, res);        ,i);
-        GLSLC(1, }                                                     );
-    }
-    GLSLC(0, }                                                         );
-
-    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
-
-    s->initialized = 1;
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-    if (spv)
-        spv->uninit(&spv);
-
-    return err;
-}
-
-static int filter_frame(AVFilterLink *inlink, AVFrame *in)
-{
-    int err;
-    AVFrame *out = NULL;
-    AVFilterContext *ctx = inlink->dst;
-    TransposeVulkanContext *s = ctx->priv;
-    AVFilterLink *outlink = ctx->outputs[0];
-
-    if (s->passthrough)
-        return ff_filter_frame(outlink, in);
-
-    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-    if (!out) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    if (!s->initialized)
-        RET(init_filter(ctx, in));
-
-    RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->shd, out, in,
-                                    VK_NULL_HANDLE, NULL, 0));
-
-    RET(av_frame_copy_props(out, in));
-
-    if (in->sample_aspect_ratio.num)
-        out->sample_aspect_ratio = in->sample_aspect_ratio;
-    else {
-        out->sample_aspect_ratio.num = in->sample_aspect_ratio.den;
-        out->sample_aspect_ratio.den = in->sample_aspect_ratio.num;
-    }
-
-    av_frame_free(&in);
-
-    return ff_filter_frame(outlink, out);
-
-fail:
-    av_frame_free(&in);
-    av_frame_free(&out);
-    return err;
-}
-
-static av_cold void transpose_vulkan_uninit(AVFilterContext *avctx)
-{
-    TransposeVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-
-    ff_vk_exec_pool_free(vkctx, &s->e);
-    ff_vk_shader_free(vkctx, &s->shd);
-
-    ff_vk_uninit(&s->vkctx);
-
-    s->initialized = 0;
-}
-
-static int config_props_output(AVFilterLink *outlink)
-{
-    FilterLink *outl = ff_filter_link(outlink);
-    AVFilterContext *avctx = outlink->src;
-    TransposeVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    AVFilterLink *inlink = avctx->inputs[0];
-    FilterLink *inl = ff_filter_link(inlink);
-
-    if ((inlink->w >= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_LANDSCAPE) ||
-        (inlink->w <= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_PORTRAIT)) {
-        av_log(avctx, AV_LOG_VERBOSE,
-               "w:%d h:%d -> w:%d h:%d (passthrough mode)\n",
-               inlink->w, inlink->h, inlink->w, inlink->h);
-        outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx);
-        return outl->hw_frames_ctx ? 0 : AVERROR(ENOMEM);
-    } else {
-        s->passthrough = TRANSPOSE_PT_TYPE_NONE;
-    }
-
-    vkctx->output_width  = inlink->h;
-    vkctx->output_height = inlink->w;
-
-    if (inlink->sample_aspect_ratio.num)
-        outlink->sample_aspect_ratio = av_div_q((AVRational) { 1, 1 },
-                                                inlink->sample_aspect_ratio);
-    else
-        outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
-
-    return ff_vk_filter_config_output(outlink);
-}
-
-#define OFFSET(x) offsetof(TransposeVulkanContext, x)
-#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
-
-static const AVOption transpose_vulkan_options[] = {
-    { "dir", "set transpose direction", OFFSET(dir), AV_OPT_TYPE_INT, { .i64 = TRANSPOSE_CCLOCK_FLIP }, 0, 7, FLAGS, .unit = "dir" },
-        { "cclock_flip", "rotate counter-clockwise with vertical flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK_FLIP }, .flags=FLAGS, .unit = "dir" },
-        { "clock",       "rotate clockwise",                            0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK       }, .flags=FLAGS, .unit = "dir" },
-        { "cclock",      "rotate counter-clockwise",                    0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK      }, .flags=FLAGS, .unit = "dir" },
-        { "clock_flip",  "rotate clockwise with vertical flip",         0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK_FLIP  }, .flags=FLAGS, .unit = "dir" },
-
-    { "passthrough", "do not apply transposition if the input matches the specified geometry",
-      OFFSET(passthrough), AV_OPT_TYPE_INT, {.i64=TRANSPOSE_PT_TYPE_NONE},  0, INT_MAX, FLAGS, .unit = "passthrough" },
-        { "none",      "always apply transposition",   0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_NONE},      INT_MIN, INT_MAX, FLAGS, .unit = "passthrough" },
-        { "portrait",  "preserve portrait geometry",   0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_PORTRAIT},  INT_MIN, INT_MAX, FLAGS, .unit = "passthrough" },
-        { "landscape", "preserve landscape geometry",  0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_LANDSCAPE}, INT_MIN, INT_MAX, FLAGS, .unit = "passthrough" },
-
-    { NULL }
-};
-
-AVFILTER_DEFINE_CLASS(transpose_vulkan);
-
-static const AVFilterPad transpose_vulkan_inputs[] = {
-    {
-        .name         = "default",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame = &filter_frame,
-        .config_props = &ff_vk_filter_config_input,
-    }
-};
-
-static const AVFilterPad transpose_vulkan_outputs[] = {
-    {
-        .name         = "default",
-        .type         = AVMEDIA_TYPE_VIDEO,
-        .config_props = &config_props_output,
-    }
-};
-
-const FFFilter ff_vf_transpose_vulkan = {
-    .p.name         = "transpose_vulkan",
-    .p.description  = NULL_IF_CONFIG_SMALL("Transpose Vulkan Filter"),
-    .p.priv_class   = &transpose_vulkan_class,
-    .p.flags        = AVFILTER_FLAG_HWDEVICE,
-    .priv_size      = sizeof(TransposeVulkanContext),
-    .init           = &ff_vk_filter_init,
-    .uninit         = &transpose_vulkan_uninit,
-    FILTER_INPUTS(transpose_vulkan_inputs),
-    FILTER_OUTPUTS(transpose_vulkan_outputs),
-    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
-    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
-};
-- 
2.49.1


From 42f2951e33ed10a48ab58529fcb69710693761f6 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:03:22 +0000
Subject: [PATCH 026/118] Changing vulkan file directory

---
 libavfilter/vulkan/vf_transpose_vulkan.c | 275 +++++++++++++++++++++++
 1 file changed, 275 insertions(+)
 create mode 100644 libavfilter/vulkan/vf_transpose_vulkan.c

diff --git a/libavfilter/vulkan/vf_transpose_vulkan.c b/libavfilter/vulkan/vf_transpose_vulkan.c
new file mode 100644
index 0000000000..1162c78588
--- /dev/null
+++ b/libavfilter/vulkan/vf_transpose_vulkan.c
@@ -0,0 +1,275 @@
+/*
+ * copyright (c) 2021 Wu Jianhua <jianhua.wu@intel.com>
+ * Copyright (c) Lynne
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/random_seed.h"
+#include "libavutil/opt.h"
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+#include "vulkan_filter.h"
+
+#include "libavfilter/filters.h"
+#include "libavfilter/transpose.h"
+#include "libavfilter/video.h"
+
+typedef struct TransposeVulkanContext {
+    FFVulkanContext vkctx;
+
+    int initialized;
+    FFVkExecPool e;
+    AVVulkanDeviceQueueFamily *qf;
+    FFVulkanShader shd;
+
+    int dir;
+    int passthrough;
+} TransposeVulkanContext;
+
+static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
+{
+    int err;
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    TransposeVulkanContext *s = ctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+
+    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
+    FFVulkanShader *shd = &s->shd;
+    FFVkSPIRVCompiler *spv;
+    FFVulkanDescriptorSetBinding *desc;
+
+    spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
+    if (!s->qf) {
+        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
+        err = AVERROR(ENOTSUP);
+        goto fail;
+    }
+
+    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
+    RET(ff_vk_shader_init(vkctx, &s->shd, "transpose",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          NULL, 0,
+                          32, 1, 1,
+                          0));
+
+    desc = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name       = "input_images",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "readonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+        {
+            .name       = "output_images",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "writeonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 2, 0, 0));
+
+    GLSLC(0, void main()                                               );
+    GLSLC(0, {                                                         );
+    GLSLC(1,     ivec2 size;                                           );
+    GLSLC(1,     ivec2 pos = ivec2(gl_GlobalInvocationID.xy);          );
+    for (int i = 0; i < planes; i++) {
+        GLSLC(0,                                                       );
+        GLSLF(1, size = imageSize(output_images[%i]);                ,i);
+        GLSLC(1, if (IS_WITHIN(pos, size)) {                           );
+        if (s->dir == TRANSPOSE_CCLOCK)
+            GLSLF(2, vec4 res = imageLoad(input_images[%i], ivec2(size.y - pos.y, pos.x)); ,i);
+        else if (s->dir == TRANSPOSE_CLOCK_FLIP || s->dir == TRANSPOSE_CLOCK) {
+            GLSLF(2, vec4 res = imageLoad(input_images[%i], ivec2(size.yx - pos.yx));      ,i);
+            if (s->dir == TRANSPOSE_CLOCK)
+                GLSLC(2, pos = ivec2(pos.x, size.y - pos.y);           );
+        } else
+            GLSLF(2, vec4 res = imageLoad(input_images[%i], pos.yx);  ,i);
+        GLSLF(2,     imageStore(output_images[%i], pos, res);        ,i);
+        GLSLC(1, }                                                     );
+    }
+    GLSLC(0, }                                                         );
+
+    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
+
+    s->initialized = 1;
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+    if (spv)
+        spv->uninit(&spv);
+
+    return err;
+}
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *in)
+{
+    int err;
+    AVFrame *out = NULL;
+    AVFilterContext *ctx = inlink->dst;
+    TransposeVulkanContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+
+    if (s->passthrough)
+        return ff_filter_frame(outlink, in);
+
+    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!out) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    if (!s->initialized)
+        RET(init_filter(ctx, in));
+
+    RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->shd, out, in,
+                                    VK_NULL_HANDLE, NULL, 0));
+
+    RET(av_frame_copy_props(out, in));
+
+    if (in->sample_aspect_ratio.num)
+        out->sample_aspect_ratio = in->sample_aspect_ratio;
+    else {
+        out->sample_aspect_ratio.num = in->sample_aspect_ratio.den;
+        out->sample_aspect_ratio.den = in->sample_aspect_ratio.num;
+    }
+
+    av_frame_free(&in);
+
+    return ff_filter_frame(outlink, out);
+
+fail:
+    av_frame_free(&in);
+    av_frame_free(&out);
+    return err;
+}
+
+static av_cold void transpose_vulkan_uninit(AVFilterContext *avctx)
+{
+    TransposeVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+
+    ff_vk_exec_pool_free(vkctx, &s->e);
+    ff_vk_shader_free(vkctx, &s->shd);
+
+    ff_vk_uninit(&s->vkctx);
+
+    s->initialized = 0;
+}
+
+static int config_props_output(AVFilterLink *outlink)
+{
+    FilterLink *outl = ff_filter_link(outlink);
+    AVFilterContext *avctx = outlink->src;
+    TransposeVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    AVFilterLink *inlink = avctx->inputs[0];
+    FilterLink *inl = ff_filter_link(inlink);
+
+    if ((inlink->w >= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_LANDSCAPE) ||
+        (inlink->w <= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_PORTRAIT)) {
+        av_log(avctx, AV_LOG_VERBOSE,
+               "w:%d h:%d -> w:%d h:%d (passthrough mode)\n",
+               inlink->w, inlink->h, inlink->w, inlink->h);
+        outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx);
+        return outl->hw_frames_ctx ? 0 : AVERROR(ENOMEM);
+    } else {
+        s->passthrough = TRANSPOSE_PT_TYPE_NONE;
+    }
+
+    vkctx->output_width  = inlink->h;
+    vkctx->output_height = inlink->w;
+
+    if (inlink->sample_aspect_ratio.num)
+        outlink->sample_aspect_ratio = av_div_q((AVRational) { 1, 1 },
+                                                inlink->sample_aspect_ratio);
+    else
+        outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
+
+    return ff_vk_filter_config_output(outlink);
+}
+
+#define OFFSET(x) offsetof(TransposeVulkanContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
+
+static const AVOption transpose_vulkan_options[] = {
+    { "dir", "set transpose direction", OFFSET(dir), AV_OPT_TYPE_INT, { .i64 = TRANSPOSE_CCLOCK_FLIP }, 0, 7, FLAGS, .unit = "dir" },
+        { "cclock_flip", "rotate counter-clockwise with vertical flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK_FLIP }, .flags=FLAGS, .unit = "dir" },
+        { "clock",       "rotate clockwise",                            0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK       }, .flags=FLAGS, .unit = "dir" },
+        { "cclock",      "rotate counter-clockwise",                    0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK      }, .flags=FLAGS, .unit = "dir" },
+        { "clock_flip",  "rotate clockwise with vertical flip",         0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK_FLIP  }, .flags=FLAGS, .unit = "dir" },
+
+    { "passthrough", "do not apply transposition if the input matches the specified geometry",
+      OFFSET(passthrough), AV_OPT_TYPE_INT, {.i64=TRANSPOSE_PT_TYPE_NONE},  0, INT_MAX, FLAGS, .unit = "passthrough" },
+        { "none",      "always apply transposition",   0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_NONE},      INT_MIN, INT_MAX, FLAGS, .unit = "passthrough" },
+        { "portrait",  "preserve portrait geometry",   0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_PORTRAIT},  INT_MIN, INT_MAX, FLAGS, .unit = "passthrough" },
+        { "landscape", "preserve landscape geometry",  0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_LANDSCAPE}, INT_MIN, INT_MAX, FLAGS, .unit = "passthrough" },
+
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(transpose_vulkan);
+
+static const AVFilterPad transpose_vulkan_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = &filter_frame,
+        .config_props = &ff_vk_filter_config_input,
+    }
+};
+
+static const AVFilterPad transpose_vulkan_outputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = &config_props_output,
+    }
+};
+
+const FFFilter ff_vf_transpose_vulkan = {
+    .p.name         = "transpose_vulkan",
+    .p.description  = NULL_IF_CONFIG_SMALL("Transpose Vulkan Filter"),
+    .p.priv_class   = &transpose_vulkan_class,
+    .p.flags        = AVFILTER_FLAG_HWDEVICE,
+    .priv_size      = sizeof(TransposeVulkanContext),
+    .init           = &ff_vk_filter_init,
+    .uninit         = &transpose_vulkan_uninit,
+    FILTER_INPUTS(transpose_vulkan_inputs),
+    FILTER_OUTPUTS(transpose_vulkan_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};
-- 
2.49.1


From d41036fd0ca230358cf26875df57e716f3306197 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:04:00 +0000
Subject: [PATCH 027/118] Changing vulkan file directory

---
 libavfilter/vf_xfade_vulkan.c | 725 ----------------------------------
 1 file changed, 725 deletions(-)
 delete mode 100644 libavfilter/vf_xfade_vulkan.c

diff --git a/libavfilter/vf_xfade_vulkan.c b/libavfilter/vf_xfade_vulkan.c
deleted file mode 100644
index 58e8797733..0000000000
--- a/libavfilter/vf_xfade_vulkan.c
+++ /dev/null
@@ -1,725 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/avassert.h"
-#include "libavutil/random_seed.h"
-#include "libavutil/opt.h"
-#include "libavutil/vulkan_spirv.h"
-#include "vulkan_filter.h"
-#include "filters.h"
-#include "video.h"
-
-#define IN_A  0
-#define IN_B  1
-#define IN_NB 2
-
-typedef struct XFadeParameters {
-    float progress;
-} XFadeParameters;
-
-typedef struct XFadeVulkanContext {
-    FFVulkanContext     vkctx;
-
-    int                 transition;
-    int64_t             duration;
-    int64_t             offset;
-
-    int                 initialized;
-    FFVkExecPool        e;
-    AVVulkanDeviceQueueFamily *qf;
-    FFVulkanShader      shd;
-    VkSampler           sampler;
-
-    // PTS when the fade should start (in IN_A timebase)
-    int64_t             start_pts;
-
-    // PTS offset between IN_A and IN_B
-    int64_t             inputs_offset_pts;
-
-    // Duration of the transition
-    int64_t             duration_pts;
-
-    // Current PTS of the first input (IN_A)
-    int64_t             pts;
-
-    // If frames are currently just passed through
-    // unmodified, like before and after the actual
-    // transition.
-    int                 passthrough;
-
-    int                 status[IN_NB];
-} XFadeVulkanContext;
-
-enum XFadeTransitions {
-    FADE,
-    WIPELEFT,
-    WIPERIGHT,
-    WIPEUP,
-    WIPEDOWN,
-    SLIDEDOWN,
-    SLIDEUP,
-    SLIDELEFT,
-    SLIDERIGHT,
-    CIRCLEOPEN,
-    CIRCLECLOSE,
-    DISSOLVE,
-    PIXELIZE,
-    WIPETL,
-    WIPETR,
-    WIPEBL,
-    WIPEBR,
-    NB_TRANSITIONS,
-};
-
-static const char transition_fade[] = {
-    C(0, void transition(int idx, ivec2 pos, float progress)                   )
-    C(0, {                                                                     )
-    C(1,     vec4 a = texture(a_images[idx], pos);                             )
-    C(1,     vec4 b = texture(b_images[idx], pos);                             )
-    C(1,     imageStore(output_images[idx], pos, mix(a, b, progress));         )
-    C(0, }                                                                     )
-};
-
-static const char transition_wipeleft[] = {
-    C(0, void transition(int idx, ivec2 pos, float progress)                   )
-    C(0, {                                                                     )
-    C(1,     ivec2 size = imageSize(output_images[idx]);                       )
-    C(1,     int  s = int(size.x * (1.0 - progress));                          )
-    C(1,     vec4 a = texture(a_images[idx], pos);                             )
-    C(1,     vec4 b = texture(b_images[idx], pos);                             )
-    C(1,     imageStore(output_images[idx], pos, pos.x > s ? b : a);           )
-    C(0, }                                                                     )
-};
-
-static const char transition_wiperight[] = {
-    C(0, void transition(int idx, ivec2 pos, float progress)                   )
-    C(0, {                                                                     )
-    C(1,     ivec2 size = imageSize(output_images[idx]);                       )
-    C(1,     int  s = int(size.x * progress);                                  )
-    C(1,     vec4 a = texture(a_images[idx], pos);                             )
-    C(1,     vec4 b = texture(b_images[idx], pos);                             )
-    C(1,     imageStore(output_images[idx], pos, pos.x > s ? a : b);           )
-    C(0, }                                                                     )
-};
-
-static const char transition_wipeup[] = {
-    C(0, void transition(int idx, ivec2 pos, float progress)                   )
-    C(0, {                                                                     )
-    C(1,     ivec2 size = imageSize(output_images[idx]);                       )
-    C(1,     int  s = int(size.y * (1.0 - progress));                          )
-    C(1,     vec4 a = texture(a_images[idx], pos);                             )
-    C(1,     vec4 b = texture(b_images[idx], pos);                             )
-    C(1,     imageStore(output_images[idx], pos, pos.y > s ? b : a);           )
-    C(0, }                                                                     )
-};
-
-static const char transition_wipedown[] = {
-    C(0, void transition(int idx, ivec2 pos, float progress)                   )
-    C(0, {                                                                     )
-    C(1,     ivec2 size = imageSize(output_images[idx]);                       )
-    C(1,     int  s = int(size.y * progress);                                  )
-    C(1,     vec4 a = texture(a_images[idx], pos);                             )
-    C(1,     vec4 b = texture(b_images[idx], pos);                             )
-    C(1,     imageStore(output_images[idx], pos, pos.y > s ? a : b);           )
-    C(0, }                                                                     )
-};
-
-#define SHADER_SLIDE_COMMON                                                              \
-    C(0, void slide(int idx, ivec2 pos, float progress, ivec2 direction)               ) \
-    C(0, {                                                                             ) \
-    C(1,     ivec2 size = imageSize(output_images[idx]);                               ) \
-    C(1,     ivec2 pi = ivec2(progress * size);                                        ) \
-    C(1,     ivec2 p = pos + pi * direction;                                           ) \
-    C(1,     ivec2 f = p % size;                                                       ) \
-    C(1,     f = f + size * ivec2(f.x < 0, f.y < 0);                                   ) \
-    C(1,     vec4 a = texture(a_images[idx], f);                                       ) \
-    C(1,     vec4 b = texture(b_images[idx], f);                                       ) \
-    C(1,     vec4 r = (p.y >= 0 && p.x >= 0 && size.y > p.y &&  size.x > p.x) ? a : b; ) \
-    C(1,     imageStore(output_images[idx], pos, r);                                   ) \
-    C(0, }                                                                             )
-
-static const char transition_slidedown[] = {
-    SHADER_SLIDE_COMMON
-    C(0, void transition(int idx, ivec2 pos, float progress)                   )
-    C(0, {                                                                     )
-    C(1,     slide(idx, pos, progress, ivec2(0, -1));                          )
-    C(0, }                                                                     )
-};
-
-static const char transition_slideup[] = {
-    SHADER_SLIDE_COMMON
-    C(0, void transition(int idx, ivec2 pos, float progress)                   )
-    C(0, {                                                                     )
-    C(1,     slide(idx, pos, progress, ivec2(0, +1));                          )
-    C(0, }                                                                     )
-};
-
-static const char transition_slideleft[] = {
-    SHADER_SLIDE_COMMON
-    C(0, void transition(int idx, ivec2 pos, float progress)                   )
-    C(0, {                                                                     )
-    C(1,     slide(idx, pos, progress, ivec2(+1, 0));                          )
-    C(0, }                                                                     )
-};
-
-static const char transition_slideright[] = {
-    SHADER_SLIDE_COMMON
-    C(0, void transition(int idx, ivec2 pos, float progress)                   )
-    C(0, {                                                                     )
-    C(1,     slide(idx, pos, progress, ivec2(-1, 0));                          )
-    C(0, }                                                                     )
-};
-
-#define SHADER_CIRCLE_COMMON                                                     \
-    C(0, void circle(int idx, ivec2 pos, float progress, bool open)            ) \
-    C(0, {                                                                     ) \
-    C(1,     const ivec2 half_size = imageSize(output_images[idx]) / 2;        ) \
-    C(1,     const float z = dot(half_size, half_size);                        ) \
-    C(1,     float p = ((open ? (1.0 - progress) : progress) - 0.5) * 3.0;     ) \
-    C(1,     ivec2 dsize = pos - half_size;                                    ) \
-    C(1,     float sm = dot(dsize, dsize) / z + p;                             ) \
-    C(1,     vec4 a = texture(a_images[idx], pos);                             ) \
-    C(1,     vec4 b = texture(b_images[idx], pos);                             ) \
-    C(1,     imageStore(output_images[idx], pos, \
-                        mix(open ? b : a, open ? a : b, \
-                            smoothstep(0.f, 1.f, sm)));                        ) \
-    C(0, }                                                                     )
-
-static const char transition_circleopen[] = {
-    SHADER_CIRCLE_COMMON
-    C(0, void transition(int idx, ivec2 pos, float progress)                   )
-    C(0, {                                                                     )
-    C(1,     circle(idx, pos, progress, true);                                 )
-    C(0, }                                                                     )
-};
-
-static const char transition_circleclose[] = {
-    SHADER_CIRCLE_COMMON
-    C(0, void transition(int idx, ivec2 pos, float progress)                   )
-    C(0, {                                                                     )
-    C(1,     circle(idx, pos, progress, false);                                )
-    C(0, }                                                                     )
-};
-
-#define SHADER_FRAND_FUNC                                                        \
-    C(0, float frand(vec2 v)                                                   ) \
-    C(0, {                                                                     ) \
-    C(1,     return fract(sin(dot(v, vec2(12.9898, 78.233))) * 43758.545);     ) \
-    C(0, }                                                                     )
-
-static const char transition_dissolve[] = {
-    SHADER_FRAND_FUNC
-    C(0, void transition(int idx, ivec2 pos, float progress)                   )
-    C(0, {                                                                     )
-    C(1,     float sm = frand(pos) * 2.0 + (1.0 - progress) * 2.0 - 1.5;       )
-    C(1,     vec4 a = texture(a_images[idx], pos);                             )
-    C(1,     vec4 b = texture(b_images[idx], pos);                             )
-    C(1,     imageStore(output_images[idx], pos, sm >= 0.5 ? a : b);           )
-    C(0, }                                                                     )
-};
-
-static const char transition_pixelize[] = {
-    C(0, void transition(int idx, ivec2 pos, float progress)                                  )
-    C(0, {                                                                                    )
-    C(1,     ivec2 size = imageSize(output_images[idx]);                                      )
-    C(1,     float d = min(progress, 1.0 - progress);                                         )
-    C(1,     float dist = ceil(d * 50.0) / 50.0;                                              )
-    C(1,     float sq = 2.0 * dist * min(size.x, size.y) / 20.0;                              )
-    C(1,     float sx = dist > 0.0 ? min((floor(pos.x / sq) + 0.5) * sq, size.x - 1) : pos.x; )
-    C(1,     float sy = dist > 0.0 ? min((floor(pos.y / sq) + 0.5) * sq, size.y - 1) : pos.y; )
-    C(1,     vec4 a = texture(a_images[idx], vec2(sx, sy));                                   )
-    C(1,     vec4 b = texture(b_images[idx], vec2(sx, sy));                                   )
-    C(1,     imageStore(output_images[idx], pos, mix(a, b, progress));                        )
-    C(0, }                                                                                    )
-};
-
-static const char transition_wipetl[] = {
-    C(0, void transition(int idx, ivec2 pos, float progress)                                  )
-    C(0, {                                                                                    )
-    C(1,     ivec2 size = imageSize(output_images[idx]);                                      )
-    C(1,     float zw = size.x * (1.0 - progress);                                            )
-    C(1,     float zh = size.y * (1.0 - progress);                                            )
-    C(1,     vec4 a = texture(a_images[idx], pos);                                            )
-    C(1,     vec4 b = texture(b_images[idx], pos);                                            )
-    C(1,     imageStore(output_images[idx], pos, (pos.y <= zh && pos.x <= zw) ? a : b);       )
-    C(0, }                                                                                    )
-};
-
-static const char transition_wipetr[] = {
-    C(0, void transition(int idx, ivec2 pos, float progress)                                  )
-    C(0, {                                                                                    )
-    C(1,     ivec2 size = imageSize(output_images[idx]);                                      )
-    C(1,     float zw = size.x * (progress);                                                  )
-    C(1,     float zh = size.y * (1.0 - progress);                                            )
-    C(1,     vec4 a = texture(a_images[idx], pos);                                            )
-    C(1,     vec4 b = texture(b_images[idx], pos);                                            )
-    C(1,     imageStore(output_images[idx], pos, (pos.y <= zh && pos.x > zw) ? a : b);        )
-    C(0, }                                                                                    )
-};
-
-static const char transition_wipebl[] = {
-    C(0, void transition(int idx, ivec2 pos, float progress)                                  )
-    C(0, {                                                                                    )
-    C(1,     ivec2 size = imageSize(output_images[idx]);                                      )
-    C(1,     float zw = size.x * (1.0 - progress);                                            )
-    C(1,     float zh = size.y * (progress);                                                  )
-    C(1,     vec4 a = texture(a_images[idx], pos);                                            )
-    C(1,     vec4 b = texture(b_images[idx], pos);                                            )
-    C(1,     imageStore(output_images[idx], pos, (pos.y > zh && pos.x <= zw) ? a : b);        )
-    C(0, }                                                                                    )
-};
-
-static const char transition_wipebr[] = {
-    C(0, void transition(int idx, ivec2 pos, float progress)                                  )
-    C(0, {                                                                                    )
-    C(1,     ivec2 size = imageSize(output_images[idx]);                                      )
-    C(1,     float zw = size.x * (progress);                                                  )
-    C(1,     float zh = size.y * (progress);                                                  )
-    C(1,     vec4 a = texture(a_images[idx], pos);                                            )
-    C(1,     vec4 b = texture(b_images[idx], pos);                                            )
-    C(1,     imageStore(output_images[idx], pos, (pos.y > zh && pos.x > zw) ? a : b);         )
-    C(0, }                                                                                    )
-};
-
-static const char* transitions_map[NB_TRANSITIONS] = {
-    [FADE]          = transition_fade,
-    [WIPELEFT]      = transition_wipeleft,
-    [WIPERIGHT]     = transition_wiperight,
-    [WIPEUP]        = transition_wipeup,
-    [WIPEDOWN]      = transition_wipedown,
-    [SLIDEDOWN]     = transition_slidedown,
-    [SLIDEUP]       = transition_slideup,
-    [SLIDELEFT]     = transition_slideleft,
-    [SLIDERIGHT]    = transition_slideright,
-    [CIRCLEOPEN]    = transition_circleopen,
-    [CIRCLECLOSE]   = transition_circleclose,
-    [DISSOLVE]      = transition_dissolve,
-    [PIXELIZE]      = transition_pixelize,
-    [WIPETL]        = transition_wipetl,
-    [WIPETR]        = transition_wipetr,
-    [WIPEBL]        = transition_wipebl,
-    [WIPEBR]        = transition_wipebr,
-};
-
-static av_cold int init_vulkan(AVFilterContext *avctx)
-{
-    int err = 0;
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    XFadeVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
-    FFVulkanShader *shd = &s->shd;
-    FFVkSPIRVCompiler *spv;
-    FFVulkanDescriptorSetBinding *desc;
-
-    spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
-    if (!s->qf) {
-        av_log(avctx, AV_LOG_ERROR, "Device has no compute queues\n");
-        err = AVERROR(ENOTSUP);
-        goto fail;
-    }
-
-    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
-    RET(ff_vk_init_sampler(vkctx, &s->sampler, 1, VK_FILTER_NEAREST));
-    RET(ff_vk_shader_init(vkctx, &s->shd, "xfade",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          NULL, 0,
-                          32, 32, 1,
-                          0));
-
-    desc = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name       = "a_images",
-            .type       = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-            .samplers   = DUP_SAMPLER(s->sampler),
-        },
-        {
-            .name       = "b_images",
-            .type       = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-            .samplers   = DUP_SAMPLER(s->sampler),
-        },
-        {
-            .name       = "output_images",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "writeonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 3, 0, 0));
-
-    GLSLC(0, layout(push_constant, std430) uniform pushConstants {                 );
-    GLSLC(1,    float progress;                                                    );
-    GLSLC(0, };                                                                    );
-
-    ff_vk_shader_add_push_const(&s->shd, 0, sizeof(XFadeParameters),
-                                VK_SHADER_STAGE_COMPUTE_BIT);
-
-    // Add the right transition type function to the shader
-    GLSLD(transitions_map[s->transition]);
-
-    GLSLC(0, void main()                                                  );
-    GLSLC(0, {                                                            );
-    GLSLC(1,     ivec2 pos = ivec2(gl_GlobalInvocationID.xy);             );
-    GLSLF(1,     int planes = %i;                                  ,planes);
-    GLSLC(1,     for (int i = 0; i < planes; i++) {                       );
-    GLSLC(2,        transition(i, pos, progress);                         );
-    GLSLC(1,     }                                                        );
-    GLSLC(0, }                                                            );
-
-    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
-
-    s->initialized = 1;
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-    if (spv)
-        spv->uninit(&spv);
-
-    return err;
-}
-
-static int xfade_frame(AVFilterContext *avctx, AVFrame *frame_a, AVFrame *frame_b)
-{
-    int err;
-    AVFilterLink *outlink = avctx->outputs[0];
-    XFadeVulkanContext *s = avctx->priv;
-    float progress;
-
-    AVFrame *output = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-    if (!output) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    if (!s->initialized) {
-        AVHWFramesContext *a_fc = (AVHWFramesContext*)frame_a->hw_frames_ctx->data;
-        AVHWFramesContext *b_fc = (AVHWFramesContext*)frame_b->hw_frames_ctx->data;
-        if (a_fc->sw_format != b_fc->sw_format) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "Currently the sw format of the first input needs to match the second!\n");
-            return AVERROR(EINVAL);
-        }
-        RET(init_vulkan(avctx));
-    }
-
-    RET(av_frame_copy_props(output, frame_a));
-    output->pts = s->pts;
-
-    progress = av_clipf((float)(s->pts - s->start_pts) / s->duration_pts,
-                        0.f, 1.f);
-
-    RET(ff_vk_filter_process_Nin(&s->vkctx, &s->e, &s->shd, output,
-                                 (AVFrame *[]){ frame_a, frame_b }, 2, s->sampler,
-                                 &(XFadeParameters){ progress }, sizeof(XFadeParameters)));
-
-    return ff_filter_frame(outlink, output);
-
-fail:
-    av_frame_free(&output);
-    return err;
-}
-
-static int config_props_output(AVFilterLink *outlink)
-{
-    int err;
-    AVFilterContext *avctx = outlink->src;
-    XFadeVulkanContext *s = avctx->priv;
-    AVFilterLink *inlink_a = avctx->inputs[IN_A];
-    AVFilterLink *inlink_b = avctx->inputs[IN_B];
-    FilterLink *il = ff_filter_link(inlink_a);
-    FilterLink *ol = ff_filter_link(outlink);
-
-    if (inlink_a->w != inlink_b->w || inlink_a->h != inlink_b->h) {
-        av_log(avctx, AV_LOG_ERROR, "First input link %s parameters "
-               "(size %dx%d) do not match the corresponding "
-               "second input link %s parameters (size %dx%d)\n",
-               avctx->input_pads[IN_A].name, inlink_a->w, inlink_a->h,
-               avctx->input_pads[IN_B].name, inlink_b->w, inlink_b->h);
-        return AVERROR(EINVAL);
-    }
-
-    if (inlink_a->time_base.num != inlink_b->time_base.num ||
-        inlink_a->time_base.den != inlink_b->time_base.den) {
-        av_log(avctx, AV_LOG_ERROR, "First input link %s timebase "
-               "(%d/%d) does not match the corresponding "
-               "second input link %s timebase (%d/%d)\n",
-               avctx->input_pads[IN_A].name, inlink_a->time_base.num, inlink_a->time_base.den,
-               avctx->input_pads[IN_B].name, inlink_b->time_base.num, inlink_b->time_base.den);
-        return AVERROR(EINVAL);
-    }
-
-    s->start_pts = s->inputs_offset_pts = AV_NOPTS_VALUE;
-
-    outlink->time_base = inlink_a->time_base;
-    ol->frame_rate = il->frame_rate;
-    outlink->sample_aspect_ratio = inlink_a->sample_aspect_ratio;
-
-    if (s->duration)
-        s->duration_pts = av_rescale_q(s->duration, AV_TIME_BASE_Q, inlink_a->time_base);
-    RET(ff_vk_filter_config_output(outlink));
-
-fail:
-    return err;
-}
-
-static int forward_frame(XFadeVulkanContext *s,
-                         AVFilterLink *inlink, AVFilterLink *outlink)
-{
-    int64_t status_pts;
-    int ret = 0, status;
-    AVFrame *frame = NULL;
-
-    ret = ff_inlink_consume_frame(inlink, &frame);
-    if (ret < 0)
-        return ret;
-
-    if (ret > 0) {
-        // If we do not have an offset yet, it's because we
-        // never got a first input. Just offset to 0
-        if (s->inputs_offset_pts == AV_NOPTS_VALUE)
-            s->inputs_offset_pts = -frame->pts;
-
-        // We got a frame, nothing to do other than adjusting the timestamp
-        frame->pts += s->inputs_offset_pts;
-        return ff_filter_frame(outlink, frame);
-    }
-
-    // Forward status with our timestamp
-    if (ff_inlink_acknowledge_status(inlink, &status, &status_pts)) {
-        if (s->inputs_offset_pts == AV_NOPTS_VALUE)
-            s->inputs_offset_pts = -status_pts;
-
-        ff_outlink_set_status(outlink, status, status_pts + s->inputs_offset_pts);
-        return 0;
-    }
-
-    // No frame available, request one if needed
-    if (ff_outlink_frame_wanted(outlink))
-        ff_inlink_request_frame(inlink);
-
-    return 0;
-}
-
-static int activate(AVFilterContext *avctx)
-{
-    XFadeVulkanContext *s = avctx->priv;
-    AVFilterLink *in_a = avctx->inputs[IN_A];
-    AVFilterLink *in_b = avctx->inputs[IN_B];
-    AVFilterLink *outlink = avctx->outputs[0];
-    int64_t status_pts;
-
-    FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, avctx);
-
-    // Check if we already transitioned or IN_A ended prematurely,
-    // in which case just forward the frames from IN_B with adjusted
-    // timestamps until EOF.
-    if (s->status[IN_A] && !s->status[IN_B])
-        return forward_frame(s, in_b, outlink);
-
-    // We did not finish transitioning yet and the first stream
-    // did not end either, so check if there are more frames to consume.
-    if (ff_inlink_check_available_frame(in_a)) {
-        AVFrame *peeked_frame = ff_inlink_peek_frame(in_a, 0);
-        s->pts = peeked_frame->pts;
-
-        if (s->start_pts == AV_NOPTS_VALUE)
-            s->start_pts =
-                s->pts + av_rescale_q(s->offset, AV_TIME_BASE_Q, in_a->time_base);
-
-        // Check if we are not yet transitioning, in which case
-        // just request and forward the input frame.
-        if (s->start_pts > s->pts) {
-            AVFrame *frame_a = NULL;
-            s->passthrough = 1;
-            ff_inlink_consume_frame(in_a, &frame_a);
-            return ff_filter_frame(outlink, frame_a);
-        }
-        s->passthrough = 0;
-
-        // We are transitioning, so we need a frame from IN_B
-        if (ff_inlink_check_available_frame(in_b)) {
-            int ret;
-            AVFrame *frame_a = NULL, *frame_b = NULL;
-            ff_inlink_consume_frame(avctx->inputs[IN_A], &frame_a);
-            ff_inlink_consume_frame(avctx->inputs[IN_B], &frame_b);
-
-            // Calculate PTS offset to first input
-            if (s->inputs_offset_pts == AV_NOPTS_VALUE)
-                s->inputs_offset_pts = s->pts - frame_b->pts;
-
-            // Check if we finished transitioning, in which case we
-            // report back EOF to IN_A as it is no longer needed.
-            if (s->pts - s->start_pts > s->duration_pts) {
-                s->status[IN_A] = AVERROR_EOF;
-                ff_inlink_set_status(in_a, AVERROR_EOF);
-                s->passthrough = 1;
-            }
-            ret = xfade_frame(avctx, frame_a, frame_b);
-            av_frame_free(&frame_a);
-            av_frame_free(&frame_b);
-            return ret;
-        }
-
-        // We did not get a frame from IN_B, check its status.
-        if (ff_inlink_acknowledge_status(in_b, &s->status[IN_B], &status_pts)) {
-            // We should transition, but IN_B is EOF so just report EOF output now.
-            ff_outlink_set_status(outlink, s->status[IN_B], s->pts);
-            return 0;
-        }
-
-        // We did not get a frame for IN_B but no EOF either, so just request more.
-        if (ff_outlink_frame_wanted(outlink)) {
-            ff_inlink_request_frame(in_b);
-            return 0;
-        }
-    }
-
-    // We did not get a frame from IN_A, check its status.
-    if (ff_inlink_acknowledge_status(in_a, &s->status[IN_A], &status_pts)) {
-        // No more frames from IN_A, do not report EOF though, we will just
-        // forward the IN_B frames in the next activate calls.
-        s->passthrough = 1;
-        ff_filter_set_ready(avctx, 100);
-        return 0;
-    }
-
-    // We have no frames yet from IN_A and no EOF, so request some.
-    if (ff_outlink_frame_wanted(outlink)) {
-        ff_inlink_request_frame(in_a);
-        return 0;
-    }
-
-    return FFERROR_NOT_READY;
-}
-
-static av_cold void uninit(AVFilterContext *avctx)
-{
-    XFadeVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    FFVulkanFunctions *vk = &vkctx->vkfn;
-
-    ff_vk_exec_pool_free(vkctx, &s->e);
-    ff_vk_shader_free(vkctx, &s->shd);
-
-    if (s->sampler)
-        vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler,
-                           vkctx->hwctx->alloc);
-
-    ff_vk_uninit(&s->vkctx);
-
-    s->initialized = 0;
-}
-
-static AVFrame *get_video_buffer(AVFilterLink *inlink, int w, int h)
-{
-    XFadeVulkanContext *s = inlink->dst->priv;
-
-    return s->passthrough ?
-        ff_null_get_video_buffer   (inlink, w, h) :
-        ff_default_get_video_buffer(inlink, w, h);
-}
-
-#define OFFSET(x) offsetof(XFadeVulkanContext, x)
-#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
-
-static const AVOption xfade_vulkan_options[] = {
-    { "transition", "set cross fade transition", OFFSET(transition), AV_OPT_TYPE_INT, {.i64=FADE}, 0, NB_TRANSITIONS-1, FLAGS, .unit = "transition" },
-        { "fade", "fade transition", 0, AV_OPT_TYPE_CONST, {.i64=FADE}, 0, 0, FLAGS, .unit = "transition" },
-        { "wipeleft", "wipe left transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPELEFT}, 0, 0, FLAGS, .unit = "transition" },
-        { "wiperight", "wipe right transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPERIGHT}, 0, 0, FLAGS, .unit = "transition" },
-        { "wipeup", "wipe up transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEUP}, 0, 0, FLAGS, .unit = "transition" },
-        { "wipedown", "wipe down transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEDOWN}, 0, 0, FLAGS, .unit = "transition" },
-        { "slidedown", "slide down transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDEDOWN}, 0, 0, FLAGS, .unit = "transition" },
-        { "slideup", "slide up transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDEUP}, 0, 0, FLAGS, .unit = "transition" },
-        { "slideleft", "slide left transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDELEFT}, 0, 0, FLAGS, .unit = "transition" },
-        { "slideright", "slide right transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDERIGHT}, 0, 0, FLAGS, .unit = "transition" },
-        { "circleopen", "circleopen transition", 0, AV_OPT_TYPE_CONST, {.i64=CIRCLEOPEN}, 0, 0, FLAGS, .unit = "transition" },
-        { "circleclose", "circleclose transition", 0, AV_OPT_TYPE_CONST, {.i64=CIRCLECLOSE}, 0, 0, FLAGS, .unit = "transition" },
-        { "dissolve", "dissolve transition", 0, AV_OPT_TYPE_CONST, {.i64=DISSOLVE}, 0, 0, FLAGS, .unit = "transition" },
-        { "pixelize", "pixelize transition", 0, AV_OPT_TYPE_CONST, {.i64=PIXELIZE}, 0, 0, FLAGS, .unit = "transition" },
-        { "wipetl", "wipe top left transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPETL}, 0, 0, FLAGS, .unit = "transition" },
-        { "wipetr", "wipe top right transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPETR}, 0, 0, FLAGS, .unit = "transition" },
-        { "wipebl", "wipe bottom left transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEBL}, 0, 0, FLAGS, .unit = "transition" },
-        { "wipebr", "wipe bottom right transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEBR}, 0, 0, FLAGS, .unit = "transition" },
-    { "duration", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=1000000}, 0, 60000000, FLAGS },
-    { "offset",   "set cross fade start relative to first input stream", OFFSET(offset), AV_OPT_TYPE_DURATION, {.i64=0}, INT64_MIN, INT64_MAX, FLAGS },
-    { NULL }
-};
-
-AVFILTER_DEFINE_CLASS(xfade_vulkan);
-
-static const AVFilterPad xfade_vulkan_inputs[] = {
-    {
-        .name             = "main",
-        .type             = AVMEDIA_TYPE_VIDEO,
-        .get_buffer.video = &get_video_buffer,
-        .config_props     = &ff_vk_filter_config_input,
-    },
-    {
-        .name             = "xfade",
-        .type             = AVMEDIA_TYPE_VIDEO,
-        .get_buffer.video = &get_video_buffer,
-        .config_props     = &ff_vk_filter_config_input,
-    },
-};
-
-static const AVFilterPad xfade_vulkan_outputs[] = {
-    {
-        .name          = "default",
-        .type          = AVMEDIA_TYPE_VIDEO,
-        .config_props  = &config_props_output,
-    },
-};
-
-const FFFilter ff_vf_xfade_vulkan = {
-    .p.name          = "xfade_vulkan",
-    .p.description   = NULL_IF_CONFIG_SMALL("Cross fade one video with another video."),
-    .p.priv_class    = &xfade_vulkan_class,
-    .p.flags         = AVFILTER_FLAG_HWDEVICE,
-    .priv_size       = sizeof(XFadeVulkanContext),
-    .init            = &ff_vk_filter_init,
-    .uninit          = &uninit,
-    .activate        = &activate,
-    FILTER_INPUTS(xfade_vulkan_inputs),
-    FILTER_OUTPUTS(xfade_vulkan_outputs),
-    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
-    .flags_internal  = FF_FILTER_FLAG_HWFRAME_AWARE,
-};
-- 
2.49.1


From 8de5912697bec07602562495fac65ed63b2b9e7c Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:04:41 +0000
Subject: [PATCH 028/118] Changing vulkan file directory

---
 libavfilter/vulkan/vf_xfade_vulkan.c | 725 +++++++++++++++++++++++++++
 1 file changed, 725 insertions(+)
 create mode 100644 libavfilter/vulkan/vf_xfade_vulkan.c

diff --git a/libavfilter/vulkan/vf_xfade_vulkan.c b/libavfilter/vulkan/vf_xfade_vulkan.c
new file mode 100644
index 0000000000..b125ae4d12
--- /dev/null
+++ b/libavfilter/vulkan/vf_xfade_vulkan.c
@@ -0,0 +1,725 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/avassert.h"
+#include "libavutil/random_seed.h"
+#include "libavutil/opt.h"
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+#include "vulkan_filter.h"
+#include "libavfilter/filters.h"
+#include "libavfilter/video.h"
+
+#define IN_A  0
+#define IN_B  1
+#define IN_NB 2
+
+typedef struct XFadeParameters {
+    float progress;
+} XFadeParameters;
+
+typedef struct XFadeVulkanContext {
+    FFVulkanContext     vkctx;
+
+    int                 transition;
+    int64_t             duration;
+    int64_t             offset;
+
+    int                 initialized;
+    FFVkExecPool        e;
+    AVVulkanDeviceQueueFamily *qf;
+    FFVulkanShader      shd;
+    VkSampler           sampler;
+
+    // PTS when the fade should start (in IN_A timebase)
+    int64_t             start_pts;
+
+    // PTS offset between IN_A and IN_B
+    int64_t             inputs_offset_pts;
+
+    // Duration of the transition
+    int64_t             duration_pts;
+
+    // Current PTS of the first input (IN_A)
+    int64_t             pts;
+
+    // If frames are currently just passed through
+    // unmodified, like before and after the actual
+    // transition.
+    int                 passthrough;
+
+    int                 status[IN_NB];
+} XFadeVulkanContext;
+
+enum XFadeTransitions {
+    FADE,
+    WIPELEFT,
+    WIPERIGHT,
+    WIPEUP,
+    WIPEDOWN,
+    SLIDEDOWN,
+    SLIDEUP,
+    SLIDELEFT,
+    SLIDERIGHT,
+    CIRCLEOPEN,
+    CIRCLECLOSE,
+    DISSOLVE,
+    PIXELIZE,
+    WIPETL,
+    WIPETR,
+    WIPEBL,
+    WIPEBR,
+    NB_TRANSITIONS,
+};
+
+static const char transition_fade[] = {
+    C(0, void transition(int idx, ivec2 pos, float progress)                   )
+    C(0, {                                                                     )
+    C(1,     vec4 a = texture(a_images[idx], pos);                             )
+    C(1,     vec4 b = texture(b_images[idx], pos);                             )
+    C(1,     imageStore(output_images[idx], pos, mix(a, b, progress));         )
+    C(0, }                                                                     )
+};
+
+static const char transition_wipeleft[] = {
+    C(0, void transition(int idx, ivec2 pos, float progress)                   )
+    C(0, {                                                                     )
+    C(1,     ivec2 size = imageSize(output_images[idx]);                       )
+    C(1,     int  s = int(size.x * (1.0 - progress));                          )
+    C(1,     vec4 a = texture(a_images[idx], pos);                             )
+    C(1,     vec4 b = texture(b_images[idx], pos);                             )
+    C(1,     imageStore(output_images[idx], pos, pos.x > s ? b : a);           )
+    C(0, }                                                                     )
+};
+
+static const char transition_wiperight[] = {
+    C(0, void transition(int idx, ivec2 pos, float progress)                   )
+    C(0, {                                                                     )
+    C(1,     ivec2 size = imageSize(output_images[idx]);                       )
+    C(1,     int  s = int(size.x * progress);                                  )
+    C(1,     vec4 a = texture(a_images[idx], pos);                             )
+    C(1,     vec4 b = texture(b_images[idx], pos);                             )
+    C(1,     imageStore(output_images[idx], pos, pos.x > s ? a : b);           )
+    C(0, }                                                                     )
+};
+
+static const char transition_wipeup[] = {
+    C(0, void transition(int idx, ivec2 pos, float progress)                   )
+    C(0, {                                                                     )
+    C(1,     ivec2 size = imageSize(output_images[idx]);                       )
+    C(1,     int  s = int(size.y * (1.0 - progress));                          )
+    C(1,     vec4 a = texture(a_images[idx], pos);                             )
+    C(1,     vec4 b = texture(b_images[idx], pos);                             )
+    C(1,     imageStore(output_images[idx], pos, pos.y > s ? b : a);           )
+    C(0, }                                                                     )
+};
+
+static const char transition_wipedown[] = {
+    C(0, void transition(int idx, ivec2 pos, float progress)                   )
+    C(0, {                                                                     )
+    C(1,     ivec2 size = imageSize(output_images[idx]);                       )
+    C(1,     int  s = int(size.y * progress);                                  )
+    C(1,     vec4 a = texture(a_images[idx], pos);                             )
+    C(1,     vec4 b = texture(b_images[idx], pos);                             )
+    C(1,     imageStore(output_images[idx], pos, pos.y > s ? a : b);           )
+    C(0, }                                                                     )
+};
+
+#define SHADER_SLIDE_COMMON                                                              \
+    C(0, void slide(int idx, ivec2 pos, float progress, ivec2 direction)               ) \
+    C(0, {                                                                             ) \
+    C(1,     ivec2 size = imageSize(output_images[idx]);                               ) \
+    C(1,     ivec2 pi = ivec2(progress * size);                                        ) \
+    C(1,     ivec2 p = pos + pi * direction;                                           ) \
+    C(1,     ivec2 f = p % size;                                                       ) \
+    C(1,     f = f + size * ivec2(f.x < 0, f.y < 0);                                   ) \
+    C(1,     vec4 a = texture(a_images[idx], f);                                       ) \
+    C(1,     vec4 b = texture(b_images[idx], f);                                       ) \
+    C(1,     vec4 r = (p.y >= 0 && p.x >= 0 && size.y > p.y &&  size.x > p.x) ? a : b; ) \
+    C(1,     imageStore(output_images[idx], pos, r);                                   ) \
+    C(0, }                                                                             )
+
+static const char transition_slidedown[] = {
+    SHADER_SLIDE_COMMON
+    C(0, void transition(int idx, ivec2 pos, float progress)                   )
+    C(0, {                                                                     )
+    C(1,     slide(idx, pos, progress, ivec2(0, -1));                          )
+    C(0, }                                                                     )
+};
+
+static const char transition_slideup[] = {
+    SHADER_SLIDE_COMMON
+    C(0, void transition(int idx, ivec2 pos, float progress)                   )
+    C(0, {                                                                     )
+    C(1,     slide(idx, pos, progress, ivec2(0, +1));                          )
+    C(0, }                                                                     )
+};
+
+static const char transition_slideleft[] = {
+    SHADER_SLIDE_COMMON
+    C(0, void transition(int idx, ivec2 pos, float progress)                   )
+    C(0, {                                                                     )
+    C(1,     slide(idx, pos, progress, ivec2(+1, 0));                          )
+    C(0, }                                                                     )
+};
+
+static const char transition_slideright[] = {
+    SHADER_SLIDE_COMMON
+    C(0, void transition(int idx, ivec2 pos, float progress)                   )
+    C(0, {                                                                     )
+    C(1,     slide(idx, pos, progress, ivec2(-1, 0));                          )
+    C(0, }                                                                     )
+};
+
+#define SHADER_CIRCLE_COMMON                                                     \
+    C(0, void circle(int idx, ivec2 pos, float progress, bool open)            ) \
+    C(0, {                                                                     ) \
+    C(1,     const ivec2 half_size = imageSize(output_images[idx]) / 2;        ) \
+    C(1,     const float z = dot(half_size, half_size);                        ) \
+    C(1,     float p = ((open ? (1.0 - progress) : progress) - 0.5) * 3.0;     ) \
+    C(1,     ivec2 dsize = pos - half_size;                                    ) \
+    C(1,     float sm = dot(dsize, dsize) / z + p;                             ) \
+    C(1,     vec4 a = texture(a_images[idx], pos);                             ) \
+    C(1,     vec4 b = texture(b_images[idx], pos);                             ) \
+    C(1,     imageStore(output_images[idx], pos, \
+                        mix(open ? b : a, open ? a : b, \
+                            smoothstep(0.f, 1.f, sm)));                        ) \
+    C(0, }                                                                     )
+
+static const char transition_circleopen[] = {
+    SHADER_CIRCLE_COMMON
+    C(0, void transition(int idx, ivec2 pos, float progress)                   )
+    C(0, {                                                                     )
+    C(1,     circle(idx, pos, progress, true);                                 )
+    C(0, }                                                                     )
+};
+
+static const char transition_circleclose[] = {
+    SHADER_CIRCLE_COMMON
+    C(0, void transition(int idx, ivec2 pos, float progress)                   )
+    C(0, {                                                                     )
+    C(1,     circle(idx, pos, progress, false);                                )
+    C(0, }                                                                     )
+};
+
+#define SHADER_FRAND_FUNC                                                        \
+    C(0, float frand(vec2 v)                                                   ) \
+    C(0, {                                                                     ) \
+    C(1,     return fract(sin(dot(v, vec2(12.9898, 78.233))) * 43758.545);     ) \
+    C(0, }                                                                     )
+
+static const char transition_dissolve[] = {
+    SHADER_FRAND_FUNC
+    C(0, void transition(int idx, ivec2 pos, float progress)                   )
+    C(0, {                                                                     )
+    C(1,     float sm = frand(pos) * 2.0 + (1.0 - progress) * 2.0 - 1.5;       )
+    C(1,     vec4 a = texture(a_images[idx], pos);                             )
+    C(1,     vec4 b = texture(b_images[idx], pos);                             )
+    C(1,     imageStore(output_images[idx], pos, sm >= 0.5 ? a : b);           )
+    C(0, }                                                                     )
+};
+
+static const char transition_pixelize[] = {
+    C(0, void transition(int idx, ivec2 pos, float progress)                                  )
+    C(0, {                                                                                    )
+    C(1,     ivec2 size = imageSize(output_images[idx]);                                      )
+    C(1,     float d = min(progress, 1.0 - progress);                                         )
+    C(1,     float dist = ceil(d * 50.0) / 50.0;                                              )
+    C(1,     float sq = 2.0 * dist * min(size.x, size.y) / 20.0;                              )
+    C(1,     float sx = dist > 0.0 ? min((floor(pos.x / sq) + 0.5) * sq, size.x - 1) : pos.x; )
+    C(1,     float sy = dist > 0.0 ? min((floor(pos.y / sq) + 0.5) * sq, size.y - 1) : pos.y; )
+    C(1,     vec4 a = texture(a_images[idx], vec2(sx, sy));                                   )
+    C(1,     vec4 b = texture(b_images[idx], vec2(sx, sy));                                   )
+    C(1,     imageStore(output_images[idx], pos, mix(a, b, progress));                        )
+    C(0, }                                                                                    )
+};
+
+static const char transition_wipetl[] = {
+    C(0, void transition(int idx, ivec2 pos, float progress)                                  )
+    C(0, {                                                                                    )
+    C(1,     ivec2 size = imageSize(output_images[idx]);                                      )
+    C(1,     float zw = size.x * (1.0 - progress);                                            )
+    C(1,     float zh = size.y * (1.0 - progress);                                            )
+    C(1,     vec4 a = texture(a_images[idx], pos);                                            )
+    C(1,     vec4 b = texture(b_images[idx], pos);                                            )
+    C(1,     imageStore(output_images[idx], pos, (pos.y <= zh && pos.x <= zw) ? a : b);       )
+    C(0, }                                                                                    )
+};
+
+static const char transition_wipetr[] = {
+    C(0, void transition(int idx, ivec2 pos, float progress)                                  )
+    C(0, {                                                                                    )
+    C(1,     ivec2 size = imageSize(output_images[idx]);                                      )
+    C(1,     float zw = size.x * (progress);                                                  )
+    C(1,     float zh = size.y * (1.0 - progress);                                            )
+    C(1,     vec4 a = texture(a_images[idx], pos);                                            )
+    C(1,     vec4 b = texture(b_images[idx], pos);                                            )
+    C(1,     imageStore(output_images[idx], pos, (pos.y <= zh && pos.x > zw) ? a : b);        )
+    C(0, }                                                                                    )
+};
+
+static const char transition_wipebl[] = {
+    C(0, void transition(int idx, ivec2 pos, float progress)                                  )
+    C(0, {                                                                                    )
+    C(1,     ivec2 size = imageSize(output_images[idx]);                                      )
+    C(1,     float zw = size.x * (1.0 - progress);                                            )
+    C(1,     float zh = size.y * (progress);                                                  )
+    C(1,     vec4 a = texture(a_images[idx], pos);                                            )
+    C(1,     vec4 b = texture(b_images[idx], pos);                                            )
+    C(1,     imageStore(output_images[idx], pos, (pos.y > zh && pos.x <= zw) ? a : b);        )
+    C(0, }                                                                                    )
+};
+
+static const char transition_wipebr[] = {
+    C(0, void transition(int idx, ivec2 pos, float progress)                                  )
+    C(0, {                                                                                    )
+    C(1,     ivec2 size = imageSize(output_images[idx]);                                      )
+    C(1,     float zw = size.x * (progress);                                                  )
+    C(1,     float zh = size.y * (progress);                                                  )
+    C(1,     vec4 a = texture(a_images[idx], pos);                                            )
+    C(1,     vec4 b = texture(b_images[idx], pos);                                            )
+    C(1,     imageStore(output_images[idx], pos, (pos.y > zh && pos.x > zw) ? a : b);         )
+    C(0, }                                                                                    )
+};
+
+static const char* transitions_map[NB_TRANSITIONS] = {
+    [FADE]          = transition_fade,
+    [WIPELEFT]      = transition_wipeleft,
+    [WIPERIGHT]     = transition_wiperight,
+    [WIPEUP]        = transition_wipeup,
+    [WIPEDOWN]      = transition_wipedown,
+    [SLIDEDOWN]     = transition_slidedown,
+    [SLIDEUP]       = transition_slideup,
+    [SLIDELEFT]     = transition_slideleft,
+    [SLIDERIGHT]    = transition_slideright,
+    [CIRCLEOPEN]    = transition_circleopen,
+    [CIRCLECLOSE]   = transition_circleclose,
+    [DISSOLVE]      = transition_dissolve,
+    [PIXELIZE]      = transition_pixelize,
+    [WIPETL]        = transition_wipetl,
+    [WIPETR]        = transition_wipetr,
+    [WIPEBL]        = transition_wipebl,
+    [WIPEBR]        = transition_wipebr,
+};
+
+static av_cold int init_vulkan(AVFilterContext *avctx)
+{
+    int err = 0;
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    XFadeVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
+    FFVulkanShader *shd = &s->shd;
+    FFVkSPIRVCompiler *spv;
+    FFVulkanDescriptorSetBinding *desc;
+
+    spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
+    if (!s->qf) {
+        av_log(avctx, AV_LOG_ERROR, "Device has no compute queues\n");
+        err = AVERROR(ENOTSUP);
+        goto fail;
+    }
+
+    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
+    RET(ff_vk_init_sampler(vkctx, &s->sampler, 1, VK_FILTER_NEAREST));
+    RET(ff_vk_shader_init(vkctx, &s->shd, "xfade",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          NULL, 0,
+                          32, 32, 1,
+                          0));
+
+    desc = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name       = "a_images",
+            .type       = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+            .samplers   = DUP_SAMPLER(s->sampler),
+        },
+        {
+            .name       = "b_images",
+            .type       = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+            .samplers   = DUP_SAMPLER(s->sampler),
+        },
+        {
+            .name       = "output_images",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "writeonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 3, 0, 0));
+
+    GLSLC(0, layout(push_constant, std430) uniform pushConstants {                 );
+    GLSLC(1,    float progress;                                                    );
+    GLSLC(0, };                                                                    );
+
+    ff_vk_shader_add_push_const(&s->shd, 0, sizeof(XFadeParameters),
+                                VK_SHADER_STAGE_COMPUTE_BIT);
+
+    // Add the right transition type function to the shader
+    GLSLD(transitions_map[s->transition]);
+
+    GLSLC(0, void main()                                                  );
+    GLSLC(0, {                                                            );
+    GLSLC(1,     ivec2 pos = ivec2(gl_GlobalInvocationID.xy);             );
+    GLSLF(1,     int planes = %i;                                  ,planes);
+    GLSLC(1,     for (int i = 0; i < planes; i++) {                       );
+    GLSLC(2,        transition(i, pos, progress);                         );
+    GLSLC(1,     }                                                        );
+    GLSLC(0, }                                                            );
+
+    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
+
+    s->initialized = 1;
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+    if (spv)
+        spv->uninit(&spv);
+
+    return err;
+}
+
+static int xfade_frame(AVFilterContext *avctx, AVFrame *frame_a, AVFrame *frame_b)
+{
+    int err;
+    AVFilterLink *outlink = avctx->outputs[0];
+    XFadeVulkanContext *s = avctx->priv;
+    float progress;
+
+    AVFrame *output = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!output) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    if (!s->initialized) {
+        AVHWFramesContext *a_fc = (AVHWFramesContext*)frame_a->hw_frames_ctx->data;
+        AVHWFramesContext *b_fc = (AVHWFramesContext*)frame_b->hw_frames_ctx->data;
+        if (a_fc->sw_format != b_fc->sw_format) {
+            av_log(avctx, AV_LOG_ERROR,
+                   "Currently the sw format of the first input needs to match the second!\n");
+            return AVERROR(EINVAL);
+        }
+        RET(init_vulkan(avctx));
+    }
+
+    RET(av_frame_copy_props(output, frame_a));
+    output->pts = s->pts;
+
+    progress = av_clipf((float)(s->pts - s->start_pts) / s->duration_pts,
+                        0.f, 1.f);
+
+    RET(ff_vk_filter_process_Nin(&s->vkctx, &s->e, &s->shd, output,
+                                 (AVFrame *[]){ frame_a, frame_b }, 2, s->sampler,
+                                 &(XFadeParameters){ progress }, sizeof(XFadeParameters)));
+
+    return ff_filter_frame(outlink, output);
+
+fail:
+    av_frame_free(&output);
+    return err;
+}
+
+static int config_props_output(AVFilterLink *outlink)
+{
+    int err;
+    AVFilterContext *avctx = outlink->src;
+    XFadeVulkanContext *s = avctx->priv;
+    AVFilterLink *inlink_a = avctx->inputs[IN_A];
+    AVFilterLink *inlink_b = avctx->inputs[IN_B];
+    FilterLink *il = ff_filter_link(inlink_a);
+    FilterLink *ol = ff_filter_link(outlink);
+
+    if (inlink_a->w != inlink_b->w || inlink_a->h != inlink_b->h) {
+        av_log(avctx, AV_LOG_ERROR, "First input link %s parameters "
+               "(size %dx%d) do not match the corresponding "
+               "second input link %s parameters (size %dx%d)\n",
+               avctx->input_pads[IN_A].name, inlink_a->w, inlink_a->h,
+               avctx->input_pads[IN_B].name, inlink_b->w, inlink_b->h);
+        return AVERROR(EINVAL);
+    }
+
+    if (inlink_a->time_base.num != inlink_b->time_base.num ||
+        inlink_a->time_base.den != inlink_b->time_base.den) {
+        av_log(avctx, AV_LOG_ERROR, "First input link %s timebase "
+               "(%d/%d) does not match the corresponding "
+               "second input link %s timebase (%d/%d)\n",
+               avctx->input_pads[IN_A].name, inlink_a->time_base.num, inlink_a->time_base.den,
+               avctx->input_pads[IN_B].name, inlink_b->time_base.num, inlink_b->time_base.den);
+        return AVERROR(EINVAL);
+    }
+
+    s->start_pts = s->inputs_offset_pts = AV_NOPTS_VALUE;
+
+    outlink->time_base = inlink_a->time_base;
+    ol->frame_rate = il->frame_rate;
+    outlink->sample_aspect_ratio = inlink_a->sample_aspect_ratio;
+
+    if (s->duration)
+        s->duration_pts = av_rescale_q(s->duration, AV_TIME_BASE_Q, inlink_a->time_base);
+    RET(ff_vk_filter_config_output(outlink));
+
+fail:
+    return err;
+}
+
+static int forward_frame(XFadeVulkanContext *s,
+                         AVFilterLink *inlink, AVFilterLink *outlink)
+{
+    int64_t status_pts;
+    int ret = 0, status;
+    AVFrame *frame = NULL;
+
+    ret = ff_inlink_consume_frame(inlink, &frame);
+    if (ret < 0)
+        return ret;
+
+    if (ret > 0) {
+        // If we do not have an offset yet, it's because we
+        // never got a first input. Just offset to 0
+        if (s->inputs_offset_pts == AV_NOPTS_VALUE)
+            s->inputs_offset_pts = -frame->pts;
+
+        // We got a frame, nothing to do other than adjusting the timestamp
+        frame->pts += s->inputs_offset_pts;
+        return ff_filter_frame(outlink, frame);
+    }
+
+    // Forward status with our timestamp
+    if (ff_inlink_acknowledge_status(inlink, &status, &status_pts)) {
+        if (s->inputs_offset_pts == AV_NOPTS_VALUE)
+            s->inputs_offset_pts = -status_pts;
+
+        ff_outlink_set_status(outlink, status, status_pts + s->inputs_offset_pts);
+        return 0;
+    }
+
+    // No frame available, request one if needed
+    if (ff_outlink_frame_wanted(outlink))
+        ff_inlink_request_frame(inlink);
+
+    return 0;
+}
+
+static int activate(AVFilterContext *avctx)
+{
+    XFadeVulkanContext *s = avctx->priv;
+    AVFilterLink *in_a = avctx->inputs[IN_A];
+    AVFilterLink *in_b = avctx->inputs[IN_B];
+    AVFilterLink *outlink = avctx->outputs[0];
+    int64_t status_pts;
+
+    FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, avctx);
+
+    // Check if we already transitioned or IN_A ended prematurely,
+    // in which case just forward the frames from IN_B with adjusted
+    // timestamps until EOF.
+    if (s->status[IN_A] && !s->status[IN_B])
+        return forward_frame(s, in_b, outlink);
+
+    // We did not finish transitioning yet and the first stream
+    // did not end either, so check if there are more frames to consume.
+    if (ff_inlink_check_available_frame(in_a)) {
+        AVFrame *peeked_frame = ff_inlink_peek_frame(in_a, 0);
+        s->pts = peeked_frame->pts;
+
+        if (s->start_pts == AV_NOPTS_VALUE)
+            s->start_pts =
+                s->pts + av_rescale_q(s->offset, AV_TIME_BASE_Q, in_a->time_base);
+
+        // Check if we are not yet transitioning, in which case
+        // just request and forward the input frame.
+        if (s->start_pts > s->pts) {
+            AVFrame *frame_a = NULL;
+            s->passthrough = 1;
+            ff_inlink_consume_frame(in_a, &frame_a);
+            return ff_filter_frame(outlink, frame_a);
+        }
+        s->passthrough = 0;
+
+        // We are transitioning, so we need a frame from IN_B
+        if (ff_inlink_check_available_frame(in_b)) {
+            int ret;
+            AVFrame *frame_a = NULL, *frame_b = NULL;
+            ff_inlink_consume_frame(avctx->inputs[IN_A], &frame_a);
+            ff_inlink_consume_frame(avctx->inputs[IN_B], &frame_b);
+
+            // Calculate PTS offset to first input
+            if (s->inputs_offset_pts == AV_NOPTS_VALUE)
+                s->inputs_offset_pts = s->pts - frame_b->pts;
+
+            // Check if we finished transitioning, in which case we
+            // report back EOF to IN_A as it is no longer needed.
+            if (s->pts - s->start_pts > s->duration_pts) {
+                s->status[IN_A] = AVERROR_EOF;
+                ff_inlink_set_status(in_a, AVERROR_EOF);
+                s->passthrough = 1;
+            }
+            ret = xfade_frame(avctx, frame_a, frame_b);
+            av_frame_free(&frame_a);
+            av_frame_free(&frame_b);
+            return ret;
+        }
+
+        // We did not get a frame from IN_B, check its status.
+        if (ff_inlink_acknowledge_status(in_b, &s->status[IN_B], &status_pts)) {
+            // We should transition, but IN_B is EOF so just report EOF output now.
+            ff_outlink_set_status(outlink, s->status[IN_B], s->pts);
+            return 0;
+        }
+
+        // We did not get a frame for IN_B but no EOF either, so just request more.
+        if (ff_outlink_frame_wanted(outlink)) {
+            ff_inlink_request_frame(in_b);
+            return 0;
+        }
+    }
+
+    // We did not get a frame from IN_A, check its status.
+    if (ff_inlink_acknowledge_status(in_a, &s->status[IN_A], &status_pts)) {
+        // No more frames from IN_A, do not report EOF though, we will just
+        // forward the IN_B frames in the next activate calls.
+        s->passthrough = 1;
+        ff_filter_set_ready(avctx, 100);
+        return 0;
+    }
+
+    // We have no frames yet from IN_A and no EOF, so request some.
+    if (ff_outlink_frame_wanted(outlink)) {
+        ff_inlink_request_frame(in_a);
+        return 0;
+    }
+
+    return FFERROR_NOT_READY;
+}
+
+static av_cold void uninit(AVFilterContext *avctx)
+{
+    XFadeVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    FFVulkanFunctions *vk = &vkctx->vkfn;
+
+    ff_vk_exec_pool_free(vkctx, &s->e);
+    ff_vk_shader_free(vkctx, &s->shd);
+
+    if (s->sampler)
+        vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler,
+                           vkctx->hwctx->alloc);
+
+    ff_vk_uninit(&s->vkctx);
+
+    s->initialized = 0;
+}
+
+static AVFrame *get_video_buffer(AVFilterLink *inlink, int w, int h)
+{
+    XFadeVulkanContext *s = inlink->dst->priv;
+
+    return s->passthrough ?
+        ff_null_get_video_buffer   (inlink, w, h) :
+        ff_default_get_video_buffer(inlink, w, h);
+}
+
+#define OFFSET(x) offsetof(XFadeVulkanContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
+
+static const AVOption xfade_vulkan_options[] = {
+    { "transition", "set cross fade transition", OFFSET(transition), AV_OPT_TYPE_INT, {.i64=FADE}, 0, NB_TRANSITIONS-1, FLAGS, .unit = "transition" },
+        { "fade", "fade transition", 0, AV_OPT_TYPE_CONST, {.i64=FADE}, 0, 0, FLAGS, .unit = "transition" },
+        { "wipeleft", "wipe left transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPELEFT}, 0, 0, FLAGS, .unit = "transition" },
+        { "wiperight", "wipe right transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPERIGHT}, 0, 0, FLAGS, .unit = "transition" },
+        { "wipeup", "wipe up transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEUP}, 0, 0, FLAGS, .unit = "transition" },
+        { "wipedown", "wipe down transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEDOWN}, 0, 0, FLAGS, .unit = "transition" },
+        { "slidedown", "slide down transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDEDOWN}, 0, 0, FLAGS, .unit = "transition" },
+        { "slideup", "slide up transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDEUP}, 0, 0, FLAGS, .unit = "transition" },
+        { "slideleft", "slide left transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDELEFT}, 0, 0, FLAGS, .unit = "transition" },
+        { "slideright", "slide right transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDERIGHT}, 0, 0, FLAGS, .unit = "transition" },
+        { "circleopen", "circleopen transition", 0, AV_OPT_TYPE_CONST, {.i64=CIRCLEOPEN}, 0, 0, FLAGS, .unit = "transition" },
+        { "circleclose", "circleclose transition", 0, AV_OPT_TYPE_CONST, {.i64=CIRCLECLOSE}, 0, 0, FLAGS, .unit = "transition" },
+        { "dissolve", "dissolve transition", 0, AV_OPT_TYPE_CONST, {.i64=DISSOLVE}, 0, 0, FLAGS, .unit = "transition" },
+        { "pixelize", "pixelize transition", 0, AV_OPT_TYPE_CONST, {.i64=PIXELIZE}, 0, 0, FLAGS, .unit = "transition" },
+        { "wipetl", "wipe top left transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPETL}, 0, 0, FLAGS, .unit = "transition" },
+        { "wipetr", "wipe top right transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPETR}, 0, 0, FLAGS, .unit = "transition" },
+        { "wipebl", "wipe bottom left transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEBL}, 0, 0, FLAGS, .unit = "transition" },
+        { "wipebr", "wipe bottom right transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEBR}, 0, 0, FLAGS, .unit = "transition" },
+    { "duration", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=1000000}, 0, 60000000, FLAGS },
+    { "offset",   "set cross fade start relative to first input stream", OFFSET(offset), AV_OPT_TYPE_DURATION, {.i64=0}, INT64_MIN, INT64_MAX, FLAGS },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(xfade_vulkan);
+
+static const AVFilterPad xfade_vulkan_inputs[] = {
+    {
+        .name             = "main",
+        .type             = AVMEDIA_TYPE_VIDEO,
+        .get_buffer.video = &get_video_buffer,
+        .config_props     = &ff_vk_filter_config_input,
+    },
+    {
+        .name             = "xfade",
+        .type             = AVMEDIA_TYPE_VIDEO,
+        .get_buffer.video = &get_video_buffer,
+        .config_props     = &ff_vk_filter_config_input,
+    },
+};
+
+static const AVFilterPad xfade_vulkan_outputs[] = {
+    {
+        .name          = "default",
+        .type          = AVMEDIA_TYPE_VIDEO,
+        .config_props  = &config_props_output,
+    },
+};
+
+const FFFilter ff_vf_xfade_vulkan = {
+    .p.name          = "xfade_vulkan",
+    .p.description   = NULL_IF_CONFIG_SMALL("Cross fade one video with another video."),
+    .p.priv_class    = &xfade_vulkan_class,
+    .p.flags         = AVFILTER_FLAG_HWDEVICE,
+    .priv_size       = sizeof(XFadeVulkanContext),
+    .init            = &ff_vk_filter_init,
+    .uninit          = &uninit,
+    .activate        = &activate,
+    FILTER_INPUTS(xfade_vulkan_inputs),
+    FILTER_OUTPUTS(xfade_vulkan_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
+    .flags_internal  = FF_FILTER_FLAG_HWFRAME_AWARE,
+};
-- 
2.49.1


From 3da68608435db38690f37502a661121950d0abe3 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:05:04 +0000
Subject: [PATCH 029/118] Changing vulkan file directory

---
 libavfilter/vsrc_testsrc_vulkan.c | 380 ------------------------------
 1 file changed, 380 deletions(-)
 delete mode 100644 libavfilter/vsrc_testsrc_vulkan.c

diff --git a/libavfilter/vsrc_testsrc_vulkan.c b/libavfilter/vsrc_testsrc_vulkan.c
deleted file mode 100644
index cb3c787213..0000000000
--- a/libavfilter/vsrc_testsrc_vulkan.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Copyright (c) Lynne
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/random_seed.h"
-#include "libavutil/csp.h"
-#include "libavutil/opt.h"
-#include "libavutil/vulkan_spirv.h"
-#include "vulkan_filter.h"
-#include "filters.h"
-#include "colorspace.h"
-#include "video.h"
-
-enum TestSrcVulkanMode {
-    TESTSRC_COLOR,
-};
-
-typedef struct TestSrcVulkanPushData {
-    float color_comp[4];
-} TestSrcVulkanPushData;
-
-typedef struct TestSrcVulkanContext {
-    FFVulkanContext vkctx;
-
-    int initialized;
-    FFVkExecPool e;
-    AVVulkanDeviceQueueFamily *qf;
-    FFVulkanShader shd;
-
-    /* Only used by color_vulkan */
-    uint8_t color_rgba[4];
-
-    TestSrcVulkanPushData opts;
-
-    int w, h;
-    int pw, ph;
-    char *out_format_string;
-    enum AVColorRange out_range;
-    unsigned int nb_frame;
-    AVRational time_base, frame_rate;
-    int64_t pts;
-    int64_t duration;           ///< duration expressed in microseconds
-    AVRational sar;             ///< sample aspect ratio
-    int draw_once;              ///< draw only the first frame, always put out the same picture
-    int draw_once_reset;        ///< draw only the first frame or in case of reset
-    AVFrame *picref;            ///< cached reference containing the painted picture
-} TestSrcVulkanContext;
-
-static av_cold int init_filter(AVFilterContext *ctx, enum TestSrcVulkanMode mode)
-{
-    int err;
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    TestSrcVulkanContext *s = ctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
-    FFVulkanShader *shd = &s->shd;
-    FFVkSPIRVCompiler *spv;
-    FFVulkanDescriptorSetBinding *desc_set;
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->vkctx.output_format);
-
-    spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
-    if (!s->qf) {
-        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
-        err = AVERROR(ENOTSUP);
-        goto fail;
-    }
-
-    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
-    RET(ff_vk_shader_init(vkctx, &s->shd, "scale",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          NULL, 0,
-                          32, 32, 1,
-                          0));
-
-    GLSLC(0, layout(push_constant, std430) uniform pushConstants {        );
-    GLSLC(1,    vec4 color_comp;                                          );
-    GLSLC(0, };                                                           );
-    GLSLC(0,                                                              );
-
-    ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts),
-                                VK_SHADER_STAGE_COMPUTE_BIT);
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name       = "output_img",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
-            .mem_quali  = "writeonly",
-            .dimensions = 2,
-            .elems      = planes,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc_set, 1, 0, 0));
-
-    GLSLC(0, void main()                                                  );
-    GLSLC(0, {                                                            );
-    GLSLC(1,     ivec2 pos = ivec2(gl_GlobalInvocationID.xy);             );
-    if (mode == TESTSRC_COLOR) {
-        double rgb2yuv[3][3];
-        double rgbad[4];
-        double yuvad[4];
-
-        enum AVColorSpace csp;
-        const AVLumaCoefficients *luma = NULL;
-
-        s->draw_once = 1;
-
-        if (desc->flags & AV_PIX_FMT_FLAG_RGB)
-            csp = AVCOL_SPC_RGB;
-        else
-            csp = AVCOL_SPC_SMPTE170M;
-
-        if (!(desc->flags & AV_PIX_FMT_FLAG_RGB) && !(luma = av_csp_luma_coeffs_from_avcsp(csp)))
-            return AVERROR(EINVAL);
-        else if (!(desc->flags & AV_PIX_FMT_FLAG_RGB))
-            ff_fill_rgb2yuv_table(luma, rgb2yuv);
-
-        for (int i = 0; i < 4; i++)
-            rgbad[i] = s->color_rgba[i] / 255.0;
-
-        if (!(desc->flags & AV_PIX_FMT_FLAG_RGB))
-            ff_matrix_mul_3x3_vec(yuvad, rgbad, rgb2yuv);
-        else
-            memcpy(yuvad, rgbad, sizeof(rgbad));
-
-        yuvad[3] = rgbad[3];
-
-        if (!(desc->flags & AV_PIX_FMT_FLAG_RGB)) {
-            for (int i = 0; i < 3; i++) {
-                int chroma = (!(desc->flags & AV_PIX_FMT_FLAG_RGB) && i > 0);
-                if (s->out_range == AVCOL_RANGE_MPEG) {
-                    yuvad[i] *= (chroma ? 224.0 : 219.0) / 255.0;
-                    yuvad[i] += (chroma ? 128.0 :  16.0) / 255.0;
-                } else if (chroma) {
-                    yuvad[i] += 0.5;
-                }
-            }
-        }
-
-        /* Ensure we place the alpha appropriately for gray formats */
-        if (desc->nb_components <= 2)
-            yuvad[1] = yuvad[3];
-
-        for (int i = 0; i < 4; i++)
-            s->opts.color_comp[i] = yuvad[i];
-
-        GLSLC(1,     vec4 r;                                                  );
-        GLSLC(0,                                                              );
-        for (int i = 0, c_off = 0; i < planes; i++) {
-            for (int c = 0; c < desc->nb_components; c++) {
-                if (desc->comp[c].plane == i) {
-                    int off = desc->comp[c].offset / (FFALIGN(desc->comp[c].depth, 8)/8);
-                    GLSLF(1, r[%i] = color_comp[%i];             ,off, c_off++);
-                }
-            }
-            GLSLF(1, imageStore(output_img[%i], pos, r);                    ,i);
-            GLSLC(0,                                                          );
-        }
-    }
-    GLSLC(0, }                                                            );
-
-    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
-
-    s->initialized = 1;
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-    if (spv)
-        spv->uninit(&spv);
-
-    return err;
-}
-
-static int testsrc_vulkan_activate(AVFilterContext *ctx)
-{
-    int err;
-    AVFilterLink *outlink = ctx->outputs[0];
-    TestSrcVulkanContext *s = ctx->priv;
-    AVFrame *frame;
-
-    if (!s->initialized) {
-        enum TestSrcVulkanMode mode = TESTSRC_COLOR;
-        err = init_filter(ctx, mode);
-        if (err < 0)
-            return err;
-    }
-
-    if (!ff_outlink_frame_wanted(outlink))
-        return FFERROR_NOT_READY;
-    if (s->duration >= 0 &&
-        av_rescale_q(s->pts, s->time_base, AV_TIME_BASE_Q) >= s->duration) {
-        ff_outlink_set_status(outlink, AVERROR_EOF, s->pts);
-        return 0;
-    }
-
-    if (s->draw_once) {
-        if (s->draw_once_reset) {
-            av_frame_free(&s->picref);
-            s->draw_once_reset = 0;
-        }
-        if (!s->picref) {
-            s->picref = ff_get_video_buffer(outlink, s->w, s->h);
-            if (!s->picref)
-                return AVERROR(ENOMEM);
-
-            err = ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->shd, s->picref, NULL,
-                                              VK_NULL_HANDLE, &s->opts, sizeof(s->opts));
-            if (err < 0)
-                return err;
-        }
-        frame = av_frame_clone(s->picref);
-    } else {
-        frame = ff_get_video_buffer(outlink, s->w, s->h);
-    }
-
-    if (!frame)
-        return AVERROR(ENOMEM);
-
-    frame->pts                 = s->pts;
-    frame->duration            = 1;
-    frame->flags               = AV_FRAME_FLAG_KEY;
-    frame->pict_type           = AV_PICTURE_TYPE_I;
-    frame->sample_aspect_ratio = s->sar;
-    if (!s->draw_once) {
-        err = ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->shd, frame, NULL,
-                                          VK_NULL_HANDLE, &s->opts, sizeof(s->opts));
-        if (err < 0) {
-            av_frame_free(&frame);
-            return err;
-        }
-    }
-
-    s->pts++;
-    s->nb_frame++;
-
-    return ff_filter_frame(outlink, frame);
-}
-
-static int testsrc_vulkan_config_props(AVFilterLink *outlink)
-{
-    int err;
-    FilterLink *l = ff_filter_link(outlink);
-    TestSrcVulkanContext *s = outlink->src->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-
-    if (!s->out_format_string) {
-        vkctx->output_format = AV_PIX_FMT_YUV444P;
-    } else {
-        vkctx->output_format = av_get_pix_fmt(s->out_format_string);
-        if (vkctx->output_format == AV_PIX_FMT_NONE) {
-            av_log(vkctx, AV_LOG_ERROR, "Invalid output format.\n");
-            return AVERROR(EINVAL);
-        }
-    }
-
-    err = ff_vk_filter_init_context(outlink->src, vkctx, NULL,
-                                    s->w, s->h, vkctx->output_format);
-    if (err < 0)
-        return err;
-
-    l->hw_frames_ctx = av_buffer_ref(vkctx->frames_ref);
-    if (!l->hw_frames_ctx)
-        return AVERROR(ENOMEM);
-
-    s->time_base = av_inv_q(s->frame_rate);
-    s->nb_frame = 0;
-    s->pts = 0;
-
-    s->vkctx.output_width = s->w;
-    s->vkctx.output_height = s->h;
-    outlink->w = s->w;
-    outlink->h = s->h;
-    outlink->sample_aspect_ratio = s->sar;
-    l->frame_rate = s->frame_rate;
-    outlink->time_base  = s->time_base;
-
-    return 0;
-}
-
-static void testsrc_vulkan_uninit(AVFilterContext *avctx)
-{
-    TestSrcVulkanContext *s = avctx->priv;
-    FFVulkanContext *vkctx = &s->vkctx;
-
-    av_frame_free(&s->picref);
-
-    ff_vk_exec_pool_free(vkctx, &s->e);
-    ff_vk_shader_free(vkctx, &s->shd);
-
-    ff_vk_uninit(&s->vkctx);
-
-    s->initialized = 0;
-}
-
-#define OFFSET(x) offsetof(TestSrcVulkanContext, x)
-#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
-
-#define COMMON_OPTS                                                                                                                           \
-    { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, { .str = "1920x1080" }, 0, 0, FLAGS },                                     \
-    { "s",    "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, { .str = "1920x1080" }, 0, 0, FLAGS },                                     \
-                                                                                                                                              \
-    { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, { .str = "60" }, 0, INT_MAX, FLAGS },                             \
-    { "r",    "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, { .str = "60" }, 0, INT_MAX, FLAGS },                             \
-                                                                                                                                              \
-    { "duration", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT64_MAX, FLAGS },                        \
-    { "d",        "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT64_MAX, FLAGS },                        \
-                                                                                                                                              \
-    { "sar", "set video sample aspect ratio", OFFSET(sar), AV_OPT_TYPE_RATIONAL, { .dbl = 1 },  0, INT_MAX, FLAGS },                          \
-                                                                                                                                              \
-    { "format", "Output video format (software format of hardware frames)", OFFSET(out_format_string), AV_OPT_TYPE_STRING, .flags = FLAGS },
-
-static const AVOption color_vulkan_options[] = {
-    { "color", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGS },
-    { "c",     "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGS },
-    COMMON_OPTS
-    { "out_range", "Output colour range (from 0 to 2) (default 0)", OFFSET(out_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED}, AVCOL_RANGE_UNSPECIFIED, AVCOL_RANGE_JPEG, .flags = FLAGS, .unit = "range" },
-        { "full", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, .unit = "range" },
-        { "limited", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, .unit = "range" },
-        { "jpeg", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, .unit = "range" },
-        { "mpeg", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, .unit = "range" },
-        { "tv", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, .unit = "range" },
-        { "pc", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, .unit = "range" },
-    { NULL },
-};
-
-AVFILTER_DEFINE_CLASS(color_vulkan);
-
-static const AVFilterPad testsrc_vulkan_outputs[] = {
-    {
-        .name = "default",
-        .type = AVMEDIA_TYPE_VIDEO,
-        .config_props = testsrc_vulkan_config_props,
-    },
-};
-
-const FFFilter ff_vsrc_color_vulkan = {
-    .p.name         = "color_vulkan",
-    .p.description  = NULL_IF_CONFIG_SMALL("Generate a constant color (Vulkan)"),
-    .p.inputs       = NULL,
-    .p.flags        = AVFILTER_FLAG_HWDEVICE,
-    .p.priv_class   = &color_vulkan_class,
-    .priv_size      = sizeof(TestSrcVulkanContext),
-    .init           = &ff_vk_filter_init,
-    .uninit         = &testsrc_vulkan_uninit,
-    .activate       = testsrc_vulkan_activate,
-    FILTER_OUTPUTS(testsrc_vulkan_outputs),
-    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
-    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
-};
-- 
2.49.1


From 6595f8ef44db685d10f38768882f2c8870b4bb74 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:05:37 +0000
Subject: [PATCH 030/118] Changing vulkan file directory

---
 libavfilter/vulkan/vsrc_testsrc_vulkan.c | 380 +++++++++++++++++++++++
 1 file changed, 380 insertions(+)
 create mode 100644 libavfilter/vulkan/vsrc_testsrc_vulkan.c

diff --git a/libavfilter/vulkan/vsrc_testsrc_vulkan.c b/libavfilter/vulkan/vsrc_testsrc_vulkan.c
new file mode 100644
index 0000000000..56b57a1e9f
--- /dev/null
+++ b/libavfilter/vulkan/vsrc_testsrc_vulkan.c
@@ -0,0 +1,380 @@
+/*
+ * Copyright (c) Lynne
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/random_seed.h"
+#include "libavutil/csp.h"
+#include "libavutil/opt.h"
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+#include "vulkan_filter.h"
+#include "libavfilter/filters.h"
+#include "libavfilter/colorspace.h"
+#include "libavfilter/video.h"
+
+enum TestSrcVulkanMode {
+    TESTSRC_COLOR,
+};
+
+typedef struct TestSrcVulkanPushData {
+    float color_comp[4];
+} TestSrcVulkanPushData;
+
+typedef struct TestSrcVulkanContext {
+    FFVulkanContext vkctx;
+
+    int initialized;
+    FFVkExecPool e;
+    AVVulkanDeviceQueueFamily *qf;
+    FFVulkanShader shd;
+
+    /* Only used by color_vulkan */
+    uint8_t color_rgba[4];
+
+    TestSrcVulkanPushData opts;
+
+    int w, h;
+    int pw, ph;
+    char *out_format_string;
+    enum AVColorRange out_range;
+    unsigned int nb_frame;
+    AVRational time_base, frame_rate;
+    int64_t pts;
+    int64_t duration;           ///< duration expressed in microseconds
+    AVRational sar;             ///< sample aspect ratio
+    int draw_once;              ///< draw only the first frame, always put out the same picture
+    int draw_once_reset;        ///< draw only the first frame or in case of reset
+    AVFrame *picref;            ///< cached reference containing the painted picture
+} TestSrcVulkanContext;
+
+static av_cold int init_filter(AVFilterContext *ctx, enum TestSrcVulkanMode mode)
+{
+    int err;
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    TestSrcVulkanContext *s = ctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
+    FFVulkanShader *shd = &s->shd;
+    FFVkSPIRVCompiler *spv;
+    FFVulkanDescriptorSetBinding *desc_set;
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->vkctx.output_format);
+
+    spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
+    if (!s->qf) {
+        av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
+        err = AVERROR(ENOTSUP);
+        goto fail;
+    }
+
+    RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
+    RET(ff_vk_shader_init(vkctx, &s->shd, "scale",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          NULL, 0,
+                          32, 32, 1,
+                          0));
+
+    GLSLC(0, layout(push_constant, std430) uniform pushConstants {        );
+    GLSLC(1,    vec4 color_comp;                                          );
+    GLSLC(0, };                                                           );
+    GLSLC(0,                                                              );
+
+    ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts),
+                                VK_SHADER_STAGE_COMPUTE_BIT);
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name       = "output_img",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
+            .mem_quali  = "writeonly",
+            .dimensions = 2,
+            .elems      = planes,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc_set, 1, 0, 0));
+
+    GLSLC(0, void main()                                                  );
+    GLSLC(0, {                                                            );
+    GLSLC(1,     ivec2 pos = ivec2(gl_GlobalInvocationID.xy);             );
+    if (mode == TESTSRC_COLOR) {
+        double rgb2yuv[3][3];
+        double rgbad[4];
+        double yuvad[4];
+
+        enum AVColorSpace csp;
+        const AVLumaCoefficients *luma = NULL;
+
+        s->draw_once = 1;
+
+        if (desc->flags & AV_PIX_FMT_FLAG_RGB)
+            csp = AVCOL_SPC_RGB;
+        else
+            csp = AVCOL_SPC_SMPTE170M;
+
+        if (!(desc->flags & AV_PIX_FMT_FLAG_RGB) && !(luma = av_csp_luma_coeffs_from_avcsp(csp)))
+            return AVERROR(EINVAL);
+        else if (!(desc->flags & AV_PIX_FMT_FLAG_RGB))
+            ff_fill_rgb2yuv_table(luma, rgb2yuv);
+
+        for (int i = 0; i < 4; i++)
+            rgbad[i] = s->color_rgba[i] / 255.0;
+
+        if (!(desc->flags & AV_PIX_FMT_FLAG_RGB))
+            ff_matrix_mul_3x3_vec(yuvad, rgbad, rgb2yuv);
+        else
+            memcpy(yuvad, rgbad, sizeof(rgbad));
+
+        yuvad[3] = rgbad[3];
+
+        if (!(desc->flags & AV_PIX_FMT_FLAG_RGB)) {
+            for (int i = 0; i < 3; i++) {
+                int chroma = (!(desc->flags & AV_PIX_FMT_FLAG_RGB) && i > 0);
+                if (s->out_range == AVCOL_RANGE_MPEG) {
+                    yuvad[i] *= (chroma ? 224.0 : 219.0) / 255.0;
+                    yuvad[i] += (chroma ? 128.0 :  16.0) / 255.0;
+                } else if (chroma) {
+                    yuvad[i] += 0.5;
+                }
+            }
+        }
+
+        /* Ensure we place the alpha appropriately for gray formats */
+        if (desc->nb_components <= 2)
+            yuvad[1] = yuvad[3];
+
+        for (int i = 0; i < 4; i++)
+            s->opts.color_comp[i] = yuvad[i];
+
+        GLSLC(1,     vec4 r;                                                  );
+        GLSLC(0,                                                              );
+        for (int i = 0, c_off = 0; i < planes; i++) {
+            for (int c = 0; c < desc->nb_components; c++) {
+                if (desc->comp[c].plane == i) {
+                    int off = desc->comp[c].offset / (FFALIGN(desc->comp[c].depth, 8)/8);
+                    GLSLF(1, r[%i] = color_comp[%i];             ,off, c_off++);
+                }
+            }
+            GLSLF(1, imageStore(output_img[%i], pos, r);                    ,i);
+            GLSLC(0,                                                          );
+        }
+    }
+    GLSLC(0, }                                                            );
+
+    RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
+
+    s->initialized = 1;
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+    if (spv)
+        spv->uninit(&spv);
+
+    return err;
+}
+
+static int testsrc_vulkan_activate(AVFilterContext *ctx)
+{
+    int err;
+    AVFilterLink *outlink = ctx->outputs[0];
+    TestSrcVulkanContext *s = ctx->priv;
+    AVFrame *frame;
+
+    if (!s->initialized) {
+        enum TestSrcVulkanMode mode = TESTSRC_COLOR;
+        err = init_filter(ctx, mode);
+        if (err < 0)
+            return err;
+    }
+
+    if (!ff_outlink_frame_wanted(outlink))
+        return FFERROR_NOT_READY;
+    if (s->duration >= 0 &&
+        av_rescale_q(s->pts, s->time_base, AV_TIME_BASE_Q) >= s->duration) {
+        ff_outlink_set_status(outlink, AVERROR_EOF, s->pts);
+        return 0;
+    }
+
+    if (s->draw_once) {
+        if (s->draw_once_reset) {
+            av_frame_free(&s->picref);
+            s->draw_once_reset = 0;
+        }
+        if (!s->picref) {
+            s->picref = ff_get_video_buffer(outlink, s->w, s->h);
+            if (!s->picref)
+                return AVERROR(ENOMEM);
+
+            err = ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->shd, s->picref, NULL,
+                                              VK_NULL_HANDLE, &s->opts, sizeof(s->opts));
+            if (err < 0)
+                return err;
+        }
+        frame = av_frame_clone(s->picref);
+    } else {
+        frame = ff_get_video_buffer(outlink, s->w, s->h);
+    }
+
+    if (!frame)
+        return AVERROR(ENOMEM);
+
+    frame->pts                 = s->pts;
+    frame->duration            = 1;
+    frame->flags               = AV_FRAME_FLAG_KEY;
+    frame->pict_type           = AV_PICTURE_TYPE_I;
+    frame->sample_aspect_ratio = s->sar;
+    if (!s->draw_once) {
+        err = ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->shd, frame, NULL,
+                                          VK_NULL_HANDLE, &s->opts, sizeof(s->opts));
+        if (err < 0) {
+            av_frame_free(&frame);
+            return err;
+        }
+    }
+
+    s->pts++;
+    s->nb_frame++;
+
+    return ff_filter_frame(outlink, frame);
+}
+
+static int testsrc_vulkan_config_props(AVFilterLink *outlink)
+{
+    int err;
+    FilterLink *l = ff_filter_link(outlink);
+    TestSrcVulkanContext *s = outlink->src->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+
+    if (!s->out_format_string) {
+        vkctx->output_format = AV_PIX_FMT_YUV444P;
+    } else {
+        vkctx->output_format = av_get_pix_fmt(s->out_format_string);
+        if (vkctx->output_format == AV_PIX_FMT_NONE) {
+            av_log(vkctx, AV_LOG_ERROR, "Invalid output format.\n");
+            return AVERROR(EINVAL);
+        }
+    }
+
+    err = ff_vk_filter_init_context(outlink->src, vkctx, NULL,
+                                    s->w, s->h, vkctx->output_format);
+    if (err < 0)
+        return err;
+
+    l->hw_frames_ctx = av_buffer_ref(vkctx->frames_ref);
+    if (!l->hw_frames_ctx)
+        return AVERROR(ENOMEM);
+
+    s->time_base = av_inv_q(s->frame_rate);
+    s->nb_frame = 0;
+    s->pts = 0;
+
+    s->vkctx.output_width = s->w;
+    s->vkctx.output_height = s->h;
+    outlink->w = s->w;
+    outlink->h = s->h;
+    outlink->sample_aspect_ratio = s->sar;
+    l->frame_rate = s->frame_rate;
+    outlink->time_base  = s->time_base;
+
+    return 0;
+}
+
+static void testsrc_vulkan_uninit(AVFilterContext *avctx)
+{
+    TestSrcVulkanContext *s = avctx->priv;
+    FFVulkanContext *vkctx = &s->vkctx;
+
+    av_frame_free(&s->picref);
+
+    ff_vk_exec_pool_free(vkctx, &s->e);
+    ff_vk_shader_free(vkctx, &s->shd);
+
+    ff_vk_uninit(&s->vkctx);
+
+    s->initialized = 0;
+}
+
+#define OFFSET(x) offsetof(TestSrcVulkanContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
+
+#define COMMON_OPTS                                                                                                                           \
+    { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, { .str = "1920x1080" }, 0, 0, FLAGS },                                     \
+    { "s",    "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, { .str = "1920x1080" }, 0, 0, FLAGS },                                     \
+                                                                                                                                              \
+    { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, { .str = "60" }, 0, INT_MAX, FLAGS },                             \
+    { "r",    "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, { .str = "60" }, 0, INT_MAX, FLAGS },                             \
+                                                                                                                                              \
+    { "duration", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT64_MAX, FLAGS },                        \
+    { "d",        "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT64_MAX, FLAGS },                        \
+                                                                                                                                              \
+    { "sar", "set video sample aspect ratio", OFFSET(sar), AV_OPT_TYPE_RATIONAL, { .dbl = 1 },  0, INT_MAX, FLAGS },                          \
+                                                                                                                                              \
+    { "format", "Output video format (software format of hardware frames)", OFFSET(out_format_string), AV_OPT_TYPE_STRING, .flags = FLAGS },
+
+static const AVOption color_vulkan_options[] = {
+    { "color", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGS },
+    { "c",     "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGS },
+    COMMON_OPTS
+    { "out_range", "Output colour range (from 0 to 2) (default 0)", OFFSET(out_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED}, AVCOL_RANGE_UNSPECIFIED, AVCOL_RANGE_JPEG, .flags = FLAGS, .unit = "range" },
+        { "full", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, .unit = "range" },
+        { "limited", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, .unit = "range" },
+        { "jpeg", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, .unit = "range" },
+        { "mpeg", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, .unit = "range" },
+        { "tv", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, .unit = "range" },
+        { "pc", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, .unit = "range" },
+    { NULL },
+};
+
+AVFILTER_DEFINE_CLASS(color_vulkan);
+
+static const AVFilterPad testsrc_vulkan_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_VIDEO,
+        .config_props = testsrc_vulkan_config_props,
+    },
+};
+
+const FFFilter ff_vsrc_color_vulkan = {
+    .p.name         = "color_vulkan",
+    .p.description  = NULL_IF_CONFIG_SMALL("Generate a constant color (Vulkan)"),
+    .p.inputs       = NULL,
+    .p.flags        = AVFILTER_FLAG_HWDEVICE,
+    .p.priv_class   = &color_vulkan_class,
+    .priv_size      = sizeof(TestSrcVulkanContext),
+    .init           = &ff_vk_filter_init,
+    .uninit         = &testsrc_vulkan_uninit,
+    .activate       = testsrc_vulkan_activate,
+    FILTER_OUTPUTS(testsrc_vulkan_outputs),
+    FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN),
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};
-- 
2.49.1


From 9dea04c66a3b8047af0573e3ce8d71d72855353b Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:07:12 +0000
Subject: [PATCH 031/118] Changing vulkan file directory

---
 libavfilter/vulkan_filter.c | 483 ------------------------------------
 1 file changed, 483 deletions(-)
 delete mode 100644 libavfilter/vulkan_filter.c

diff --git a/libavfilter/vulkan_filter.c b/libavfilter/vulkan_filter.c
deleted file mode 100644
index a9f47741ed..0000000000
--- a/libavfilter/vulkan_filter.c
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * Copyright (c) Lynne
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "filters.h"
-#include "vulkan_filter.h"
-#include "libavutil/vulkan_loader.h"
-
-int ff_vk_filter_init_context(AVFilterContext *avctx, FFVulkanContext *s,
-                              AVBufferRef *frames_ref,
-                              int width, int height, enum AVPixelFormat sw_format)
-{
-    int err;
-    AVHWFramesContext *frames_ctx;
-    AVHWDeviceContext *device_ctx;
-    AVVulkanFramesContext *vk_frames;
-    AVVulkanDeviceContext *vk_dev;
-    AVBufferRef *device_ref = avctx->hw_device_ctx;
-
-    /* Check if context is reusable as-is */
-    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;
-        device_ctx = (AVHWDeviceContext *)frames_ctx->device_ref->data;
-        vk_frames = frames_ctx->hwctx;
-        vk_dev = device_ctx->hwctx;
-
-        /* Width and height mismatch */
-        if (width != frames_ctx->width ||
-            height != frames_ctx->height)
-            goto skip;
-
-        /* Format mismatch */
-        if (sw_format != frames_ctx->sw_format)
-            goto skip;
-
-        /* Don't let linear through. */
-        if (vk_frames->tiling == VK_IMAGE_TILING_LINEAR)
-            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 = {
-                .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
-            };
-            vk->GetPhysicalDeviceFormatProperties2(vk_dev->phys_dev, sub[i],
-                                                   &prop);
-            no_storage |= !(prop.formatProperties.optimalTilingFeatures &
-                            VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT);
-        }
-
-        /* Check if it's usable */
-        if (no_storage) {
-skip:
-            av_log(avctx, AV_LOG_VERBOSE, "Cannot reuse context, creating a new one\n");
-            device_ref = frames_ctx->device_ref;
-            frames_ref = NULL;
-        } else {
-            av_log(avctx, AV_LOG_VERBOSE, "Reusing existing frames context\n");
-            frames_ref = av_buffer_ref(frames_ref);
-            if (!frames_ref)
-                return AVERROR(ENOMEM);
-        }
-    }
-
-    if (!frames_ref) {
-        if (!device_ref) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "Vulkan filtering requires a device context!\n");
-            return AVERROR(EINVAL);
-        }
-
-        frames_ref = av_hwframe_ctx_alloc(device_ref);
-
-        frames_ctx = (AVHWFramesContext *)frames_ref->data;
-        frames_ctx->format    = AV_PIX_FMT_VULKAN;
-        frames_ctx->sw_format = sw_format;
-        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;
-
-        err = av_hwframe_ctx_init(frames_ref);
-        if (err < 0) {
-            av_buffer_unref(&frames_ref);
-            return err;
-        }
-
-        device_ctx = (AVHWDeviceContext *)frames_ctx->device_ref->data;
-        vk_dev = device_ctx->hwctx;
-    }
-
-    s->extensions = ff_vk_extensions_to_mask(vk_dev->enabled_dev_extensions,
-                                             vk_dev->nb_enabled_dev_extensions);
-    s->extensions |= ff_vk_extensions_to_mask(vk_dev->enabled_inst_extensions,
-                                              vk_dev->nb_enabled_inst_extensions);
-
-    err = ff_vk_load_functions(device_ctx, &s->vkfn, s->extensions, 1, 1);
-    if (err < 0) {
-        av_buffer_unref(&frames_ref);
-        return err;
-    }
-
-    s->frames_ref = frames_ref;
-    s->frames = frames_ctx;
-    s->hwfc = vk_frames;
-    s->device = device_ctx;
-    s->hwctx = device_ctx->hwctx;
-
-    err = ff_vk_load_props(s);
-    if (err < 0)
-        av_buffer_unref(&s->frames_ref);
-
-    return err;
-}
-
-int ff_vk_filter_config_input(AVFilterLink *inlink)
-{
-    FilterLink *l = ff_filter_link(inlink);
-    AVHWFramesContext *input_frames;
-    AVFilterContext *avctx = inlink->dst;
-    FFVulkanContext *s = inlink->dst->priv;
-
-    if (!l->hw_frames_ctx) {
-        av_log(inlink->dst, AV_LOG_ERROR, "Vulkan filtering requires a "
-               "hardware frames context on the input.\n");
-        return AVERROR(EINVAL);
-    }
-
-    input_frames = (AVHWFramesContext *)l->hw_frames_ctx->data;
-    if (input_frames->format != AV_PIX_FMT_VULKAN)
-        return AVERROR(EINVAL);
-
-    /* Extract the device and default output format from the first input. */
-    if (avctx->inputs[0] != inlink)
-        return 0;
-
-    /* Save the ref, without reffing it */
-    s->input_frames_ref = l->hw_frames_ctx;
-
-    /* Defaults */
-    s->input_format = input_frames->sw_format;
-    s->output_format = input_frames->sw_format;
-    s->output_width = inlink->w;
-    s->output_height = inlink->h;
-
-    return 0;
-}
-
-int ff_vk_filter_config_output(AVFilterLink *outlink)
-{
-    int err;
-    FilterLink *l = ff_filter_link(outlink);
-    FFVulkanContext *s = outlink->src->priv;
-
-    av_buffer_unref(&l->hw_frames_ctx);
-
-    err = ff_vk_filter_init_context(outlink->src, s, s->input_frames_ref,
-                                    s->output_width, s->output_height,
-                                    s->output_format);
-    if (err < 0)
-        return err;
-
-    l->hw_frames_ctx = av_buffer_ref(s->frames_ref);
-    if (!l->hw_frames_ctx)
-        return AVERROR(ENOMEM);
-
-    outlink->w = s->output_width;
-    outlink->h = s->output_height;
-
-    return err;
-}
-
-int ff_vk_filter_init(AVFilterContext *avctx)
-{
-    FFVulkanContext *s = avctx->priv;
-
-    s->output_format = AV_PIX_FMT_NONE;
-
-    return 0;
-}
-
-int ff_vk_filter_process_simple(FFVulkanContext *vkctx, FFVkExecPool *e,
-                                FFVulkanShader *shd, AVFrame *out_f, AVFrame *in_f,
-                                VkSampler sampler, void *push_src, size_t push_size)
-{
-    int err = 0;
-    FFVulkanFunctions *vk = &vkctx->vkfn;
-    VkImageView in_views[AV_NUM_DATA_POINTERS];
-    VkImageView out_views[AV_NUM_DATA_POINTERS];
-    VkImageMemoryBarrier2 img_bar[37];
-    int nb_img_bar = 0;
-    VkImageLayout in_layout = sampler != VK_NULL_HANDLE ?
-                              VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL :
-                              VK_IMAGE_LAYOUT_GENERAL;
-
-    /* Update descriptors and init the exec context */
-    FFVkExecContext *exec = ff_vk_exec_get(vkctx, e);
-    ff_vk_exec_start(vkctx, exec);
-
-    RET(ff_vk_exec_add_dep_frame(vkctx, exec, out_f,
-                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
-    RET(ff_vk_create_imageviews(vkctx, exec, out_views, out_f, FF_VK_REP_FLOAT));
-    ff_vk_shader_update_img_array(vkctx, exec, shd, out_f, out_views, 0, !!in_f,
-                                  VK_IMAGE_LAYOUT_GENERAL,
-                                  VK_NULL_HANDLE);
-    if (in_f) {
-        RET(ff_vk_exec_add_dep_frame(vkctx, exec, in_f,
-                                     VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                     VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
-        RET(ff_vk_create_imageviews(vkctx, exec, in_views,  in_f, FF_VK_REP_FLOAT));
-        ff_vk_shader_update_img_array(vkctx, exec, shd,  in_f,  in_views, 0, 0,
-                                      in_layout,
-                                      sampler);
-    }
-
-    /* Bind pipeline, update push data */
-    ff_vk_exec_bind_shader(vkctx, exec, shd);
-    if (push_src)
-        ff_vk_shader_update_push_const(vkctx, exec, shd, VK_SHADER_STAGE_COMPUTE_BIT,
-                                       0, push_size, push_src);
-
-    /* Add data sync barriers */
-    ff_vk_frame_barrier(vkctx, exec, out_f, img_bar, &nb_img_bar,
-                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                        VK_ACCESS_SHADER_WRITE_BIT,
-                        VK_IMAGE_LAYOUT_GENERAL,
-                        VK_QUEUE_FAMILY_IGNORED);
-    if (in_f)
-        ff_vk_frame_barrier(vkctx, exec, in_f, img_bar, &nb_img_bar,
-                            VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                            VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                            VK_ACCESS_SHADER_READ_BIT,
-                            in_layout,
-                            VK_QUEUE_FAMILY_IGNORED);
-
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-            .pImageMemoryBarriers = img_bar,
-            .imageMemoryBarrierCount = nb_img_bar,
-        });
-
-    vk->CmdDispatch(exec->buf,
-                    FFALIGN(vkctx->output_width,  shd->lg_size[0])/shd->lg_size[0],
-                    FFALIGN(vkctx->output_height, shd->lg_size[1])/shd->lg_size[1],
-                    shd->lg_size[2]);
-
-    return ff_vk_exec_submit(vkctx, exec);
-fail:
-    ff_vk_exec_discard_deps(vkctx, exec);
-    return err;
-}
-
-int ff_vk_filter_process_2pass(FFVulkanContext *vkctx, FFVkExecPool *e,
-                               FFVulkanShader *shd_list[2],
-                               AVFrame *out, AVFrame *tmp, AVFrame *in,
-                               VkSampler sampler, void *push_src, size_t push_size)
-{
-    int err = 0;
-    FFVulkanFunctions *vk = &vkctx->vkfn;
-    VkImageView in_views[AV_NUM_DATA_POINTERS];
-    VkImageView tmp_views[AV_NUM_DATA_POINTERS];
-    VkImageView out_views[AV_NUM_DATA_POINTERS];
-    VkImageMemoryBarrier2 img_bar[37];
-    int nb_img_bar = 0;
-    VkImageLayout in_layout = sampler != VK_NULL_HANDLE ?
-                              VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL :
-                              VK_IMAGE_LAYOUT_GENERAL;
-
-    /* Update descriptors and init the exec context */
-    FFVkExecContext *exec = ff_vk_exec_get(vkctx, e);
-    ff_vk_exec_start(vkctx, exec);
-
-    RET(ff_vk_exec_add_dep_frame(vkctx, exec, in,
-                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
-    RET(ff_vk_exec_add_dep_frame(vkctx, exec, tmp,
-                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
-    RET(ff_vk_exec_add_dep_frame(vkctx, exec, out,
-                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
-
-    RET(ff_vk_create_imageviews(vkctx, exec, in_views,  in, FF_VK_REP_FLOAT));
-    RET(ff_vk_create_imageviews(vkctx, exec, tmp_views, tmp, FF_VK_REP_FLOAT));
-    RET(ff_vk_create_imageviews(vkctx, exec, out_views, out, FF_VK_REP_FLOAT));
-
-    ff_vk_frame_barrier(vkctx, exec, in, img_bar, &nb_img_bar,
-                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                        VK_ACCESS_SHADER_READ_BIT,
-                        in_layout,
-                        VK_QUEUE_FAMILY_IGNORED);
-    ff_vk_frame_barrier(vkctx, exec, tmp, img_bar, &nb_img_bar,
-                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                        VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
-                        VK_IMAGE_LAYOUT_GENERAL,
-                        VK_QUEUE_FAMILY_IGNORED);
-    ff_vk_frame_barrier(vkctx, exec, out, img_bar, &nb_img_bar,
-                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                        VK_ACCESS_SHADER_WRITE_BIT,
-                        VK_IMAGE_LAYOUT_GENERAL,
-                        VK_QUEUE_FAMILY_IGNORED);
-
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-            .pImageMemoryBarriers = img_bar,
-            .imageMemoryBarrierCount = nb_img_bar,
-        });
-
-    for (int i = 0; i < 2; i++) {
-        FFVulkanShader *shd = shd_list[i];
-        AVFrame *src_f = !i ? in : tmp;
-        AVFrame *dst_f = !i ? tmp : out;
-        VkImageView *src_views = !i ? in_views : tmp_views;
-        VkImageView *dst_views = !i ? tmp_views : out_views;
-
-        ff_vk_shader_update_img_array(vkctx, exec, shd, src_f, src_views, 0, 0,
-                                      !i ? in_layout :
-                                           VK_IMAGE_LAYOUT_GENERAL,
-                                      sampler);
-        ff_vk_shader_update_img_array(vkctx, exec, shd, dst_f, dst_views, 0, 1,
-                                      VK_IMAGE_LAYOUT_GENERAL,
-                                      VK_NULL_HANDLE);
-
-        /* Bind pipeline, update push data */
-        ff_vk_exec_bind_shader(vkctx, exec, shd);
-        if (push_src)
-            ff_vk_shader_update_push_const(vkctx, exec, shd, VK_SHADER_STAGE_COMPUTE_BIT,
-                                           0, push_size, push_src);
-
-        vk->CmdDispatch(exec->buf,
-                        FFALIGN(vkctx->output_width,  shd->lg_size[0])/shd->lg_size[0],
-                        FFALIGN(vkctx->output_height, shd->lg_size[1])/shd->lg_size[1],
-                        shd->lg_size[2]);
-    }
-
-    return ff_vk_exec_submit(vkctx, exec);
-fail:
-    ff_vk_exec_discard_deps(vkctx, exec);
-    return err;
-}
-
-int ff_vk_filter_process_Nin(FFVulkanContext *vkctx, FFVkExecPool *e,
-                             FFVulkanShader *shd,
-                             AVFrame *out, AVFrame *in[], int nb_in,
-                             VkSampler sampler, void *push_src, size_t push_size)
-{
-    int err = 0;
-    FFVulkanFunctions *vk = &vkctx->vkfn;
-    VkImageView in_views[16][AV_NUM_DATA_POINTERS];
-    VkImageView out_views[AV_NUM_DATA_POINTERS];
-    VkImageMemoryBarrier2 img_bar[128];
-    int nb_img_bar = 0;
-    VkImageLayout in_layout = sampler != VK_NULL_HANDLE ?
-                              VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL :
-                              VK_IMAGE_LAYOUT_GENERAL;
-
-    /* Update descriptors and init the exec context */
-    FFVkExecContext *exec = ff_vk_exec_get(vkctx, e);
-    ff_vk_exec_start(vkctx, exec);
-
-    /* Add deps and create temporary imageviews */
-    RET(ff_vk_exec_add_dep_frame(vkctx, exec, out,
-                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
-    RET(ff_vk_create_imageviews(vkctx, exec, out_views, out, FF_VK_REP_FLOAT));
-    for (int i = 0; i < nb_in; i++) {
-        RET(ff_vk_exec_add_dep_frame(vkctx, exec, in[i],
-                                     VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                     VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
-        RET(ff_vk_create_imageviews(vkctx, exec, in_views[i], in[i], FF_VK_REP_FLOAT));
-    }
-
-    /* Update descriptor sets */
-    ff_vk_shader_update_img_array(vkctx, exec, shd, out, out_views, 0, nb_in,
-                                  VK_IMAGE_LAYOUT_GENERAL,
-                                  VK_NULL_HANDLE);
-    for (int i = 0; i < nb_in; i++)
-        ff_vk_shader_update_img_array(vkctx, exec, shd, in[i], in_views[i], 0, i,
-                                      in_layout,
-                                      sampler);
-
-    /* Bind pipeline, update push data */
-    ff_vk_exec_bind_shader(vkctx, exec, shd);
-    if (push_src)
-        ff_vk_shader_update_push_const(vkctx, exec, shd, VK_SHADER_STAGE_COMPUTE_BIT,
-                                       0, push_size, push_src);
-
-    /* Add data sync barriers */
-    ff_vk_frame_barrier(vkctx, exec, out, img_bar, &nb_img_bar,
-                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                        VK_ACCESS_SHADER_WRITE_BIT,
-                        VK_IMAGE_LAYOUT_GENERAL,
-                        VK_QUEUE_FAMILY_IGNORED);
-    for (int i = 0; i < nb_in; i++)
-        ff_vk_frame_barrier(vkctx, exec, in[i], img_bar, &nb_img_bar,
-                            VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                            VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                            VK_ACCESS_SHADER_READ_BIT,
-                            in_layout,
-                            VK_QUEUE_FAMILY_IGNORED);
-
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-            .pImageMemoryBarriers = img_bar,
-            .imageMemoryBarrierCount = nb_img_bar,
-        });
-
-    vk->CmdDispatch(exec->buf,
-                    FFALIGN(vkctx->output_width,  shd->lg_size[0])/shd->lg_size[0],
-                    FFALIGN(vkctx->output_height, shd->lg_size[1])/shd->lg_size[1],
-                    shd->lg_size[2]);
-
-    return ff_vk_exec_submit(vkctx, exec);
-fail:
-    ff_vk_exec_discard_deps(vkctx, exec);
-    return err;
-}
-- 
2.49.1


From b436dc72a98892a37880208ddaa213d4f3f6eacc Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:07:37 +0000
Subject: [PATCH 032/118] Changing vulkan file directory

---
 libavfilter/vulkan/vulkan_filter.c | 483 +++++++++++++++++++++++++++++
 1 file changed, 483 insertions(+)
 create mode 100644 libavfilter/vulkan/vulkan_filter.c

diff --git a/libavfilter/vulkan/vulkan_filter.c b/libavfilter/vulkan/vulkan_filter.c
new file mode 100644
index 0000000000..2fc37cc4c0
--- /dev/null
+++ b/libavfilter/vulkan/vulkan_filter.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright (c) Lynne
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavfilter/filters.h"
+#include "vulkan_filter.h"
+#include "../../libavutil/vulkan/vulkan_loader.h"
+
+int ff_vk_filter_init_context(AVFilterContext *avctx, FFVulkanContext *s,
+                              AVBufferRef *frames_ref,
+                              int width, int height, enum AVPixelFormat sw_format)
+{
+    int err;
+    AVHWFramesContext *frames_ctx;
+    AVHWDeviceContext *device_ctx;
+    AVVulkanFramesContext *vk_frames;
+    AVVulkanDeviceContext *vk_dev;
+    AVBufferRef *device_ref = avctx->hw_device_ctx;
+
+    /* Check if context is reusable as-is */
+    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;
+        device_ctx = (AVHWDeviceContext *)frames_ctx->device_ref->data;
+        vk_frames = frames_ctx->hwctx;
+        vk_dev = device_ctx->hwctx;
+
+        /* Width and height mismatch */
+        if (width != frames_ctx->width ||
+            height != frames_ctx->height)
+            goto skip;
+
+        /* Format mismatch */
+        if (sw_format != frames_ctx->sw_format)
+            goto skip;
+
+        /* Don't let linear through. */
+        if (vk_frames->tiling == VK_IMAGE_TILING_LINEAR)
+            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 = {
+                .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
+            };
+            vk->GetPhysicalDeviceFormatProperties2(vk_dev->phys_dev, sub[i],
+                                                   &prop);
+            no_storage |= !(prop.formatProperties.optimalTilingFeatures &
+                            VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT);
+        }
+
+        /* Check if it's usable */
+        if (no_storage) {
+skip:
+            av_log(avctx, AV_LOG_VERBOSE, "Cannot reuse context, creating a new one\n");
+            device_ref = frames_ctx->device_ref;
+            frames_ref = NULL;
+        } else {
+            av_log(avctx, AV_LOG_VERBOSE, "Reusing existing frames context\n");
+            frames_ref = av_buffer_ref(frames_ref);
+            if (!frames_ref)
+                return AVERROR(ENOMEM);
+        }
+    }
+
+    if (!frames_ref) {
+        if (!device_ref) {
+            av_log(avctx, AV_LOG_ERROR,
+                   "Vulkan filtering requires a device context!\n");
+            return AVERROR(EINVAL);
+        }
+
+        frames_ref = av_hwframe_ctx_alloc(device_ref);
+
+        frames_ctx = (AVHWFramesContext *)frames_ref->data;
+        frames_ctx->format    = AV_PIX_FMT_VULKAN;
+        frames_ctx->sw_format = sw_format;
+        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;
+
+        err = av_hwframe_ctx_init(frames_ref);
+        if (err < 0) {
+            av_buffer_unref(&frames_ref);
+            return err;
+        }
+
+        device_ctx = (AVHWDeviceContext *)frames_ctx->device_ref->data;
+        vk_dev = device_ctx->hwctx;
+    }
+
+    s->extensions = ff_vk_extensions_to_mask(vk_dev->enabled_dev_extensions,
+                                             vk_dev->nb_enabled_dev_extensions);
+    s->extensions |= ff_vk_extensions_to_mask(vk_dev->enabled_inst_extensions,
+                                              vk_dev->nb_enabled_inst_extensions);
+
+    err = ff_vk_load_functions(device_ctx, &s->vkfn, s->extensions, 1, 1);
+    if (err < 0) {
+        av_buffer_unref(&frames_ref);
+        return err;
+    }
+
+    s->frames_ref = frames_ref;
+    s->frames = frames_ctx;
+    s->hwfc = vk_frames;
+    s->device = device_ctx;
+    s->hwctx = device_ctx->hwctx;
+
+    err = ff_vk_load_props(s);
+    if (err < 0)
+        av_buffer_unref(&s->frames_ref);
+
+    return err;
+}
+
+int ff_vk_filter_config_input(AVFilterLink *inlink)
+{
+    FilterLink *l = ff_filter_link(inlink);
+    AVHWFramesContext *input_frames;
+    AVFilterContext *avctx = inlink->dst;
+    FFVulkanContext *s = inlink->dst->priv;
+
+    if (!l->hw_frames_ctx) {
+        av_log(inlink->dst, AV_LOG_ERROR, "Vulkan filtering requires a "
+               "hardware frames context on the input.\n");
+        return AVERROR(EINVAL);
+    }
+
+    input_frames = (AVHWFramesContext *)l->hw_frames_ctx->data;
+    if (input_frames->format != AV_PIX_FMT_VULKAN)
+        return AVERROR(EINVAL);
+
+    /* Extract the device and default output format from the first input. */
+    if (avctx->inputs[0] != inlink)
+        return 0;
+
+    /* Save the ref, without reffing it */
+    s->input_frames_ref = l->hw_frames_ctx;
+
+    /* Defaults */
+    s->input_format = input_frames->sw_format;
+    s->output_format = input_frames->sw_format;
+    s->output_width = inlink->w;
+    s->output_height = inlink->h;
+
+    return 0;
+}
+
+int ff_vk_filter_config_output(AVFilterLink *outlink)
+{
+    int err;
+    FilterLink *l = ff_filter_link(outlink);
+    FFVulkanContext *s = outlink->src->priv;
+
+    av_buffer_unref(&l->hw_frames_ctx);
+
+    err = ff_vk_filter_init_context(outlink->src, s, s->input_frames_ref,
+                                    s->output_width, s->output_height,
+                                    s->output_format);
+    if (err < 0)
+        return err;
+
+    l->hw_frames_ctx = av_buffer_ref(s->frames_ref);
+    if (!l->hw_frames_ctx)
+        return AVERROR(ENOMEM);
+
+    outlink->w = s->output_width;
+    outlink->h = s->output_height;
+
+    return err;
+}
+
+int ff_vk_filter_init(AVFilterContext *avctx)
+{
+    FFVulkanContext *s = avctx->priv;
+
+    s->output_format = AV_PIX_FMT_NONE;
+
+    return 0;
+}
+
+int ff_vk_filter_process_simple(FFVulkanContext *vkctx, FFVkExecPool *e,
+                                FFVulkanShader *shd, AVFrame *out_f, AVFrame *in_f,
+                                VkSampler sampler, void *push_src, size_t push_size)
+{
+    int err = 0;
+    FFVulkanFunctions *vk = &vkctx->vkfn;
+    VkImageView in_views[AV_NUM_DATA_POINTERS];
+    VkImageView out_views[AV_NUM_DATA_POINTERS];
+    VkImageMemoryBarrier2 img_bar[37];
+    int nb_img_bar = 0;
+    VkImageLayout in_layout = sampler != VK_NULL_HANDLE ?
+                              VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL :
+                              VK_IMAGE_LAYOUT_GENERAL;
+
+    /* Update descriptors and init the exec context */
+    FFVkExecContext *exec = ff_vk_exec_get(vkctx, e);
+    ff_vk_exec_start(vkctx, exec);
+
+    RET(ff_vk_exec_add_dep_frame(vkctx, exec, out_f,
+                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
+    RET(ff_vk_create_imageviews(vkctx, exec, out_views, out_f, FF_VK_REP_FLOAT));
+    ff_vk_shader_update_img_array(vkctx, exec, shd, out_f, out_views, 0, !!in_f,
+                                  VK_IMAGE_LAYOUT_GENERAL,
+                                  VK_NULL_HANDLE);
+    if (in_f) {
+        RET(ff_vk_exec_add_dep_frame(vkctx, exec, in_f,
+                                     VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                     VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
+        RET(ff_vk_create_imageviews(vkctx, exec, in_views,  in_f, FF_VK_REP_FLOAT));
+        ff_vk_shader_update_img_array(vkctx, exec, shd,  in_f,  in_views, 0, 0,
+                                      in_layout,
+                                      sampler);
+    }
+
+    /* Bind pipeline, update push data */
+    ff_vk_exec_bind_shader(vkctx, exec, shd);
+    if (push_src)
+        ff_vk_shader_update_push_const(vkctx, exec, shd, VK_SHADER_STAGE_COMPUTE_BIT,
+                                       0, push_size, push_src);
+
+    /* Add data sync barriers */
+    ff_vk_frame_barrier(vkctx, exec, out_f, img_bar, &nb_img_bar,
+                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                        VK_ACCESS_SHADER_WRITE_BIT,
+                        VK_IMAGE_LAYOUT_GENERAL,
+                        VK_QUEUE_FAMILY_IGNORED);
+    if (in_f)
+        ff_vk_frame_barrier(vkctx, exec, in_f, img_bar, &nb_img_bar,
+                            VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                            VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                            VK_ACCESS_SHADER_READ_BIT,
+                            in_layout,
+                            VK_QUEUE_FAMILY_IGNORED);
+
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+            .pImageMemoryBarriers = img_bar,
+            .imageMemoryBarrierCount = nb_img_bar,
+        });
+
+    vk->CmdDispatch(exec->buf,
+                    FFALIGN(vkctx->output_width,  shd->lg_size[0])/shd->lg_size[0],
+                    FFALIGN(vkctx->output_height, shd->lg_size[1])/shd->lg_size[1],
+                    shd->lg_size[2]);
+
+    return ff_vk_exec_submit(vkctx, exec);
+fail:
+    ff_vk_exec_discard_deps(vkctx, exec);
+    return err;
+}
+
+int ff_vk_filter_process_2pass(FFVulkanContext *vkctx, FFVkExecPool *e,
+                               FFVulkanShader *shd_list[2],
+                               AVFrame *out, AVFrame *tmp, AVFrame *in,
+                               VkSampler sampler, void *push_src, size_t push_size)
+{
+    int err = 0;
+    FFVulkanFunctions *vk = &vkctx->vkfn;
+    VkImageView in_views[AV_NUM_DATA_POINTERS];
+    VkImageView tmp_views[AV_NUM_DATA_POINTERS];
+    VkImageView out_views[AV_NUM_DATA_POINTERS];
+    VkImageMemoryBarrier2 img_bar[37];
+    int nb_img_bar = 0;
+    VkImageLayout in_layout = sampler != VK_NULL_HANDLE ?
+                              VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL :
+                              VK_IMAGE_LAYOUT_GENERAL;
+
+    /* Update descriptors and init the exec context */
+    FFVkExecContext *exec = ff_vk_exec_get(vkctx, e);
+    ff_vk_exec_start(vkctx, exec);
+
+    RET(ff_vk_exec_add_dep_frame(vkctx, exec, in,
+                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
+    RET(ff_vk_exec_add_dep_frame(vkctx, exec, tmp,
+                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
+    RET(ff_vk_exec_add_dep_frame(vkctx, exec, out,
+                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
+
+    RET(ff_vk_create_imageviews(vkctx, exec, in_views,  in, FF_VK_REP_FLOAT));
+    RET(ff_vk_create_imageviews(vkctx, exec, tmp_views, tmp, FF_VK_REP_FLOAT));
+    RET(ff_vk_create_imageviews(vkctx, exec, out_views, out, FF_VK_REP_FLOAT));
+
+    ff_vk_frame_barrier(vkctx, exec, in, img_bar, &nb_img_bar,
+                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                        VK_ACCESS_SHADER_READ_BIT,
+                        in_layout,
+                        VK_QUEUE_FAMILY_IGNORED);
+    ff_vk_frame_barrier(vkctx, exec, tmp, img_bar, &nb_img_bar,
+                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                        VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
+                        VK_IMAGE_LAYOUT_GENERAL,
+                        VK_QUEUE_FAMILY_IGNORED);
+    ff_vk_frame_barrier(vkctx, exec, out, img_bar, &nb_img_bar,
+                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                        VK_ACCESS_SHADER_WRITE_BIT,
+                        VK_IMAGE_LAYOUT_GENERAL,
+                        VK_QUEUE_FAMILY_IGNORED);
+
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+            .pImageMemoryBarriers = img_bar,
+            .imageMemoryBarrierCount = nb_img_bar,
+        });
+
+    for (int i = 0; i < 2; i++) {
+        FFVulkanShader *shd = shd_list[i];
+        AVFrame *src_f = !i ? in : tmp;
+        AVFrame *dst_f = !i ? tmp : out;
+        VkImageView *src_views = !i ? in_views : tmp_views;
+        VkImageView *dst_views = !i ? tmp_views : out_views;
+
+        ff_vk_shader_update_img_array(vkctx, exec, shd, src_f, src_views, 0, 0,
+                                      !i ? in_layout :
+                                           VK_IMAGE_LAYOUT_GENERAL,
+                                      sampler);
+        ff_vk_shader_update_img_array(vkctx, exec, shd, dst_f, dst_views, 0, 1,
+                                      VK_IMAGE_LAYOUT_GENERAL,
+                                      VK_NULL_HANDLE);
+
+        /* Bind pipeline, update push data */
+        ff_vk_exec_bind_shader(vkctx, exec, shd);
+        if (push_src)
+            ff_vk_shader_update_push_const(vkctx, exec, shd, VK_SHADER_STAGE_COMPUTE_BIT,
+                                           0, push_size, push_src);
+
+        vk->CmdDispatch(exec->buf,
+                        FFALIGN(vkctx->output_width,  shd->lg_size[0])/shd->lg_size[0],
+                        FFALIGN(vkctx->output_height, shd->lg_size[1])/shd->lg_size[1],
+                        shd->lg_size[2]);
+    }
+
+    return ff_vk_exec_submit(vkctx, exec);
+fail:
+    ff_vk_exec_discard_deps(vkctx, exec);
+    return err;
+}
+
+int ff_vk_filter_process_Nin(FFVulkanContext *vkctx, FFVkExecPool *e,
+                             FFVulkanShader *shd,
+                             AVFrame *out, AVFrame *in[], int nb_in,
+                             VkSampler sampler, void *push_src, size_t push_size)
+{
+    int err = 0;
+    FFVulkanFunctions *vk = &vkctx->vkfn;
+    VkImageView in_views[16][AV_NUM_DATA_POINTERS];
+    VkImageView out_views[AV_NUM_DATA_POINTERS];
+    VkImageMemoryBarrier2 img_bar[128];
+    int nb_img_bar = 0;
+    VkImageLayout in_layout = sampler != VK_NULL_HANDLE ?
+                              VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL :
+                              VK_IMAGE_LAYOUT_GENERAL;
+
+    /* Update descriptors and init the exec context */
+    FFVkExecContext *exec = ff_vk_exec_get(vkctx, e);
+    ff_vk_exec_start(vkctx, exec);
+
+    /* Add deps and create temporary imageviews */
+    RET(ff_vk_exec_add_dep_frame(vkctx, exec, out,
+                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
+    RET(ff_vk_create_imageviews(vkctx, exec, out_views, out, FF_VK_REP_FLOAT));
+    for (int i = 0; i < nb_in; i++) {
+        RET(ff_vk_exec_add_dep_frame(vkctx, exec, in[i],
+                                     VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                     VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
+        RET(ff_vk_create_imageviews(vkctx, exec, in_views[i], in[i], FF_VK_REP_FLOAT));
+    }
+
+    /* Update descriptor sets */
+    ff_vk_shader_update_img_array(vkctx, exec, shd, out, out_views, 0, nb_in,
+                                  VK_IMAGE_LAYOUT_GENERAL,
+                                  VK_NULL_HANDLE);
+    for (int i = 0; i < nb_in; i++)
+        ff_vk_shader_update_img_array(vkctx, exec, shd, in[i], in_views[i], 0, i,
+                                      in_layout,
+                                      sampler);
+
+    /* Bind pipeline, update push data */
+    ff_vk_exec_bind_shader(vkctx, exec, shd);
+    if (push_src)
+        ff_vk_shader_update_push_const(vkctx, exec, shd, VK_SHADER_STAGE_COMPUTE_BIT,
+                                       0, push_size, push_src);
+
+    /* Add data sync barriers */
+    ff_vk_frame_barrier(vkctx, exec, out, img_bar, &nb_img_bar,
+                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                        VK_ACCESS_SHADER_WRITE_BIT,
+                        VK_IMAGE_LAYOUT_GENERAL,
+                        VK_QUEUE_FAMILY_IGNORED);
+    for (int i = 0; i < nb_in; i++)
+        ff_vk_frame_barrier(vkctx, exec, in[i], img_bar, &nb_img_bar,
+                            VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                            VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                            VK_ACCESS_SHADER_READ_BIT,
+                            in_layout,
+                            VK_QUEUE_FAMILY_IGNORED);
+
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+            .pImageMemoryBarriers = img_bar,
+            .imageMemoryBarrierCount = nb_img_bar,
+        });
+
+    vk->CmdDispatch(exec->buf,
+                    FFALIGN(vkctx->output_width,  shd->lg_size[0])/shd->lg_size[0],
+                    FFALIGN(vkctx->output_height, shd->lg_size[1])/shd->lg_size[1],
+                    shd->lg_size[2]);
+
+    return ff_vk_exec_submit(vkctx, exec);
+fail:
+    ff_vk_exec_discard_deps(vkctx, exec);
+    return err;
+}
-- 
2.49.1


From d225975ae3b900213f891173d1d5ae82b81ae3c2 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:08:16 +0000
Subject: [PATCH 033/118] Changing vulkan file directory

---
 libavfilter/vulkan_filter.h | 65 -------------------------------------
 1 file changed, 65 deletions(-)
 delete mode 100644 libavfilter/vulkan_filter.h

diff --git a/libavfilter/vulkan_filter.h b/libavfilter/vulkan_filter.h
deleted file mode 100644
index 6ed9c4de39..0000000000
--- a/libavfilter/vulkan_filter.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) Lynne
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVFILTER_VULKAN_FILTER_H
-#define AVFILTER_VULKAN_FILTER_H
-
-#include "avfilter.h"
-
-#include "libavutil/vulkan.h"
-
-/**
- * General lavfi IO functions
- */
-int ff_vk_filter_init         (AVFilterContext *avctx);
-int ff_vk_filter_config_input (AVFilterLink   *inlink);
-int ff_vk_filter_config_output(AVFilterLink  *outlink);
-
-/**
- * Can be called manually, if not using ff_vk_filter_config_output.
- */
-int ff_vk_filter_init_context(AVFilterContext *avctx, FFVulkanContext *s,
-                              AVBufferRef *frames_ref,
-                              int width, int height, enum AVPixelFormat sw_format);
-
-/**
- * Submit a compute shader with a zero/one input and single out for execution.
- */
-int ff_vk_filter_process_simple(FFVulkanContext *vkctx, FFVkExecPool *e,
-                                FFVulkanShader *shd, AVFrame *out_f, AVFrame *in_f,
-                                VkSampler sampler, void *push_src, size_t push_size);
-
-/**
- * Submit a compute shader with a single in and single out with 2 stages.
- */
-int ff_vk_filter_process_2pass(FFVulkanContext *vkctx, FFVkExecPool *e,
-                               FFVulkanShader *shd_list[2],
-                               AVFrame *out, AVFrame *tmp, AVFrame *in,
-                               VkSampler sampler, void *push_src, size_t push_size);
-
-/**
- * Up to 16 inputs, one output
- */
-int ff_vk_filter_process_Nin(FFVulkanContext *vkctx, FFVkExecPool *e,
-                             FFVulkanShader *shd,
-                             AVFrame *out, AVFrame *in[], int nb_in,
-                             VkSampler sampler, void *push_src, size_t push_size);
-
-#endif /* AVFILTER_VULKAN_FILTER_H */
-- 
2.49.1


From 1306b83df47bacd1744cb698cbc86f390b951bd3 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:09:03 +0000
Subject: [PATCH 034/118] Changing vulkan file directory

---
 libavfilter/vulkan/vulkan_filter.h | 65 ++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)
 create mode 100644 libavfilter/vulkan/vulkan_filter.h

diff --git a/libavfilter/vulkan/vulkan_filter.h b/libavfilter/vulkan/vulkan_filter.h
new file mode 100644
index 0000000000..045f0e6d73
--- /dev/null
+++ b/libavfilter/vulkan/vulkan_filter.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) Lynne
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVFILTER_VULKAN_FILTER_H
+#define AVFILTER_VULKAN_FILTER_H
+
+#include "libavfilter/avfilter.h"
+
+#include "../../libavutil/vulkan/vulkan.h"
+
+/**
+ * General lavfi IO functions
+ */
+int ff_vk_filter_init         (AVFilterContext *avctx);
+int ff_vk_filter_config_input (AVFilterLink   *inlink);
+int ff_vk_filter_config_output(AVFilterLink  *outlink);
+
+/**
+ * Can be called manually, if not using ff_vk_filter_config_output.
+ */
+int ff_vk_filter_init_context(AVFilterContext *avctx, FFVulkanContext *s,
+                              AVBufferRef *frames_ref,
+                              int width, int height, enum AVPixelFormat sw_format);
+
+/**
+ * Submit a compute shader with a zero/one input and single out for execution.
+ */
+int ff_vk_filter_process_simple(FFVulkanContext *vkctx, FFVkExecPool *e,
+                                FFVulkanShader *shd, AVFrame *out_f, AVFrame *in_f,
+                                VkSampler sampler, void *push_src, size_t push_size);
+
+/**
+ * Submit a compute shader with a single in and single out with 2 stages.
+ */
+int ff_vk_filter_process_2pass(FFVulkanContext *vkctx, FFVkExecPool *e,
+                               FFVulkanShader *shd_list[2],
+                               AVFrame *out, AVFrame *tmp, AVFrame *in,
+                               VkSampler sampler, void *push_src, size_t push_size);
+
+/**
+ * Up to 16 inputs, one output
+ */
+int ff_vk_filter_process_Nin(FFVulkanContext *vkctx, FFVkExecPool *e,
+                             FFVulkanShader *shd,
+                             AVFrame *out, AVFrame *in[], int nb_in,
+                             VkSampler sampler, void *push_src, size_t push_size);
+
+#endif /* AVFILTER_VULKAN_FILTER_H */
-- 
2.49.1


From 198667bb79f9e3ea36e9d72620fa5a2c4c42b099 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:09:39 +0000
Subject: [PATCH 035/118] Changing vulkan file directory

---
 libavfilter/vulkan/vulkan_source.c | 188 +++++++++++++++++++++++++++++
 1 file changed, 188 insertions(+)
 create mode 100644 libavfilter/vulkan/vulkan_source.c

diff --git a/libavfilter/vulkan/vulkan_source.c b/libavfilter/vulkan/vulkan_source.c
new file mode 100644
index 0000000000..16e709980a
--- /dev/null
+++ b/libavfilter/vulkan/vulkan_source.c
@@ -0,0 +1,188 @@
+#include <stddef.h>
+#include "vulkan_source.h"
+
+const char *ff_source_bwdif_comp = "\
+const vec4 coef_lf[2] = { vec4(4309), vec4(213), };\n\
+const vec4 coef_hf[3] = { vec4(5570), vec4(3801), vec4(1016) };\n\
+const vec4 coef_sp[2] = { vec4(5077), vec4(981), };\n\
+\n\
+vec4 process_intra(vec4 cur[4])\n\
+{\n\
+   return (coef_sp[0]*(cur[1] + cur[2]) - coef_sp[1]*(cur[0] + cur[3])) / (1 << 13);\n\
+}\n\
+\n\
+void process_plane_intra(int idx, ivec2 pos)\n\
+{\n\
+    vec4 dcur[4];\n\
+    dcur[0] = imageLoad(cur[idx], pos - ivec2(0, 3));\n\
+    dcur[1] = imageLoad(cur[idx], pos - ivec2(0, 1));\n\
+    dcur[2] = imageLoad(cur[idx], pos + ivec2(0, 1));\n\
+    dcur[3] = imageLoad(cur[idx], pos + ivec2(0, 3));\n\
+    imageStore(dst[idx], pos, process_intra(dcur));\n\
+}\n\
+\n\
+vec4 process_line(vec4 prev2[5], vec4 prev1[2], vec4 cur[4], vec4 next1[2], vec4 next2[5])\n\
+{\n\
+   vec4 fc = cur[1];\n\
+   vec4 fe = cur[2];\n\
+   vec4 fs = prev2[2] + next2[2];\n\
+   vec4 fd = fs / 2;\n\
+\n\
+   vec4 temp_diff[3];\n\
+   temp_diff[0] = abs(prev2[2] - next2[2]);\n\
+   temp_diff[1] = (abs(prev1[0] - fc) + abs(prev1[1] - fe)) / 2;\n\
+   temp_diff[2] = (abs(next1[0] - fc) + abs(next1[1] - fe)) / 2;\n\
+   vec4 diff = max(temp_diff[0] / 2, max(temp_diff[1], temp_diff[2]));\n\
+   bvec4 diff_mask = equal(diff, vec4(0));\n\
+\n\
+   vec4 fbs = prev2[1] + next2[1];\n\
+   vec4 ffs = prev2[3] + next2[3];\n\
+   vec4 fb = (fbs / 2) - fc;\n\
+   vec4 ff = (ffs / 2) - fe;\n\
+   vec4 dc = fd - fc;\n\
+   vec4 de = fd - fe;\n\
+   vec4 mmax = max(de, max(dc, min(fb, ff)));\n\
+   vec4 mmin = min(de, min(dc, max(fb, ff)));\n\
+   diff = max(diff, max(mmin, -mmax));\n\
+\n\
+   vec4 interpolate_all = (((coef_hf[0]*(fs) - coef_hf[1]*(fbs + ffs) +\n\
+                             coef_hf[2]*(prev2[0] + next2[0] + prev2[4] + next2[4])) / 4) +\n\
+                           coef_lf[0]*(fc + fe) - coef_lf[1]*(cur[0] + cur[3])) / (1 << 13);\n\
+   vec4 interpolate_cur = (coef_sp[0]*(fc + fe) - coef_sp[1]*(cur[0] + cur[3])) / (1 << 13);\n\
+\n\
+   bvec4 interpolate_cnd1 = greaterThan(abs(fc - fe), temp_diff[0]);\n\
+   vec4 interpol = mix(interpolate_cur, interpolate_all, interpolate_cnd1);\n\
+   interpol = clamp(interpol, fd - diff, fd + diff);\n\
+   return mix(interpol, fd, diff_mask);\n\
+}\n\
+\n\
+void process_plane(int idx, const ivec2 pos, bool filter_field,\n\
+                   bool is_intra, bool field_parity)\n\
+{\n\
+    vec4 dcur[4];\n\
+    vec4 prev1[2];\n\
+    vec4 next1[2];\n\
+    vec4 prev2[5];\n\
+    vec4 next2[5];\n\
+\n\
+    dcur[0] = imageLoad(cur[idx], pos - ivec2(0, 3));\n\
+    dcur[1] = imageLoad(cur[idx], pos - ivec2(0, 1));\n\
+    dcur[2] = imageLoad(cur[idx], pos + ivec2(0, 1));\n\
+    dcur[3] = imageLoad(cur[idx], pos + ivec2(0, 3));\n\
+\n\
+    prev1[0] = imageLoad(prev[idx], pos - ivec2(0, 1));\n\
+    prev1[1] = imageLoad(prev[idx], pos + ivec2(0, 1));\n\
+\n\
+    next1[0] = imageLoad(next[idx], pos - ivec2(0, 1));\n\
+    next1[1] = imageLoad(next[idx], pos + ivec2(0, 1));\n\
+\n\
+    if (field_parity) {\n\
+        prev2[0] = imageLoad(prev[idx], pos - ivec2(0, 4));\n\
+        prev2[1] = imageLoad(prev[idx], pos - ivec2(0, 2));\n\
+        prev2[2] = imageLoad(prev[idx], pos);\n\
+        prev2[3] = imageLoad(prev[idx], pos + ivec2(0, 2));\n\
+        prev2[4] = imageLoad(prev[idx], pos + ivec2(0, 4));\n\
+\n\
+        next2[0] = imageLoad(cur[idx], pos - ivec2(0, 4));\n\
+        next2[1] = imageLoad(cur[idx], pos - ivec2(0, 2));\n\
+        next2[2] = imageLoad(cur[idx], pos);\n\
+        next2[3] = imageLoad(cur[idx], pos + ivec2(0, 2));\n\
+        next2[4] = imageLoad(cur[idx], pos + ivec2(0, 4));\n\
+    } else {\n\
+        prev2[0] = imageLoad(cur[idx], pos - ivec2(0, 4));\n\
+        prev2[1] = imageLoad(cur[idx], pos - ivec2(0, 2));\n\
+        prev2[2] = imageLoad(cur[idx], pos);\n\
+        prev2[3] = imageLoad(cur[idx], pos + ivec2(0, 2));\n\
+        prev2[4] = imageLoad(cur[idx], pos + ivec2(0, 4));\n\
+\n\
+        next2[0] = imageLoad(next[idx], pos - ivec2(0, 4));\n\
+        next2[1] = imageLoad(next[idx], pos - ivec2(0, 2));\n\
+        next2[2] = imageLoad(next[idx], pos);\n\
+        next2[3] = imageLoad(next[idx], pos + ivec2(0, 2));\n\
+        next2[4] = imageLoad(next[idx], pos + ivec2(0, 4));\n\
+    }\n\
+\n\
+    imageStore(dst[idx], pos, process_line(prev2, prev1, dcur, next1, next2));\n\
+}";
+
+const char *ff_source_debayer_comp = "\
+#define LD(xo, yo) \\\n\
+    (imageLoad(input_img[0], pos + ivec2((xo), (yo))).r)\n\
+\n\
+void debayer_bilinear(void)\n\
+{\n\
+    ivec2 pos = ivec2(gl_GlobalInvocationID.xy) << 1;\n\
+\n\
+    /* R basis */\n\
+    vec4 tl = vec4(LD(0, 0),\n\
+                   (LD(1, 0) + LD(-1, 0) + LD(0, 1) + LD(0, -1)) / 4.0f,\n\
+                   (LD(-1, -1) + LD(1, 1) + LD(-1, 1) + LD(1, -1)) / 4.0f,\n\
+                   1.0f);\n\
+    imageStore(output_img[0], pos, tl);\n\
+\n\
+    /* G1 basis */\n\
+    vec4 tr = vec4((LD(2, 0) + LD(0, 0)) / 2.0f,\n\
+                   LD(1, 0),\n\
+                   (LD(1, 1) + LD(1, -1)) / 2.0f,\n\
+                   1.0f);\n\
+    imageStore(output_img[0], pos + ivec2(1, 0), tr);\n\
+\n\
+    /* G2 basis */\n\
+    vec4 bl = vec4((LD(0, 2) + LD(0, 0)) / 2.0f,\n\
+                   LD(0, 1),\n\
+                   (LD(1, 1) + LD(-1, 1)) / 2.0f,\n\
+                   1.0f);\n\
+    imageStore(output_img[0], pos + ivec2(0, 1), bl);\n\
+\n\
+    /* B basis */\n\
+    vec4 br = vec4((LD(0, 0) + LD(2, 2) + LD(0, 2) + LD(2, 0)) / 4.0f,\n\
+                   (LD(2, 1) + LD(0, 1) + LD(1, 2) + LD(1, 0)) / 4.0f,\n\
+                   LD(1, 1),\n\
+                   1.0f);\n\
+    imageStore(output_img[0], pos + ivec2(1, 1), br);\n\
+}\n\
+\n\
+void debayer_bilinear_hq(void)\n\
+{\n\
+    ivec2 pos = ivec2(gl_GlobalInvocationID.xy) << 1;\n\
+\n\
+    /* R basis */\n\
+    vec4 tl = vec4(LD(0, 0),\n\
+                   (4.0f*LD(0, 0) + 2.0f*(LD(0, -1) + LD(0, 1) + LD(-1, 0) + LD(1, 0)) -\n\
+                    (LD(0, -2) + LD(0, 2) + LD(-2, 0) + LD(2, 0))) / 8.0f,\n\
+                   (12.0f*LD(0, 0) + 4.0f*(LD(-1, -1) + LD(-1, 1) + LD(1, -1) + LD(1, 1)) -\n\
+                    3.0f*(LD(0, -2) + LD(0, 2) + LD(-2, 0) + LD(2, 0))) / 16.0f,\n\
+                   1.0f);\n\
+    imageStore(output_img[0], pos, tl);\n\
+\n\
+    /* G1 basis */\n\
+    vec4 tr = vec4((10.0f*LD(1, 0) + 8.0f*(LD(0, 0) + LD(2, 0)) -\n\
+                    2.0f*(LD(0, -1) + LD(2, 1) + LD(0, 1) + LD(2, -1) + LD(-1, 0) + LD(3, 0)) +\n\
+                    LD(1, -2) + LD(1, 2)) / 16.0f,\n\
+                   LD(1, 0),\n\
+                   (10.0f*LD(1, 0) + 8.0f*(LD(1, -1) + LD(1, 1)) -\n\
+                    2.0f*(LD(0, -1) + LD(0, 1) + LD(2, -1) + LD(2, 1) + LD(1, -2) + LD(1, 2)) +\n\
+                    LD(-1, 0) + LD(3, 0)) / 16.0f,\n\
+                   1.0f);\n\
+    imageStore(output_img[0], pos + ivec2(1, 0), tr);\n\
+\n\
+    /* G2 basis */\n\
+    vec4 bl = vec4((10.0f*LD(0, 1) + 8.0f*(LD(0, 0) + LD(0, 2)) -\n\
+                   2.0f*(LD(-1, 0) + LD(-1, 2) + LD(1, 0) + LD(1, 2) + LD(0, -1) + LD(0, 3)) +\n\
+                   LD(-2, 1) + LD(2, 1)) / 16.0f,\n\
+                   LD(0, 1),\n\
+                   (10.0f*LD(0, 1) + 8.0f*(LD(-1, 1) + LD(1, 1)) -\n\
+                   2.0f*(LD(-1, 0) + LD(1, 2) + LD(-1, 2) + LD(1, 0) + LD(-2, 1) + LD(2, 1)) +\n\
+                    LD(0, -1) + LD(0, 3)) / 16.0f,\n\
+                   1.0f);\n\
+    imageStore(output_img[0], pos + ivec2(0, 1), bl);\n\
+\n\
+    /* B basis */\n\
+    vec4 br = vec4((12.0f*LD(1, 1) + 4.0f*(LD(0, 0) + LD(0, 2) + LD(2, 0) + LD(2, 2)) -\n\
+                    3.0f*(LD(1, -1) + LD(1, 3) + LD(-1, 1) + LD(3, 1))) / 16.0f,\n\
+                   (4.0f*LD(1, 1) + 2.0f*(LD(1, 0) + LD(1, 2) + LD(0, 1) + LD(2, 1)) -\n\
+                    (LD(1, -1) + LD(1, 3) + LD(-1, 1) + LD(3, 1))) / 8.0f,\n\
+                   LD(1, 1),\n\
+                   1.0f);\n\
+    imageStore(output_img[0], pos + ivec2(1, 1), br);\n\
+}";
-- 
2.49.1


From 9dcc0332b7e6f28920bf3e5d26d1b96b5c930999 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:10:18 +0000
Subject: [PATCH 036/118] Changing vulkan file directory

---
 libavfilter/vulkan/vulkan_source.h | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 libavfilter/vulkan/vulkan_source.h

diff --git a/libavfilter/vulkan/vulkan_source.h b/libavfilter/vulkan/vulkan_source.h
new file mode 100644
index 0000000000..b756654852
--- /dev/null
+++ b/libavfilter/vulkan/vulkan_source.h
@@ -0,0 +1,25 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVFILTER_VULKAN_SOURCE_H
+#define AVFILTER_VULKAN_SOURCE_H
+
+extern const char *ff_source_bwdif_comp;
+extern const char *ff_source_debayer_comp;
+
+#endif /* AVFILTER_VULKAN_SOURCE_H */
-- 
2.49.1


From 10cb6227192a78e1fea6461fe7cd06ba96c424eb Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:10:47 +0000
Subject: [PATCH 037/118] Changing vulkan file directory

---
 libavfilter/vulkan/bwdif.comp | 122 ----------------------------------
 1 file changed, 122 deletions(-)
 delete mode 100644 libavfilter/vulkan/bwdif.comp

diff --git a/libavfilter/vulkan/bwdif.comp b/libavfilter/vulkan/bwdif.comp
deleted file mode 100644
index 5152464823..0000000000
--- a/libavfilter/vulkan/bwdif.comp
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) Lynne
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-const vec4 coef_lf[2] = { vec4(4309), vec4(213), };
-const vec4 coef_hf[3] = { vec4(5570), vec4(3801), vec4(1016) };
-const vec4 coef_sp[2] = { vec4(5077), vec4(981), };
-
-vec4 process_intra(vec4 cur[4])
-{
-   return (coef_sp[0]*(cur[1] + cur[2]) - coef_sp[1]*(cur[0] + cur[3])) / (1 << 13);
-}
-
-void process_plane_intra(int idx, ivec2 pos)
-{
-    vec4 dcur[4];
-    dcur[0] = imageLoad(cur[idx], pos - ivec2(0, 3));
-    dcur[1] = imageLoad(cur[idx], pos - ivec2(0, 1));
-    dcur[2] = imageLoad(cur[idx], pos + ivec2(0, 1));
-    dcur[3] = imageLoad(cur[idx], pos + ivec2(0, 3));
-    imageStore(dst[idx], pos, process_intra(dcur));
-}
-
-vec4 process_line(vec4 prev2[5], vec4 prev1[2], vec4 cur[4], vec4 next1[2], vec4 next2[5])
-{
-   vec4 fc = cur[1];
-   vec4 fe = cur[2];
-   vec4 fs = prev2[2] + next2[2];
-   vec4 fd = fs / 2;
-
-   vec4 temp_diff[3];
-   temp_diff[0] = abs(prev2[2] - next2[2]);
-   temp_diff[1] = (abs(prev1[0] - fc) + abs(prev1[1] - fe)) / 2;
-   temp_diff[2] = (abs(next1[0] - fc) + abs(next1[1] - fe)) / 2;
-   vec4 diff = max(temp_diff[0] / 2, max(temp_diff[1], temp_diff[2]));
-   bvec4 diff_mask = equal(diff, vec4(0));
-
-   vec4 fbs = prev2[1] + next2[1];
-   vec4 ffs = prev2[3] + next2[3];
-   vec4 fb = (fbs / 2) - fc;
-   vec4 ff = (ffs / 2) - fe;
-   vec4 dc = fd - fc;
-   vec4 de = fd - fe;
-   vec4 mmax = max(de, max(dc, min(fb, ff)));
-   vec4 mmin = min(de, min(dc, max(fb, ff)));
-   diff = max(diff, max(mmin, -mmax));
-
-   vec4 interpolate_all = (((coef_hf[0]*(fs) - coef_hf[1]*(fbs + ffs) +
-                             coef_hf[2]*(prev2[0] + next2[0] + prev2[4] + next2[4])) / 4) +
-                           coef_lf[0]*(fc + fe) - coef_lf[1]*(cur[0] + cur[3])) / (1 << 13);
-   vec4 interpolate_cur = (coef_sp[0]*(fc + fe) - coef_sp[1]*(cur[0] + cur[3])) / (1 << 13);
-
-   bvec4 interpolate_cnd1 = greaterThan(abs(fc - fe), temp_diff[0]);
-   vec4 interpol = mix(interpolate_cur, interpolate_all, interpolate_cnd1);
-   interpol = clamp(interpol, fd - diff, fd + diff);
-   return mix(interpol, fd, diff_mask);
-}
-
-void process_plane(int idx, const ivec2 pos, bool filter_field,
-                   bool is_intra, bool field_parity)
-{
-    vec4 dcur[4];
-    vec4 prev1[2];
-    vec4 next1[2];
-    vec4 prev2[5];
-    vec4 next2[5];
-
-    dcur[0] = imageLoad(cur[idx], pos - ivec2(0, 3));
-    dcur[1] = imageLoad(cur[idx], pos - ivec2(0, 1));
-    dcur[2] = imageLoad(cur[idx], pos + ivec2(0, 1));
-    dcur[3] = imageLoad(cur[idx], pos + ivec2(0, 3));
-
-    prev1[0] = imageLoad(prev[idx], pos - ivec2(0, 1));
-    prev1[1] = imageLoad(prev[idx], pos + ivec2(0, 1));
-
-    next1[0] = imageLoad(next[idx], pos - ivec2(0, 1));
-    next1[1] = imageLoad(next[idx], pos + ivec2(0, 1));
-
-    if (field_parity) {
-        prev2[0] = imageLoad(prev[idx], pos - ivec2(0, 4));
-        prev2[1] = imageLoad(prev[idx], pos - ivec2(0, 2));
-        prev2[2] = imageLoad(prev[idx], pos);
-        prev2[3] = imageLoad(prev[idx], pos + ivec2(0, 2));
-        prev2[4] = imageLoad(prev[idx], pos + ivec2(0, 4));
-
-        next2[0] = imageLoad(cur[idx], pos - ivec2(0, 4));
-        next2[1] = imageLoad(cur[idx], pos - ivec2(0, 2));
-        next2[2] = imageLoad(cur[idx], pos);
-        next2[3] = imageLoad(cur[idx], pos + ivec2(0, 2));
-        next2[4] = imageLoad(cur[idx], pos + ivec2(0, 4));
-    } else {
-        prev2[0] = imageLoad(cur[idx], pos - ivec2(0, 4));
-        prev2[1] = imageLoad(cur[idx], pos - ivec2(0, 2));
-        prev2[2] = imageLoad(cur[idx], pos);
-        prev2[3] = imageLoad(cur[idx], pos + ivec2(0, 2));
-        prev2[4] = imageLoad(cur[idx], pos + ivec2(0, 4));
-
-        next2[0] = imageLoad(next[idx], pos - ivec2(0, 4));
-        next2[1] = imageLoad(next[idx], pos - ivec2(0, 2));
-        next2[2] = imageLoad(next[idx], pos);
-        next2[3] = imageLoad(next[idx], pos + ivec2(0, 2));
-        next2[4] = imageLoad(next[idx], pos + ivec2(0, 4));
-    }
-
-    imageStore(dst[idx], pos, process_line(prev2, prev1, dcur, next1, next2));
-}
-- 
2.49.1


From c38b0cbce5614088c0f599da96ed798b2e67b9e3 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:10:58 +0000
Subject: [PATCH 038/118] Changing vulkan file directory

---
 libavfilter/vulkan/debayer.comp | 102 --------------------------------
 1 file changed, 102 deletions(-)
 delete mode 100644 libavfilter/vulkan/debayer.comp

diff --git a/libavfilter/vulkan/debayer.comp b/libavfilter/vulkan/debayer.comp
deleted file mode 100644
index c86c2f5eec..0000000000
--- a/libavfilter/vulkan/debayer.comp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *
- * Copyright (c) 2025 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#define LD(xo, yo) \
-    (imageLoad(input_img[0], pos + ivec2((xo), (yo))).r)
-
-void debayer_bilinear(void)
-{
-    ivec2 pos = ivec2(gl_GlobalInvocationID.xy) << 1;
-
-    /* R basis */
-    vec4 tl = vec4(LD(0, 0),
-                   (LD(1, 0) + LD(-1, 0) + LD(0, 1) + LD(0, -1)) / 4.0f,
-                   (LD(-1, -1) + LD(1, 1) + LD(-1, 1) + LD(1, -1)) / 4.0f,
-                   1.0f);
-    imageStore(output_img[0], pos, tl);
-
-    /* G1 basis */
-    vec4 tr = vec4((LD(2, 0) + LD(0, 0)) / 2.0f,
-                   LD(1, 0),
-                   (LD(1, 1) + LD(1, -1)) / 2.0f,
-                   1.0f);
-    imageStore(output_img[0], pos + ivec2(1, 0), tr);
-
-    /* G2 basis */
-    vec4 bl = vec4((LD(0, 2) + LD(0, 0)) / 2.0f,
-                   LD(0, 1),
-                   (LD(1, 1) + LD(-1, 1)) / 2.0f,
-                   1.0f);
-    imageStore(output_img[0], pos + ivec2(0, 1), bl);
-
-    /* B basis */
-    vec4 br = vec4((LD(0, 0) + LD(2, 2) + LD(0, 2) + LD(2, 0)) / 4.0f,
-                   (LD(2, 1) + LD(0, 1) + LD(1, 2) + LD(1, 0)) / 4.0f,
-                   LD(1, 1),
-                   1.0f);
-    imageStore(output_img[0], pos + ivec2(1, 1), br);
-}
-
-void debayer_bilinear_hq(void)
-{
-    ivec2 pos = ivec2(gl_GlobalInvocationID.xy) << 1;
-
-    /* R basis */
-    vec4 tl = vec4(LD(0, 0),
-                   (4.0f*LD(0, 0) + 2.0f*(LD(0, -1) + LD(0, 1) + LD(-1, 0) + LD(1, 0)) -
-                    (LD(0, -2) + LD(0, 2) + LD(-2, 0) + LD(2, 0))) / 8.0f,
-                   (12.0f*LD(0, 0) + 4.0f*(LD(-1, -1) + LD(-1, 1) + LD(1, -1) + LD(1, 1)) -
-                    3.0f*(LD(0, -2) + LD(0, 2) + LD(-2, 0) + LD(2, 0))) / 16.0f,
-                   1.0f);
-    imageStore(output_img[0], pos, tl);
-
-    /* G1 basis */
-    vec4 tr = vec4((10.0f*LD(1, 0) + 8.0f*(LD(0, 0) + LD(2, 0)) -
-                    2.0f*(LD(0, -1) + LD(2, 1) + LD(0, 1) + LD(2, -1) + LD(-1, 0) + LD(3, 0)) +
-                    LD(1, -2) + LD(1, 2)) / 16.0f,
-                   LD(1, 0),
-                   (10.0f*LD(1, 0) + 8.0f*(LD(1, -1) + LD(1, 1)) -
-                    2.0f*(LD(0, -1) + LD(0, 1) + LD(2, -1) + LD(2, 1) + LD(1, -2) + LD(1, 2)) +
-                    LD(-1, 0) + LD(3, 0)) / 16.0f,
-                   1.0f);
-    imageStore(output_img[0], pos + ivec2(1, 0), tr);
-
-
-    /* G2 basis */
-    vec4 bl = vec4((10.0f*LD(0, 1) + 8.0f*(LD(0, 0) + LD(0, 2)) -
-                   2.0f*(LD(-1, 0) + LD(-1, 2) + LD(1, 0) + LD(1, 2) + LD(0, -1) + LD(0, 3)) +
-                   LD(-2, 1) + LD(2, 1)) / 16.0f,
-                   LD(0, 1),
-                   (10.0f*LD(0, 1) + 8.0f*(LD(-1, 1) + LD(1, 1)) -
-                   2.0f*(LD(-1, 0) + LD(1, 2) + LD(-1, 2) + LD(1, 0) + LD(-2, 1) + LD(2, 1)) +
-                    LD(0, -1) + LD(0, 3)) / 16.0f,
-                   1.0f);
-    imageStore(output_img[0], pos + ivec2(0, 1), bl);
-
-    /* B basis */
-    vec4 br = vec4((12.0f*LD(1, 1) + 4.0f*(LD(0, 0) + LD(0, 2) + LD(2, 0) + LD(2, 2)) -
-                    3.0f*(LD(1, -1) + LD(1, 3) + LD(-1, 1) + LD(3, 1))) / 16.0f,
-                   (4.0f*LD(1, 1) + 2.0f*(LD(1, 0) + LD(1, 2) + LD(0, 1) + LD(2, 1)) -
-                    (LD(1, -1) + LD(1, 3) + LD(-1, 1) + LD(3, 1))) / 8.0f,
-                   LD(1, 1),
-                   1.0f);
-    imageStore(output_img[0], pos + ivec2(1, 1), br);
-}
-- 
2.49.1


From 205ac1c6183973e11f82feeef9743777dc5c9b94 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:14:07 +0000
Subject: [PATCH 039/118] Changing vulkan file directory

---
 libavutil/hwcontext_vulkan.c | 4790 ----------------------------------
 1 file changed, 4790 deletions(-)
 delete mode 100644 libavutil/hwcontext_vulkan.c

diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
deleted file mode 100644
index 47f894f75f..0000000000
--- a/libavutil/hwcontext_vulkan.c
+++ /dev/null
@@ -1,4790 +0,0 @@
-/*
- * Copyright (c) Lynne
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#define VK_NO_PROTOTYPES
-#define VK_ENABLE_BETA_EXTENSIONS
-
-#ifdef _WIN32
-#include <windows.h> /* Included to prevent conflicts with CreateSemaphore */
-#include <versionhelpers.h>
-#include "compat/w32dlfcn.h"
-#else
-#include <dlfcn.h>
-#include <unistd.h>
-#endif
-
-#include "thread.h"
-
-#include "config.h"
-#include "pixdesc.h"
-#include "avstring.h"
-#include "imgutils.h"
-#include "hwcontext.h"
-#include "hwcontext_internal.h"
-#include "hwcontext_vulkan.h"
-#include "mem.h"
-
-#include "vulkan.h"
-#include "vulkan_loader.h"
-
-#if CONFIG_VAAPI
-#include "hwcontext_vaapi.h"
-#endif
-
-#if CONFIG_LIBDRM
-#if CONFIG_VAAPI
-#include <va/va_drmcommon.h>
-#endif
-#ifdef __linux__
-#include <sys/sysmacros.h>
-#endif
-#include <sys/stat.h>
-#include <xf86drm.h>
-#include <drm_fourcc.h>
-#include "hwcontext_drm.h"
-#endif
-
-#if HAVE_LINUX_DMA_BUF_H
-#include <sys/ioctl.h>
-#include <linux/dma-buf.h>
-#endif
-
-#if CONFIG_CUDA
-#include "hwcontext_cuda_internal.h"
-#include "cuda_check.h"
-#define CHECK_CU(x) FF_CUDA_CHECK_DL(cuda_cu, cu, x)
-#endif
-
-typedef struct VulkanDeviceFeatures {
-    VkPhysicalDeviceFeatures2 device;
-
-    VkPhysicalDeviceVulkan11Features vulkan_1_1;
-    VkPhysicalDeviceVulkan12Features vulkan_1_2;
-    VkPhysicalDeviceVulkan13Features vulkan_1_3;
-    VkPhysicalDeviceTimelineSemaphoreFeatures timeline_semaphore;
-    VkPhysicalDeviceShaderSubgroupRotateFeaturesKHR subgroup_rotate;
-    VkPhysicalDeviceHostImageCopyFeaturesEXT host_image_copy;
-
-#ifdef VK_KHR_shader_expect_assume
-    VkPhysicalDeviceShaderExpectAssumeFeaturesKHR expect_assume;
-#endif
-
-    VkPhysicalDeviceVideoMaintenance1FeaturesKHR video_maintenance_1;
-#ifdef VK_KHR_video_maintenance2
-    VkPhysicalDeviceVideoMaintenance2FeaturesKHR video_maintenance_2;
-#endif
-#ifdef VK_KHR_video_decode_vp9
-    VkPhysicalDeviceVideoDecodeVP9FeaturesKHR vp9_decode;
-#endif
-#ifdef VK_KHR_video_encode_av1
-    VkPhysicalDeviceVideoEncodeAV1FeaturesKHR av1_encode;
-#endif
-
-    VkPhysicalDeviceShaderObjectFeaturesEXT shader_object;
-    VkPhysicalDeviceCooperativeMatrixFeaturesKHR cooperative_matrix;
-    VkPhysicalDeviceDescriptorBufferFeaturesEXT descriptor_buffer;
-    VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float;
-
-#ifdef VK_KHR_shader_relaxed_extended_instruction
-    VkPhysicalDeviceShaderRelaxedExtendedInstructionFeaturesKHR relaxed_extended_instruction;
-#endif
-} VulkanDeviceFeatures;
-
-typedef struct VulkanDevicePriv {
-    /**
-     * The public AVVulkanDeviceContext. See hwcontext_vulkan.h for it.
-     */
-    AVVulkanDeviceContext p;
-
-    /* Vulkan library and loader functions */
-    void *libvulkan;
-
-    FFVulkanContext    vkctx;
-    AVVulkanDeviceQueueFamily *compute_qf;
-    AVVulkanDeviceQueueFamily *transfer_qf;
-
-    /* Properties */
-    VkPhysicalDeviceProperties2 props;
-    VkPhysicalDeviceMemoryProperties mprops;
-    VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops;
-    VkPhysicalDeviceDriverProperties dprops;
-
-    /* Opaque FD external semaphore properties */
-    VkExternalSemaphoreProperties ext_sem_props_opaque;
-
-    /* Enabled features */
-    VulkanDeviceFeatures feats;
-
-    /* Queues */
-    pthread_mutex_t **qf_mutex;
-    uint32_t nb_tot_qfs;
-    uint32_t img_qfs[64];
-    uint32_t nb_img_qfs;
-
-    /* Debug callback */
-    VkDebugUtilsMessengerEXT debug_ctx;
-
-    /* Settings */
-    int use_linear_images;
-
-    /* Option to allocate all image planes in a single allocation */
-    int contiguous_planes;
-
-    /* Disable multiplane images */
-    int disable_multiplane;
-
-    /* Disable host image transfer */
-    int disable_host_transfer;
-
-    /* Prefer memcpy over dynamic host pointer imports */
-    int avoid_host_import;
-
-    /* Maximum queues */
-    int limit_queues;
-} VulkanDevicePriv;
-
-typedef struct VulkanFramesPriv {
-    /**
-     * The public AVVulkanFramesContext. See hwcontext_vulkan.h for it.
-     */
-    AVVulkanFramesContext p;
-
-    /* Image conversions */
-    FFVkExecPool compute_exec;
-
-    /* Image transfers */
-    FFVkExecPool upload_exec;
-    FFVkExecPool download_exec;
-
-    /* Temporary buffer pools */
-    AVBufferPool *tmp;
-
-    /* Modifier info list to free at uninit */
-    VkImageDrmFormatModifierListCreateInfoEXT *modifier_info;
-
-    /* Properties for DRM modifier for each plane in the image */
-    VkDrmFormatModifierPropertiesEXT drm_format_modifier_properties[5];
-} VulkanFramesPriv;
-
-typedef struct AVVkFrameInternal {
-    pthread_mutex_t update_mutex;
-
-#if CONFIG_CUDA
-    /* Importing external memory into cuda is really expensive so we keep the
-     * memory imported all the time */
-    AVBufferRef *cuda_fc_ref; /* Need to keep it around for uninit */
-    CUexternalMemory ext_mem[AV_NUM_DATA_POINTERS];
-    CUmipmappedArray cu_mma[AV_NUM_DATA_POINTERS];
-    CUarray cu_array[AV_NUM_DATA_POINTERS];
-    CUexternalSemaphore cu_sem[AV_NUM_DATA_POINTERS];
-#ifdef _WIN32
-    HANDLE ext_mem_handle[AV_NUM_DATA_POINTERS];
-    HANDLE ext_sem_handle[AV_NUM_DATA_POINTERS];
-#endif
-#endif
-} AVVkFrameInternal;
-
-/* Initialize all structs in VulkanDeviceFeatures */
-static void device_features_init(AVHWDeviceContext *ctx, VulkanDeviceFeatures *feats)
-{
-    VulkanDevicePriv *p = ctx->hwctx;
-    FFVulkanContext *s = &p->vkctx;
-
-    feats->device = (VkPhysicalDeviceFeatures2) {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
-    };
-
-    FF_VK_STRUCT_EXT(s, &feats->device, &feats->vulkan_1_1, FF_VK_EXT_NO_FLAG,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES);
-    FF_VK_STRUCT_EXT(s, &feats->device, &feats->vulkan_1_2, FF_VK_EXT_NO_FLAG,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES);
-    FF_VK_STRUCT_EXT(s, &feats->device, &feats->vulkan_1_3, FF_VK_EXT_NO_FLAG,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES);
-
-    FF_VK_STRUCT_EXT(s, &feats->device, &feats->timeline_semaphore, FF_VK_EXT_PORTABILITY_SUBSET,
-                     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,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES_KHR);
-#endif
-
-    FF_VK_STRUCT_EXT(s, &feats->device, &feats->video_maintenance_1, FF_VK_EXT_VIDEO_MAINTENANCE_1,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR);
-#ifdef VK_KHR_video_maintenance2
-    FF_VK_STRUCT_EXT(s, &feats->device, &feats->video_maintenance_2, FF_VK_EXT_VIDEO_MAINTENANCE_2,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_2_FEATURES_KHR);
-#endif
-#ifdef VK_KHR_video_decode_vp9
-    FF_VK_STRUCT_EXT(s, &feats->device, &feats->vp9_decode, FF_VK_EXT_VIDEO_DECODE_VP9,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_DECODE_VP9_FEATURES_KHR);
-#endif
-#ifdef VK_KHR_video_encode_av1
-    FF_VK_STRUCT_EXT(s, &feats->device, &feats->av1_encode, FF_VK_EXT_VIDEO_ENCODE_AV1,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_AV1_FEATURES_KHR);
-#endif
-
-    FF_VK_STRUCT_EXT(s, &feats->device, &feats->shader_object, FF_VK_EXT_SHADER_OBJECT,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT);
-    FF_VK_STRUCT_EXT(s, &feats->device, &feats->cooperative_matrix, FF_VK_EXT_COOP_MATRIX,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR);
-    FF_VK_STRUCT_EXT(s, &feats->device, &feats->descriptor_buffer, FF_VK_EXT_DESCRIPTOR_BUFFER,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT);
-    FF_VK_STRUCT_EXT(s, &feats->device, &feats->atomic_float, FF_VK_EXT_ATOMIC_FLOAT,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT);
-
-#ifdef VK_KHR_shader_relaxed_extended_instruction
-    FF_VK_STRUCT_EXT(s, &feats->device, &feats->relaxed_extended_instruction, FF_VK_EXT_RELAXED_EXTENDED_INSTR,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_RELAXED_EXTENDED_INSTRUCTION_FEATURES_KHR);
-#endif
-}
-
-/* Copy all needed device features */
-static void device_features_copy_needed(VulkanDeviceFeatures *dst, VulkanDeviceFeatures *src)
-{
-#define COPY_VAL(VAL)        \
-    do {                     \
-        dst->VAL = src->VAL; \
-    } while (0)              \
-
-    COPY_VAL(device.features.shaderImageGatherExtended);
-    COPY_VAL(device.features.shaderStorageImageReadWithoutFormat);
-    COPY_VAL(device.features.shaderStorageImageWriteWithoutFormat);
-    COPY_VAL(device.features.fragmentStoresAndAtomics);
-    COPY_VAL(device.features.vertexPipelineStoresAndAtomics);
-    COPY_VAL(device.features.shaderInt64);
-    COPY_VAL(device.features.shaderInt16);
-    COPY_VAL(device.features.shaderFloat64);
-    COPY_VAL(device.features.shaderStorageImageReadWithoutFormat);
-    COPY_VAL(device.features.shaderStorageImageWriteWithoutFormat);
-
-    COPY_VAL(vulkan_1_1.samplerYcbcrConversion);
-    COPY_VAL(vulkan_1_1.storagePushConstant16);
-    COPY_VAL(vulkan_1_1.storageBuffer16BitAccess);
-    COPY_VAL(vulkan_1_1.uniformAndStorageBuffer16BitAccess);
-
-    COPY_VAL(vulkan_1_2.timelineSemaphore);
-    COPY_VAL(vulkan_1_2.scalarBlockLayout);
-    COPY_VAL(vulkan_1_2.bufferDeviceAddress);
-    COPY_VAL(vulkan_1_2.hostQueryReset);
-    COPY_VAL(vulkan_1_2.storagePushConstant8);
-    COPY_VAL(vulkan_1_2.shaderInt8);
-    COPY_VAL(vulkan_1_2.storageBuffer8BitAccess);
-    COPY_VAL(vulkan_1_2.uniformAndStorageBuffer8BitAccess);
-    COPY_VAL(vulkan_1_2.shaderFloat16);
-    COPY_VAL(vulkan_1_2.shaderBufferInt64Atomics);
-    COPY_VAL(vulkan_1_2.shaderSharedInt64Atomics);
-    COPY_VAL(vulkan_1_2.vulkanMemoryModel);
-    COPY_VAL(vulkan_1_2.vulkanMemoryModelDeviceScope);
-    COPY_VAL(vulkan_1_2.uniformBufferStandardLayout);
-
-    COPY_VAL(vulkan_1_3.dynamicRendering);
-    COPY_VAL(vulkan_1_3.maintenance4);
-    COPY_VAL(vulkan_1_3.synchronization2);
-    COPY_VAL(vulkan_1_3.computeFullSubgroups);
-    COPY_VAL(vulkan_1_3.subgroupSizeControl);
-    COPY_VAL(vulkan_1_3.shaderZeroInitializeWorkgroupMemory);
-    COPY_VAL(vulkan_1_3.dynamicRendering);
-
-    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
-    COPY_VAL(video_maintenance_2.videoMaintenance2);
-#endif
-
-#ifdef VK_KHR_video_decode_vp9
-    COPY_VAL(vp9_decode.videoDecodeVP9);
-#endif
-
-#ifdef VK_KHR_video_encode_av1
-    COPY_VAL(av1_encode.videoEncodeAV1);
-#endif
-
-    COPY_VAL(shader_object.shaderObject);
-
-    COPY_VAL(cooperative_matrix.cooperativeMatrix);
-
-    COPY_VAL(descriptor_buffer.descriptorBuffer);
-    COPY_VAL(descriptor_buffer.descriptorBufferPushDescriptors);
-
-    COPY_VAL(atomic_float.shaderBufferFloat32Atomics);
-    COPY_VAL(atomic_float.shaderBufferFloat32AtomicAdd);
-
-#ifdef VK_KHR_shader_relaxed_extended_instruction
-    COPY_VAL(relaxed_extended_instruction.shaderRelaxedExtendedInstruction);
-#endif
-
-#ifdef VK_KHR_shader_expect_assume
-    COPY_VAL(expect_assume.shaderExpectAssume);
-#endif
-
-#undef COPY_VAL
-}
-
-#define ASPECT_2PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT)
-#define ASPECT_3PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT)
-
-static const struct FFVkFormatEntry {
-    VkFormat vkf;
-    enum AVPixelFormat pixfmt;
-    VkImageAspectFlags aspect;
-    int vk_planes;
-    int nb_images;
-    int nb_images_fallback;
-    const VkFormat fallback[5];
-} vk_formats_list[] = {
-    /* Gray formats */
-    { VK_FORMAT_R8_UNORM,   AV_PIX_FMT_GRAY8,   VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8_UNORM   } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GRAY10,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM  } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GRAY12,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM  } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GRAY14,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM  } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GRAY16,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM  } },
-    { VK_FORMAT_R32_UINT,   AV_PIX_FMT_GRAY32,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32_UINT   } },
-    { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GRAYF32, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32_SFLOAT } },
-
-    /* RGB formats */
-    { VK_FORMAT_B8G8R8A8_UNORM,           AV_PIX_FMT_BGRA,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B8G8R8A8_UNORM           } },
-    { VK_FORMAT_R8G8B8A8_UNORM,           AV_PIX_FMT_RGBA,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM           } },
-    { VK_FORMAT_R8G8B8_UNORM,             AV_PIX_FMT_RGB24,   VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8_UNORM             } },
-    { VK_FORMAT_B8G8R8_UNORM,             AV_PIX_FMT_BGR24,   VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B8G8R8_UNORM             } },
-    { VK_FORMAT_R16G16B16_UNORM,          AV_PIX_FMT_RGB48,   VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16_UNORM          } },
-    { VK_FORMAT_R16G16B16A16_UNORM,       AV_PIX_FMT_RGBA64,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM       } },
-    { VK_FORMAT_R5G6B5_UNORM_PACK16,      AV_PIX_FMT_RGB565,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R5G6B5_UNORM_PACK16      } },
-    { VK_FORMAT_B5G6R5_UNORM_PACK16,      AV_PIX_FMT_BGR565,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B5G6R5_UNORM_PACK16      } },
-    { VK_FORMAT_B8G8R8A8_UNORM,           AV_PIX_FMT_BGR0,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B8G8R8A8_UNORM           } },
-    { VK_FORMAT_R8G8B8A8_UNORM,           AV_PIX_FMT_RGB0,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM           } },
-    { VK_FORMAT_A2R10G10B10_UNORM_PACK32, AV_PIX_FMT_X2RGB10, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_A2R10G10B10_UNORM_PACK32 } },
-    { VK_FORMAT_A2B10G10R10_UNORM_PACK32, AV_PIX_FMT_X2BGR10, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_A2B10G10R10_UNORM_PACK32 } },
-    { VK_FORMAT_R32G32B32_SFLOAT,         AV_PIX_FMT_RGBF32,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32G32B32_SFLOAT         } },
-    { VK_FORMAT_R32G32B32A32_SFLOAT,      AV_PIX_FMT_RGBAF32, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32G32B32A32_SFLOAT      } },
-    { VK_FORMAT_R32G32B32_UINT,           AV_PIX_FMT_RGB96,   VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32G32B32_UINT           } },
-    { VK_FORMAT_R32G32B32A32_UINT,        AV_PIX_FMT_RGBA128, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32G32B32A32_UINT        } },
-
-    /* Planar RGB */
-    { VK_FORMAT_R8_UNORM,   AV_PIX_FMT_GBRP,     VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM   } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRP10,   VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRP12,   VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRP14,   VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRP16,   VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
-    { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GBRPF32,  VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } },
-
-    /* Planar RGB + Alpha */
-    { VK_FORMAT_R8_UNORM,   AV_PIX_FMT_GBRAP,    VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM   } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRAP10,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRAP12,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRAP14,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRAP16,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
-    { VK_FORMAT_R32_UINT,   AV_PIX_FMT_GBRAP32,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R32_UINT,   VK_FORMAT_R32_UINT,   VK_FORMAT_R32_UINT,   VK_FORMAT_R32_UINT   } },
-    { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GBRAPF32, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } },
-
-    /* Bayer */
-    { VK_FORMAT_R16_UNORM, AV_PIX_FMT_BAYER_RGGB16, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM } },
-
-    /* Two-plane 420 YUV at 8, 10, 12 and 16 bits */
-    { VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,                  AV_PIX_FMT_NV12, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R8_UNORM,  VK_FORMAT_R8G8_UNORM   } },
-    { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, AV_PIX_FMT_P010, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
-    { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, AV_PIX_FMT_P012, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
-    { VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,               AV_PIX_FMT_P016, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
-
-    /* Two-plane 422 YUV at 8, 10 and 16 bits */
-    { VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,                  AV_PIX_FMT_NV16, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R8_UNORM,  VK_FORMAT_R8G8_UNORM   } },
-    { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, AV_PIX_FMT_P210, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
-    { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, AV_PIX_FMT_P212, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
-    { VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,               AV_PIX_FMT_P216, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
-
-    /* Two-plane 444 YUV at 8, 10 and 16 bits */
-    { VK_FORMAT_G8_B8R8_2PLANE_444_UNORM,                  AV_PIX_FMT_NV24, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R8_UNORM,  VK_FORMAT_R8G8_UNORM   } },
-    { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16, AV_PIX_FMT_P410, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
-    { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16, AV_PIX_FMT_P412, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
-    { VK_FORMAT_G16_B16R16_2PLANE_444_UNORM,               AV_PIX_FMT_P416, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
-
-    /* Three-plane 420, 422, 444 at 8, 10, 12 and 16 bits */
-    { VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,    AV_PIX_FMT_YUV420P,   ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM  } },
-    { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P10, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P12, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P16, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,    AV_PIX_FMT_YUV422P,   ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM  } },
-    { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P10, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P12, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P16, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,    AV_PIX_FMT_YUV444P,   ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM  } },
-    { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P10, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P12, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-    { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P16, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
-
-    /* Single plane 422 at 8, 10, 12 and 16 bits */
-    { VK_FORMAT_G8B8G8R8_422_UNORM,                     AV_PIX_FMT_YUYV422, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM     } },
-    { VK_FORMAT_B8G8R8G8_422_UNORM,                     AV_PIX_FMT_UYVY422, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM     } },
-    { VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, AV_PIX_FMT_Y210,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
-    { VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, AV_PIX_FMT_Y212,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
-    { VK_FORMAT_G16B16G16R16_422_UNORM,                 AV_PIX_FMT_Y216,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
-
-    /* Planar YUVA 420 at 8, 10 and 16 bits */
-    { VK_FORMAT_R8_UNORM,   AV_PIX_FMT_YUVA420P,    VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM   } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_YUVA420P10,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_YUVA420P16,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
-
-    /* Planar YUVA 422 at 8, 10, 12 and 16 bits */
-    { VK_FORMAT_R8_UNORM,   AV_PIX_FMT_YUVA422P,    VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM   } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_YUVA422P10,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_YUVA422P12,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_YUVA422P16,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
-
-    /* Planar YUVA 444 at 8, 10, 12 and 16 bits */
-    { VK_FORMAT_R8_UNORM,   AV_PIX_FMT_YUVA444P,    VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM   } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_YUVA444P10,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_YUVA444P12,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_YUVA444P16,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
-
-    /* Single plane 444 at 8, 10, 12 and 16 bits */
-    { VK_FORMAT_B8G8R8A8_UNORM,                         AV_PIX_FMT_UYVA,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B8G8R8A8_UNORM     } },
-    { VK_FORMAT_A2R10G10B10_UNORM_PACK32,               AV_PIX_FMT_XV30,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
-    { VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,     AV_PIX_FMT_XV36,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
-    { VK_FORMAT_R16G16B16A16_UNORM,                     AV_PIX_FMT_XV48,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
-};
-static const int nb_vk_formats_list = FF_ARRAY_ELEMS(vk_formats_list);
-
-const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p)
-{
-    for (int i = 0; i < nb_vk_formats_list; i++)
-        if (vk_formats_list[i].pixfmt == p)
-            return vk_formats_list[i].fallback;
-    return NULL;
-}
-
-static const struct FFVkFormatEntry *vk_find_format_entry(enum AVPixelFormat p)
-{
-    for (int i = 0; i < nb_vk_formats_list; i++)
-        if (vk_formats_list[i].pixfmt == p)
-            return &vk_formats_list[i];
-    return NULL;
-}
-
-static int vkfmt_from_pixfmt2(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p,
-                              VkImageTiling tiling,
-                              VkFormat fmts[AV_NUM_DATA_POINTERS], /* Output format list */
-                              int *nb_images,                      /* Output number of images */
-                              VkImageAspectFlags *aspect,          /* Output aspect */
-                              VkImageUsageFlags *supported_usage,  /* Output supported usage */
-                              int disable_multiplane, int need_storage)
-{
-    VulkanDevicePriv *priv = dev_ctx->hwctx;
-    AVVulkanDeviceContext *hwctx = &priv->p;
-    FFVulkanFunctions *vk = &priv->vkctx.vkfn;
-
-    const VkFormatFeatureFlagBits2 basic_flags = VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT |
-                                                 VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT  |
-                                                 VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT;
-
-    for (int i = 0; i < nb_vk_formats_list; i++) {
-        if (vk_formats_list[i].pixfmt == p) {
-            VkFormatProperties3 fprops = {
-                .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3,
-            };
-            VkFormatProperties2 prop = {
-                .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
-                .pNext = &fprops,
-            };
-            VkFormatFeatureFlagBits2 feats_primary, feats_secondary;
-            int basics_primary = 0, basics_secondary = 0;
-            int storage_primary = 0, storage_secondary = 0;
-
-            vk->GetPhysicalDeviceFormatProperties2(hwctx->phys_dev,
-                                                   vk_formats_list[i].vkf,
-                                                   &prop);
-
-            feats_primary = tiling == VK_IMAGE_TILING_LINEAR ?
-                             fprops.linearTilingFeatures : fprops.optimalTilingFeatures;
-            basics_primary = (feats_primary & basic_flags) == basic_flags;
-            storage_primary = !!(feats_primary & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT);
-
-            if (vk_formats_list[i].vkf != vk_formats_list[i].fallback[0]) {
-                vk->GetPhysicalDeviceFormatProperties2(hwctx->phys_dev,
-                                                       vk_formats_list[i].fallback[0],
-                                                       &prop);
-                feats_secondary = tiling == VK_IMAGE_TILING_LINEAR ?
-                                  fprops.linearTilingFeatures : fprops.optimalTilingFeatures;
-                basics_secondary = (feats_secondary & basic_flags) == basic_flags;
-                storage_secondary = !!(feats_secondary & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT);
-            } else {
-                basics_secondary = basics_primary;
-                storage_secondary = storage_primary;
-            }
-
-            if (basics_primary &&
-                !(disable_multiplane && vk_formats_list[i].vk_planes > 1) &&
-                (!need_storage || (need_storage && (storage_primary | storage_secondary)))) {
-                if (fmts) {
-                    if (vk_formats_list[i].nb_images > 1) {
-                        for (int j = 0; j < vk_formats_list[i].nb_images_fallback; j++)
-                            fmts[j] = vk_formats_list[i].fallback[j];
-                    } else {
-                        fmts[0] = vk_formats_list[i].vkf;
-                    }
-                }
-                if (nb_images)
-                    *nb_images = 1;
-                if (aspect)
-                    *aspect = vk_formats_list[i].aspect;
-                if (supported_usage)
-                    *supported_usage = ff_vk_map_feats_to_usage(feats_primary) |
-                                       ((need_storage && (storage_primary | storage_secondary)) ?
-                                        VK_IMAGE_USAGE_STORAGE_BIT : 0);
-                return 0;
-            } else if (basics_secondary &&
-                       (!need_storage || (need_storage && storage_secondary))) {
-                if (fmts) {
-                    for (int j = 0; j < vk_formats_list[i].nb_images_fallback; j++)
-                        fmts[j] = vk_formats_list[i].fallback[j];
-                }
-                if (nb_images)
-                    *nb_images = vk_formats_list[i].nb_images_fallback;
-                if (aspect)
-                    *aspect = vk_formats_list[i].aspect;
-                if (supported_usage)
-                    *supported_usage = ff_vk_map_feats_to_usage(feats_secondary);
-                return 0;
-            } else {
-                return AVERROR(ENOTSUP);
-            }
-        }
-    }
-
-    return AVERROR(EINVAL);
-}
-
-#if CONFIG_VULKAN_STATIC
-VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance,
-                                                               const char *pName);
-#endif
-
-static int load_libvulkan(AVHWDeviceContext *ctx)
-{
-    VulkanDevicePriv *p = ctx->hwctx;
-    AVVulkanDeviceContext *hwctx = &p->p;
-
-#if CONFIG_VULKAN_STATIC
-    hwctx->get_proc_addr = vkGetInstanceProcAddr;
-#else
-    static const char *lib_names[] = {
-#if defined(_WIN32)
-        "vulkan-1.dll",
-#elif defined(__APPLE__)
-        "libvulkan.dylib",
-        "libvulkan.1.dylib",
-        "libMoltenVK.dylib",
-#else
-        "libvulkan.so.1",
-        "libvulkan.so",
-#endif
-    };
-
-    for (int i = 0; i < FF_ARRAY_ELEMS(lib_names); i++) {
-        p->libvulkan = dlopen(lib_names[i], RTLD_NOW | RTLD_LOCAL);
-        if (p->libvulkan)
-            break;
-    }
-
-    if (!p->libvulkan) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to open the libvulkan library!\n");
-        return AVERROR_UNKNOWN;
-    }
-
-    hwctx->get_proc_addr = (PFN_vkGetInstanceProcAddr)dlsym(p->libvulkan, "vkGetInstanceProcAddr");
-#endif /* CONFIG_VULKAN_STATIC */
-
-    return 0;
-}
-
-typedef struct VulkanOptExtension {
-    const char *name;
-    FFVulkanExtensions flag;
-} VulkanOptExtension;
-
-static const VulkanOptExtension optional_instance_exts[] = {
-    { VK_EXT_LAYER_SETTINGS_EXTENSION_NAME,                   FF_VK_EXT_NO_FLAG                },
-#ifdef __APPLE__
-    { VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,          FF_VK_EXT_NO_FLAG                },
-#endif
-};
-
-static const VulkanOptExtension optional_device_exts[] = {
-    /* Misc or required by other extensions */
-    { VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME,               FF_VK_EXT_PORTABILITY_SUBSET     },
-    { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME,                  FF_VK_EXT_PUSH_DESCRIPTOR        },
-    { VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME,                FF_VK_EXT_DESCRIPTOR_BUFFER      },
-    { VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME,              FF_VK_EXT_DEVICE_DRM             },
-    { VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME,              FF_VK_EXT_ATOMIC_FLOAT           },
-    { VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME,               FF_VK_EXT_COOP_MATRIX            },
-    { VK_EXT_SHADER_OBJECT_EXTENSION_NAME,                    FF_VK_EXT_SHADER_OBJECT          },
-    { VK_KHR_SHADER_SUBGROUP_ROTATE_EXTENSION_NAME,           FF_VK_EXT_SUBGROUP_ROTATE        },
-#ifdef VK_KHR_shader_expect_assume
-    { VK_KHR_SHADER_EXPECT_ASSUME_EXTENSION_NAME,             FF_VK_EXT_EXPECT_ASSUME          },
-#endif
-    { 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    },
-#endif
-
-    /* Imports/exports */
-    { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,               FF_VK_EXT_EXTERNAL_FD_MEMORY     },
-    { VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME,          FF_VK_EXT_EXTERNAL_DMABUF_MEMORY },
-    { VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME,        FF_VK_EXT_DRM_MODIFIER_FLAGS     },
-    { VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,            FF_VK_EXT_EXTERNAL_FD_SEM        },
-    { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME,             FF_VK_EXT_EXTERNAL_HOST_MEMORY   },
-#ifdef _WIN32
-    { VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,            FF_VK_EXT_EXTERNAL_WIN32_MEMORY  },
-    { VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME,         FF_VK_EXT_EXTERNAL_WIN32_SEM     },
-#endif
-
-    /* Video encoding/decoding */
-    { VK_KHR_VIDEO_QUEUE_EXTENSION_NAME,                      FF_VK_EXT_VIDEO_QUEUE            },
-    { VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME,               FF_VK_EXT_VIDEO_ENCODE_QUEUE     },
-    { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME,               FF_VK_EXT_VIDEO_DECODE_QUEUE     },
-    { VK_KHR_VIDEO_ENCODE_H264_EXTENSION_NAME,                FF_VK_EXT_VIDEO_ENCODE_H264      },
-    { VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME,                FF_VK_EXT_VIDEO_DECODE_H264      },
-    { VK_KHR_VIDEO_ENCODE_H265_EXTENSION_NAME,                FF_VK_EXT_VIDEO_ENCODE_H265      },
-    { VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME,                FF_VK_EXT_VIDEO_DECODE_H265      },
-#ifdef VK_KHR_video_decode_vp9
-    { VK_KHR_VIDEO_DECODE_VP9_EXTENSION_NAME,                 FF_VK_EXT_VIDEO_DECODE_VP9       },
-#endif
-#ifdef VK_KHR_video_encode_av1
-    { VK_KHR_VIDEO_ENCODE_AV1_EXTENSION_NAME,                 FF_VK_EXT_VIDEO_ENCODE_AV1       },
-#endif
-    { VK_KHR_VIDEO_DECODE_AV1_EXTENSION_NAME,                 FF_VK_EXT_VIDEO_DECODE_AV1       },
-};
-
-static VkBool32 VKAPI_CALL vk_dbg_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
-                                           VkDebugUtilsMessageTypeFlagsEXT messageType,
-                                           const VkDebugUtilsMessengerCallbackDataEXT *data,
-                                           void *priv)
-{
-    int l;
-    AVHWDeviceContext *ctx = priv;
-
-    /* Ignore false positives */
-    switch (data->messageIdNumber) {
-    case 0x086974c1: /* BestPractices-vkCreateCommandPool-command-buffer-reset */
-    case 0xfd92477a: /* BestPractices-vkAllocateMemory-small-allocation */
-    case 0x618ab1e7: /* VUID-VkImageViewCreateInfo-usage-02275 */
-    case 0x30f4ac70: /* VUID-VkImageCreateInfo-pNext-06811 */
-        return VK_FALSE;
-    default:
-        break;
-    }
-
-    switch (severity) {
-    case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: l = AV_LOG_VERBOSE; break;
-    case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:    l = AV_LOG_INFO;    break;
-    case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: l = AV_LOG_WARNING; break;
-    case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:   l = AV_LOG_ERROR;   break;
-    default:                                              l = AV_LOG_DEBUG;   break;
-    }
-
-    av_log(ctx, l, "%s\n", data->pMessage);
-    for (int i = 0; i < data->cmdBufLabelCount; i++)
-        av_log(ctx, l, "\t%i: %s\n", i, data->pCmdBufLabels[i].pLabelName);
-
-    return VK_FALSE;
-}
-
-#define ADD_VAL_TO_LIST(list, count, val)                                      \
-    do {                                                                       \
-        list = av_realloc_array(list, sizeof(*list), ++count);                 \
-        if (!list) {                                                           \
-            err = AVERROR(ENOMEM);                                             \
-            goto fail;                                                         \
-        }                                                                      \
-        list[count - 1] = av_strdup(val);                                      \
-        if (!list[count - 1]) {                                                \
-            err = AVERROR(ENOMEM);                                             \
-            goto fail;                                                         \
-        }                                                                      \
-    } while(0)
-
-#define RELEASE_PROPS(props, count)                                            \
-    if (props) {                                                               \
-        for (int i = 0; i < count; i++)                                        \
-            av_free((void *)((props)[i]));                                     \
-        av_free((void *)props);                                                \
-    }
-
-enum FFVulkanDebugMode {
-    FF_VULKAN_DEBUG_NONE = 0,
-    /* Standard GPU-assisted validation */
-    FF_VULKAN_DEBUG_VALIDATE = 1,
-    /* Passes printfs in shaders to the debug callback */
-    FF_VULKAN_DEBUG_PRINTF = 2,
-    /* Enables extra printouts */
-    FF_VULKAN_DEBUG_PRACTICES = 3,
-    /* Disables validation but keeps shader debug info and optimizations */
-    FF_VULKAN_DEBUG_PROFILE = 4,
-
-    FF_VULKAN_DEBUG_NB,
-};
-
-static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts,
-                            const char * const **dst, uint32_t *num,
-                            enum FFVulkanDebugMode debug_mode)
-{
-    const char *tstr;
-    const char **extension_names = NULL;
-    VulkanDevicePriv *p = ctx->hwctx;
-    AVVulkanDeviceContext *hwctx = &p->p;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-    int err = 0, found, extensions_found = 0;
-
-    const char *mod;
-    int optional_exts_num;
-    uint32_t sup_ext_count;
-    char *user_exts_str = NULL;
-    AVDictionaryEntry *user_exts;
-    VkExtensionProperties *sup_ext;
-    const VulkanOptExtension *optional_exts;
-
-    if (!dev) {
-        mod = "instance";
-        optional_exts = optional_instance_exts;
-        optional_exts_num = FF_ARRAY_ELEMS(optional_instance_exts);
-        user_exts = av_dict_get(opts, "instance_extensions", NULL, 0);
-        if (user_exts) {
-            user_exts_str = av_strdup(user_exts->value);
-            if (!user_exts_str) {
-                err = AVERROR(ENOMEM);
-                goto fail;
-            }
-        }
-        vk->EnumerateInstanceExtensionProperties(NULL, &sup_ext_count, NULL);
-        sup_ext = av_malloc_array(sup_ext_count, sizeof(VkExtensionProperties));
-        if (!sup_ext)
-            return AVERROR(ENOMEM);
-        vk->EnumerateInstanceExtensionProperties(NULL, &sup_ext_count, sup_ext);
-    } else {
-        mod = "device";
-        optional_exts = optional_device_exts;
-        optional_exts_num = FF_ARRAY_ELEMS(optional_device_exts);
-        user_exts = av_dict_get(opts, "device_extensions", NULL, 0);
-        if (user_exts) {
-            user_exts_str = av_strdup(user_exts->value);
-            if (!user_exts_str) {
-                err = AVERROR(ENOMEM);
-                goto fail;
-            }
-        }
-        vk->EnumerateDeviceExtensionProperties(hwctx->phys_dev, NULL,
-                                               &sup_ext_count, NULL);
-        sup_ext = av_malloc_array(sup_ext_count, sizeof(VkExtensionProperties));
-        if (!sup_ext)
-            return AVERROR(ENOMEM);
-        vk->EnumerateDeviceExtensionProperties(hwctx->phys_dev, NULL,
-                                               &sup_ext_count, sup_ext);
-    }
-
-    for (int i = 0; i < optional_exts_num; i++) {
-        tstr = optional_exts[i].name;
-        found = 0;
-
-        /* Intel has had a bad descriptor buffer implementation for a while */
-        if (p->dprops.driverID == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA &&
-            !strcmp(tstr, VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME))
-            continue;
-
-        if (dev &&
-            ((debug_mode == FF_VULKAN_DEBUG_VALIDATE) ||
-             (debug_mode == FF_VULKAN_DEBUG_PRINTF) ||
-             (debug_mode == FF_VULKAN_DEBUG_PRACTICES)) &&
-            !strcmp(tstr, VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME)) {
-            continue;
-        }
-
-        for (int j = 0; j < sup_ext_count; j++) {
-            if (!strcmp(tstr, sup_ext[j].extensionName)) {
-                found = 1;
-                break;
-            }
-        }
-        if (!found)
-            continue;
-
-        av_log(ctx, AV_LOG_VERBOSE, "Using %s extension %s\n", mod, tstr);
-        p->vkctx.extensions |= optional_exts[i].flag;
-        ADD_VAL_TO_LIST(extension_names, extensions_found, tstr);
-    }
-
-    if (!dev &&
-        ((debug_mode == FF_VULKAN_DEBUG_VALIDATE) ||
-         (debug_mode == FF_VULKAN_DEBUG_PRINTF) ||
-         (debug_mode == FF_VULKAN_DEBUG_PRACTICES))) {
-        tstr = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
-        found = 0;
-        for (int j = 0; j < sup_ext_count; j++) {
-            if (!strcmp(tstr, sup_ext[j].extensionName)) {
-                found = 1;
-                break;
-            }
-        }
-        if (found) {
-            av_log(ctx, AV_LOG_VERBOSE, "Using %s extension %s\n", mod, tstr);
-            ADD_VAL_TO_LIST(extension_names, extensions_found, tstr);
-        } else {
-            av_log(ctx, AV_LOG_ERROR, "Debug extension \"%s\" not found!\n",
-                   tstr);
-            err = AVERROR(EINVAL);
-            goto fail;
-        }
-    }
-
-#ifdef VK_KHR_shader_relaxed_extended_instruction
-    if (((debug_mode == FF_VULKAN_DEBUG_PRINTF) ||
-         (debug_mode == FF_VULKAN_DEBUG_PROFILE)) && dev) {
-        tstr = VK_KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION_EXTENSION_NAME;
-        found = 0;
-        for (int j = 0; j < sup_ext_count; j++) {
-            if (!strcmp(tstr, sup_ext[j].extensionName)) {
-                found = 1;
-                break;
-            }
-        }
-        if (found) {
-            av_log(ctx, AV_LOG_VERBOSE, "Using %s extension %s\n", mod, tstr);
-            ADD_VAL_TO_LIST(extension_names, extensions_found, tstr);
-        } else {
-            av_log(ctx, AV_LOG_ERROR, "Debug_printf/profile enabled, but extension \"%s\" not found!\n",
-                   tstr);
-            err = AVERROR(EINVAL);
-            goto fail;
-        }
-    }
-#endif
-
-    if (user_exts_str) {
-        char *save, *token = av_strtok(user_exts_str, "+", &save);
-        while (token) {
-            found = 0;
-            for (int j = 0; j < sup_ext_count; j++) {
-                if (!strcmp(token, sup_ext[j].extensionName)) {
-                    found = 1;
-                    break;
-                }
-            }
-            if (found) {
-                av_log(ctx, AV_LOG_VERBOSE, "Using %s extension \"%s\"\n", mod, token);
-                ADD_VAL_TO_LIST(extension_names, extensions_found, token);
-            } else {
-                av_log(ctx, AV_LOG_WARNING, "%s extension \"%s\" not found, excluding.\n",
-                       mod, token);
-            }
-            token = av_strtok(NULL, "+", &save);
-        }
-    }
-
-    *dst = extension_names;
-    *num = extensions_found;
-
-    av_free(user_exts_str);
-    av_free(sup_ext);
-    return 0;
-
-fail:
-    RELEASE_PROPS(extension_names, extensions_found);
-    av_free(user_exts_str);
-    av_free(sup_ext);
-    return err;
-}
-
-static int check_layers(AVHWDeviceContext *ctx, AVDictionary *opts,
-                        const char * const **dst, uint32_t *num,
-                        enum FFVulkanDebugMode *debug_mode)
-{
-    int err = 0;
-    VulkanDevicePriv *priv = ctx->hwctx;
-    FFVulkanFunctions *vk = &priv->vkctx.vkfn;
-
-    static const char layer_standard_validation[] = { "VK_LAYER_KHRONOS_validation" };
-    int layer_standard_validation_found = 0;
-
-    uint32_t sup_layer_count;
-    VkLayerProperties *sup_layers;
-
-    AVDictionaryEntry *user_layers = av_dict_get(opts, "layers", NULL, 0);
-    char *user_layers_str = NULL;
-    char *save, *token;
-
-    const char **enabled_layers = NULL;
-    uint32_t enabled_layers_count = 0;
-
-    AVDictionaryEntry *debug_opt = av_dict_get(opts, "debug", NULL, 0);
-    enum FFVulkanDebugMode mode;
-
-    *debug_mode = mode = FF_VULKAN_DEBUG_NONE;
-
-    /* Get a list of all layers */
-    vk->EnumerateInstanceLayerProperties(&sup_layer_count, NULL);
-    sup_layers = av_malloc_array(sup_layer_count, sizeof(VkLayerProperties));
-    if (!sup_layers)
-        return AVERROR(ENOMEM);
-    vk->EnumerateInstanceLayerProperties(&sup_layer_count, sup_layers);
-
-    av_log(ctx, AV_LOG_VERBOSE, "Supported layers:\n");
-    for (int i = 0; i < sup_layer_count; i++)
-        av_log(ctx, AV_LOG_VERBOSE, "\t%s\n", sup_layers[i].layerName);
-
-    /* If no user layers or debug layers are given, return */
-    if (!debug_opt && !user_layers)
-        goto end;
-
-    /* Check for any properly supported validation layer */
-    if (debug_opt) {
-        if (!strcmp(debug_opt->value, "profile")) {
-            mode = FF_VULKAN_DEBUG_PROFILE;
-        } else if (!strcmp(debug_opt->value, "printf")) {
-            mode = FF_VULKAN_DEBUG_PRINTF;
-        } else if (!strcmp(debug_opt->value, "validate")) {
-            mode = FF_VULKAN_DEBUG_VALIDATE;
-        } else if (!strcmp(debug_opt->value, "practices")) {
-            mode = FF_VULKAN_DEBUG_PRACTICES;
-        } else {
-            char *end_ptr = NULL;
-            int idx = strtol(debug_opt->value, &end_ptr, 10);
-            if (end_ptr == debug_opt->value || end_ptr[0] != '\0' ||
-                idx < 0 || idx >= FF_VULKAN_DEBUG_NB) {
-                av_log(ctx, AV_LOG_ERROR, "Invalid debugging mode \"%s\"\n",
-                       debug_opt->value);
-                err = AVERROR(EINVAL);
-                goto end;
-            }
-            mode = idx;
-        }
-    }
-
-    /* If mode is VALIDATE or PRINTF, try to find the standard validation layer extension */
-    if ((mode == FF_VULKAN_DEBUG_VALIDATE) ||
-        (mode == FF_VULKAN_DEBUG_PRINTF) ||
-        (mode == FF_VULKAN_DEBUG_PRACTICES)) {
-        for (int i = 0; i < sup_layer_count; i++) {
-            if (!strcmp(layer_standard_validation, sup_layers[i].layerName)) {
-                av_log(ctx, AV_LOG_VERBOSE, "Standard validation layer %s is enabled\n",
-                       layer_standard_validation);
-                ADD_VAL_TO_LIST(enabled_layers, enabled_layers_count, layer_standard_validation);
-                *debug_mode = mode;
-                layer_standard_validation_found = 1;
-                break;
-            }
-        }
-        if (!layer_standard_validation_found) {
-            av_log(ctx, AV_LOG_ERROR,
-                   "Validation Layer \"%s\" not supported\n", layer_standard_validation);
-            err = AVERROR(ENOTSUP);
-            goto end;
-        }
-    } else if (mode == FF_VULKAN_DEBUG_PROFILE) {
-        *debug_mode = mode;
-    }
-
-    /* Process any custom layers enabled */
-    if (user_layers) {
-        int found;
-
-        user_layers_str = av_strdup(user_layers->value);
-        if (!user_layers_str) {
-            err = AVERROR(ENOMEM);
-            goto fail;
-        }
-
-        token = av_strtok(user_layers_str, "+", &save);
-        while (token) {
-            found = 0;
-
-            /* If debug=1/2 was specified as an option, skip this layer */
-            if (!strcmp(layer_standard_validation, token) && layer_standard_validation_found) {
-                token = av_strtok(NULL, "+", &save);
-                break;
-            }
-
-            /* Try to find the layer in the list of supported layers */
-            for (int j = 0; j < sup_layer_count; j++) {
-                if (!strcmp(token, sup_layers[j].layerName)) {
-                    found = 1;
-                    break;
-                }
-            }
-
-            if (found) {
-                av_log(ctx, AV_LOG_VERBOSE, "Using layer: %s\n", token);
-                ADD_VAL_TO_LIST(enabled_layers, enabled_layers_count, token);
-
-                /* If debug was not set as an option, force it */
-                if (!strcmp(layer_standard_validation, token))
-                    *debug_mode = FF_VULKAN_DEBUG_VALIDATE;
-            } else {
-                av_log(ctx, AV_LOG_ERROR,
-                       "Layer \"%s\" not supported\n", token);
-                err = AVERROR(EINVAL);
-                goto end;
-            }
-
-            token = av_strtok(NULL, "+", &save);
-        }
-    }
-
-fail:
-end:
-    av_free(sup_layers);
-    av_free(user_layers_str);
-
-    if (err < 0) {
-        RELEASE_PROPS(enabled_layers, enabled_layers_count);
-    } else {
-        *dst = enabled_layers;
-        *num = enabled_layers_count;
-    }
-
-    return err;
-}
-
-/* Creates a VkInstance */
-static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts,
-                           enum FFVulkanDebugMode *debug_mode)
-{
-    int err = 0;
-    VkResult ret;
-    VulkanDevicePriv *p = ctx->hwctx;
-    AVVulkanDeviceContext *hwctx = &p->p;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-    VkApplicationInfo application_info = {
-        .sType              = VK_STRUCTURE_TYPE_APPLICATION_INFO,
-        .pApplicationName   = "ffmpeg",
-        .applicationVersion = VK_MAKE_VERSION(LIBAVUTIL_VERSION_MAJOR,
-                                              LIBAVUTIL_VERSION_MINOR,
-                                              LIBAVUTIL_VERSION_MICRO),
-        .pEngineName        = "libavutil",
-        .apiVersion         = VK_API_VERSION_1_3,
-        .engineVersion      = VK_MAKE_VERSION(LIBAVUTIL_VERSION_MAJOR,
-                                              LIBAVUTIL_VERSION_MINOR,
-                                              LIBAVUTIL_VERSION_MICRO),
-    };
-    VkValidationFeaturesEXT validation_features = {
-        .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
-    };
-    VkInstanceCreateInfo inst_props = {
-        .sType            = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
-        .pApplicationInfo = &application_info,
-    };
-
-    if (!hwctx->get_proc_addr) {
-        err = load_libvulkan(ctx);
-        if (err < 0)
-            return err;
-    }
-
-    err = ff_vk_load_functions(ctx, vk, p->vkctx.extensions, 0, 0);
-    if (err < 0) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to load instance enumeration functions!\n");
-        return err;
-    }
-
-    err = check_layers(ctx, opts, &inst_props.ppEnabledLayerNames,
-                       &inst_props.enabledLayerCount, debug_mode);
-    if (err)
-        goto fail;
-
-    /* Check for present/missing extensions */
-    err = check_extensions(ctx, 0, opts, &inst_props.ppEnabledExtensionNames,
-                           &inst_props.enabledExtensionCount, *debug_mode);
-    hwctx->enabled_inst_extensions = inst_props.ppEnabledExtensionNames;
-    hwctx->nb_enabled_inst_extensions = inst_props.enabledExtensionCount;
-    if (err < 0)
-        goto fail;
-
-    /* Enable debug features if needed */
-    if (*debug_mode == FF_VULKAN_DEBUG_VALIDATE) {
-        static const VkValidationFeatureEnableEXT feat_list_validate[] = {
-            VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
-            VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT,
-            VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT,
-        };
-        validation_features.pEnabledValidationFeatures = feat_list_validate;
-        validation_features.enabledValidationFeatureCount = FF_ARRAY_ELEMS(feat_list_validate);
-        inst_props.pNext = &validation_features;
-    } else if (*debug_mode == FF_VULKAN_DEBUG_PRINTF) {
-        static const VkValidationFeatureEnableEXT feat_list_debug[] = {
-            VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
-            VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT,
-            VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT,
-        };
-        validation_features.pEnabledValidationFeatures = feat_list_debug;
-        validation_features.enabledValidationFeatureCount = FF_ARRAY_ELEMS(feat_list_debug);
-        inst_props.pNext = &validation_features;
-    } else if (*debug_mode == FF_VULKAN_DEBUG_PRACTICES) {
-        static const VkValidationFeatureEnableEXT feat_list_practices[] = {
-            VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
-            VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
-        };
-        validation_features.pEnabledValidationFeatures = feat_list_practices;
-        validation_features.enabledValidationFeatureCount = FF_ARRAY_ELEMS(feat_list_practices);
-        inst_props.pNext = &validation_features;
-    }
-
-#ifdef __APPLE__
-    for (int i = 0; i < inst_props.enabledExtensionCount; i++) {
-        if (!strcmp(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
-                    inst_props.ppEnabledExtensionNames[i])) {
-            inst_props.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
-            break;
-        }
-    }
-#endif
-
-    /* Try to create the instance */
-    ret = vk->CreateInstance(&inst_props, hwctx->alloc, &hwctx->inst);
-
-    /* Check for errors */
-    if (ret != VK_SUCCESS) {
-        av_log(ctx, AV_LOG_ERROR, "Instance creation failure: %s\n",
-               ff_vk_ret2str(ret));
-        err = AVERROR_EXTERNAL;
-        goto fail;
-    }
-
-    err = ff_vk_load_functions(ctx, vk, p->vkctx.extensions, 1, 0);
-    if (err < 0) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to load instance functions!\n");
-        goto fail;
-    }
-
-    /* Setup debugging callback if needed */
-    if ((*debug_mode == FF_VULKAN_DEBUG_VALIDATE) ||
-        (*debug_mode == FF_VULKAN_DEBUG_PRINTF) ||
-        (*debug_mode == FF_VULKAN_DEBUG_PRACTICES)) {
-        VkDebugUtilsMessengerCreateInfoEXT dbg = {
-            .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
-            .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
-                               VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT    |
-                               VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
-                               VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
-            .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT    |
-                           VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
-                           VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
-            .pfnUserCallback = vk_dbg_callback,
-            .pUserData = ctx,
-        };
-
-        vk->CreateDebugUtilsMessengerEXT(hwctx->inst, &dbg,
-                                         hwctx->alloc, &p->debug_ctx);
-    }
-
-    err = 0;
-
-fail:
-    RELEASE_PROPS(inst_props.ppEnabledLayerNames, inst_props.enabledLayerCount);
-    return err;
-}
-
-typedef struct VulkanDeviceSelection {
-    uint8_t uuid[VK_UUID_SIZE]; /* Will use this first unless !has_uuid */
-    int has_uuid;
-    uint32_t drm_major; /* Will use this second unless !has_drm */
-    uint32_t drm_minor; /* Will use this second unless !has_drm */
-    uint32_t has_drm; /* has drm node info */
-    const char *name; /* Will use this third unless NULL */
-    uint32_t pci_device; /* Will use this fourth unless 0x0 */
-    uint32_t vendor_id; /* Last resort to find something deterministic */
-    int index; /* Finally fall back to index */
-} VulkanDeviceSelection;
-
-static const char *vk_dev_type(enum VkPhysicalDeviceType type)
-{
-    switch (type) {
-    case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: return "integrated";
-    case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:   return "discrete";
-    case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:    return "virtual";
-    case VK_PHYSICAL_DEVICE_TYPE_CPU:            return "software";
-    default:                                     return "unknown";
-    }
-}
-
-/* Finds a device */
-static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select)
-{
-    int err = 0, choice = -1;
-    uint32_t num;
-    VkResult ret;
-    VulkanDevicePriv *p = ctx->hwctx;
-    AVVulkanDeviceContext *hwctx = &p->p;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-    VkPhysicalDevice *devices = NULL;
-    VkPhysicalDeviceIDProperties *idp = NULL;
-    VkPhysicalDeviceProperties2 *prop = NULL;
-    VkPhysicalDeviceDriverProperties *driver_prop = NULL;
-    VkPhysicalDeviceDrmPropertiesEXT *drm_prop = NULL;
-
-    ret = vk->EnumeratePhysicalDevices(hwctx->inst, &num, NULL);
-    if (ret != VK_SUCCESS || !num) {
-        av_log(ctx, AV_LOG_ERROR, "No devices found: %s!\n", ff_vk_ret2str(ret));
-        return AVERROR(ENODEV);
-    }
-
-    devices = av_malloc_array(num, sizeof(VkPhysicalDevice));
-    if (!devices)
-        return AVERROR(ENOMEM);
-
-    ret = vk->EnumeratePhysicalDevices(hwctx->inst, &num, devices);
-    if (ret != VK_SUCCESS) {
-        av_log(ctx, AV_LOG_ERROR, "Failed enumerating devices: %s\n",
-               ff_vk_ret2str(ret));
-        err = AVERROR(ENODEV);
-        goto end;
-    }
-
-    prop = av_calloc(num, sizeof(*prop));
-    if (!prop) {
-        err = AVERROR(ENOMEM);
-        goto end;
-    }
-
-    idp = av_calloc(num, sizeof(*idp));
-    if (!idp) {
-        err = AVERROR(ENOMEM);
-        goto end;
-    }
-
-    driver_prop = av_calloc(num, sizeof(*driver_prop));
-    if (!driver_prop) {
-        err = AVERROR(ENOMEM);
-        goto end;
-    }
-
-    if (p->vkctx.extensions & FF_VK_EXT_DEVICE_DRM) {
-        drm_prop = av_calloc(num, sizeof(*drm_prop));
-        if (!drm_prop) {
-            err = AVERROR(ENOMEM);
-            goto end;
-        }
-    }
-
-    av_log(ctx, AV_LOG_VERBOSE, "GPU listing:\n");
-    for (int i = 0; i < num; i++) {
-        if (p->vkctx.extensions & FF_VK_EXT_DEVICE_DRM) {
-            drm_prop[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT;
-            driver_prop[i].pNext = &drm_prop[i];
-        }
-        driver_prop[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
-        idp[i].pNext = &driver_prop[i];
-        idp[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
-        prop[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
-        prop[i].pNext = &idp[i];
-
-        vk->GetPhysicalDeviceProperties2(devices[i], &prop[i]);
-        av_log(ctx, AV_LOG_VERBOSE, "    %d: %s (%s) (0x%x)\n", i,
-               prop[i].properties.deviceName,
-               vk_dev_type(prop[i].properties.deviceType),
-               prop[i].properties.deviceID);
-    }
-
-    if (select->has_uuid) {
-        for (int i = 0; i < num; i++) {
-            if (!strncmp(idp[i].deviceUUID, select->uuid, VK_UUID_SIZE)) {
-                choice = i;
-                goto end;
-             }
-        }
-        av_log(ctx, AV_LOG_ERROR, "Unable to find device by given UUID!\n");
-        err = AVERROR(ENODEV);
-        goto end;
-    } else if ((p->vkctx.extensions & FF_VK_EXT_DEVICE_DRM) && select->has_drm) {
-        for (int i = 0; i < num; i++) {
-            if ((select->drm_major == drm_prop[i].primaryMajor &&
-                 select->drm_minor == drm_prop[i].primaryMinor) ||
-                (select->drm_major == drm_prop[i].renderMajor &&
-                 select->drm_minor == drm_prop[i].renderMinor)) {
-                choice = i;
-                goto end;
-             }
-        }
-        av_log(ctx, AV_LOG_ERROR, "Unable to find device by given DRM node numbers %i:%i!\n",
-               select->drm_major, select->drm_minor);
-        err = AVERROR(ENODEV);
-        goto end;
-    } else if (select->name) {
-        av_log(ctx, AV_LOG_VERBOSE, "Requested device: %s\n", select->name);
-        for (int i = 0; i < num; i++) {
-            if (strstr(prop[i].properties.deviceName, select->name)) {
-                choice = i;
-                goto end;
-             }
-        }
-        av_log(ctx, AV_LOG_ERROR, "Unable to find device \"%s\"!\n",
-               select->name);
-        err = AVERROR(ENODEV);
-        goto end;
-    } else if (select->pci_device) {
-        av_log(ctx, AV_LOG_VERBOSE, "Requested device: 0x%x\n", select->pci_device);
-        for (int i = 0; i < num; i++) {
-            if (select->pci_device == prop[i].properties.deviceID) {
-                choice = i;
-                goto end;
-            }
-        }
-        av_log(ctx, AV_LOG_ERROR, "Unable to find device with PCI ID 0x%x!\n",
-               select->pci_device);
-        err = AVERROR(EINVAL);
-        goto end;
-    } else if (select->vendor_id) {
-        av_log(ctx, AV_LOG_VERBOSE, "Requested vendor: 0x%x\n", select->vendor_id);
-        for (int i = 0; i < num; i++) {
-            if (select->vendor_id == prop[i].properties.vendorID) {
-                choice = i;
-                goto end;
-            }
-        }
-        av_log(ctx, AV_LOG_ERROR, "Unable to find device with Vendor ID 0x%x!\n",
-               select->vendor_id);
-        err = AVERROR(ENODEV);
-        goto end;
-    } else {
-        if (select->index < num) {
-            choice = select->index;
-            goto end;
-        }
-        av_log(ctx, AV_LOG_ERROR, "Unable to find device with index %i!\n",
-               select->index);
-        err = AVERROR(ENODEV);
-        goto end;
-    }
-
-end:
-    if (choice > -1) {
-        av_log(ctx, AV_LOG_VERBOSE, "Device %d selected: %s (%s) (0x%x)\n",
-               choice, prop[choice].properties.deviceName,
-               vk_dev_type(prop[choice].properties.deviceType),
-               prop[choice].properties.deviceID);
-        hwctx->phys_dev = devices[choice];
-        p->props = prop[choice];
-        p->props.pNext = NULL;
-        p->dprops = driver_prop[choice];
-        p->dprops.pNext = NULL;
-    }
-
-    av_free(devices);
-    av_free(prop);
-    av_free(idp);
-    av_free(drm_prop);
-    av_free(driver_prop);
-
-    return err;
-}
-
-/* Picks the least used qf with the fewest unneeded flags, or -1 if none found */
-static inline int pick_queue_family(VkQueueFamilyProperties2 *qf, uint32_t num_qf,
-                                    VkQueueFlagBits flags)
-{
-    int index = -1;
-    uint32_t min_score = UINT32_MAX;
-
-    for (int i = 0; i < num_qf; i++) {
-        VkQueueFlagBits qflags = qf[i].queueFamilyProperties.queueFlags;
-
-        /* Per the spec, reporting transfer caps is optional for these 2 types */
-        if ((flags & VK_QUEUE_TRANSFER_BIT) &&
-            (qflags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT)))
-            qflags |= VK_QUEUE_TRANSFER_BIT;
-
-        if (qflags & flags) {
-            uint32_t score = av_popcount(qflags) + qf[i].queueFamilyProperties.timestampValidBits;
-            if (score < min_score) {
-                index = i;
-                min_score = score;
-            }
-        }
-    }
-
-    if (index > -1)
-        qf[index].queueFamilyProperties.timestampValidBits++;
-
-    return index;
-}
-
-static inline int pick_video_queue_family(VkQueueFamilyProperties2 *qf,
-                                          VkQueueFamilyVideoPropertiesKHR *qf_vid, uint32_t num_qf,
-                                          VkVideoCodecOperationFlagBitsKHR flags)
-{
-    int index = -1;
-    uint32_t min_score = UINT32_MAX;
-
-    for (int i = 0; i < num_qf; i++) {
-        const VkQueueFlagBits qflags = qf[i].queueFamilyProperties.queueFlags;
-        const VkQueueFlagBits vflags = qf_vid[i].videoCodecOperations;
-
-        if (!(qflags & (VK_QUEUE_VIDEO_ENCODE_BIT_KHR | VK_QUEUE_VIDEO_DECODE_BIT_KHR)))
-            continue;
-
-        if (vflags & flags) {
-            uint32_t score = av_popcount(vflags) + qf[i].queueFamilyProperties.timestampValidBits;
-            if (score < min_score) {
-                index = i;
-                min_score = score;
-            }
-        }
-    }
-
-    if (index > -1)
-        qf[index].queueFamilyProperties.timestampValidBits++;
-
-    return index;
-}
-
-static int setup_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd)
-{
-    uint32_t num;
-    VulkanDevicePriv *p = ctx->hwctx;
-    AVVulkanDeviceContext *hwctx = &p->p;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-
-    VkQueueFamilyProperties2 *qf = NULL;
-    VkQueueFamilyVideoPropertiesKHR *qf_vid = NULL;
-
-    /* First get the number of queue families */
-    vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &num, NULL);
-    if (!num) {
-        av_log(ctx, AV_LOG_ERROR, "Failed to get queues!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    /* Then allocate memory */
-    qf = av_malloc_array(num, sizeof(VkQueueFamilyProperties2));
-    if (!qf)
-        return AVERROR(ENOMEM);
-
-    qf_vid = av_malloc_array(num, sizeof(VkQueueFamilyVideoPropertiesKHR));
-    if (!qf_vid)
-        return AVERROR(ENOMEM);
-
-    for (uint32_t i = 0; i < num; i++) {
-        qf_vid[i] = (VkQueueFamilyVideoPropertiesKHR) {
-            .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR,
-        };
-        qf[i] = (VkQueueFamilyProperties2) {
-            .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
-            .pNext = p->vkctx.extensions & FF_VK_EXT_VIDEO_QUEUE ? &qf_vid[i] : NULL,
-        };
-    }
-
-    /* Finally retrieve the queue families */
-    vk->GetPhysicalDeviceQueueFamilyProperties2(hwctx->phys_dev, &num, qf);
-
-    av_log(ctx, AV_LOG_VERBOSE, "Queue families:\n");
-    for (int i = 0; i < num; i++) {
-        av_log(ctx, AV_LOG_VERBOSE, "    %i:%s%s%s%s%s%s%s%s (queues: %i)\n", i,
-               ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_GRAPHICS_BIT) ? " graphics" : "",
-               ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_COMPUTE_BIT) ? " compute" : "",
-               ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_TRANSFER_BIT) ? " transfer" : "",
-               ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_VIDEO_ENCODE_BIT_KHR) ? " encode" : "",
-               ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_VIDEO_DECODE_BIT_KHR) ? " decode" : "",
-               ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_SPARSE_BINDING_BIT) ? " sparse" : "",
-               ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_OPTICAL_FLOW_BIT_NV) ? " optical_flow" : "",
-               ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_PROTECTED_BIT) ? " protected" : "",
-               qf[i].queueFamilyProperties.queueCount);
-
-        /* We use this field to keep a score of how many times we've used that
-         * queue family in order to make better choices. */
-        qf[i].queueFamilyProperties.timestampValidBits = 0;
-    }
-
-    hwctx->nb_qf = 0;
-
-    /* Pick each queue family to use. */
-#define PICK_QF(type, vid_op)                                            \
-    do {                                                                 \
-        uint32_t i;                                                      \
-        uint32_t idx;                                                    \
-                                                                         \
-        if (vid_op)                                                      \
-            idx = pick_video_queue_family(qf, qf_vid, num, vid_op);      \
-        else                                                             \
-            idx = pick_queue_family(qf, num, type);                      \
-                                                                         \
-        if (idx == -1)                                                   \
-            continue;                                                    \
-                                                                         \
-        for (i = 0; i < hwctx->nb_qf; i++) {                             \
-            if (hwctx->qf[i].idx == idx) {                               \
-                hwctx->qf[i].flags |= type;                              \
-                hwctx->qf[i].video_caps |= vid_op;                       \
-                break;                                                   \
-            }                                                            \
-        }                                                                \
-        if (i == hwctx->nb_qf) {                                         \
-            hwctx->qf[i].idx = idx;                                      \
-            hwctx->qf[i].num = qf[idx].queueFamilyProperties.queueCount; \
-            if (p->limit_queues ||                                       \
-                p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY) { \
-                int max = p->limit_queues;                               \
-                if (type == VK_QUEUE_GRAPHICS_BIT)                       \
-                    hwctx->qf[i].num = FFMIN(hwctx->qf[i].num,           \
-                                             max ? max : 1);             \
-                else if (max)                                            \
-                    hwctx->qf[i].num = FFMIN(hwctx->qf[i].num, max);     \
-            }                                                            \
-            hwctx->qf[i].flags = type;                                   \
-            hwctx->qf[i].video_caps = vid_op;                            \
-            hwctx->nb_qf++;                                              \
-        }                                                                \
-    } while (0)
-
-    PICK_QF(VK_QUEUE_GRAPHICS_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR);
-    PICK_QF(VK_QUEUE_COMPUTE_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR);
-    PICK_QF(VK_QUEUE_TRANSFER_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR);
-
-    PICK_QF(VK_QUEUE_VIDEO_ENCODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR);
-    PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR);
-
-    PICK_QF(VK_QUEUE_VIDEO_ENCODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR);
-    PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR);
-
-#ifdef VK_KHR_video_decode_vp9
-    PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_VP9_BIT_KHR);
-#endif
-
-#ifdef VK_KHR_video_encode_av1
-    PICK_QF(VK_QUEUE_VIDEO_ENCODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR);
-#endif
-    PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR);
-
-    av_free(qf);
-    av_free(qf_vid);
-
-#undef PICK_QF
-
-    cd->pQueueCreateInfos = av_malloc_array(hwctx->nb_qf,
-                                            sizeof(VkDeviceQueueCreateInfo));
-    if (!cd->pQueueCreateInfos)
-        return AVERROR(ENOMEM);
-
-    for (uint32_t i = 0; i < hwctx->nb_qf; i++) {
-        int dup = 0;
-        float *weights = NULL;
-        VkDeviceQueueCreateInfo *pc;
-        for (uint32_t j = 0; j < cd->queueCreateInfoCount; j++) {
-            if (hwctx->qf[i].idx == cd->pQueueCreateInfos[j].queueFamilyIndex) {
-                dup = 1;
-                break;
-            }
-        }
-        if (dup)
-            continue;
-
-        weights = av_malloc_array(hwctx->qf[i].num, sizeof(float));
-        if (!weights) {
-            for (uint32_t j = 0; j < cd->queueCreateInfoCount; j++)
-                av_free((void *)cd->pQueueCreateInfos[i].pQueuePriorities);
-            av_free((void *)cd->pQueueCreateInfos);
-            return AVERROR(ENOMEM);
-        }
-
-        for (uint32_t j = 0; j < hwctx->qf[i].num; j++)
-            weights[j] = 1.0;
-
-        pc = (VkDeviceQueueCreateInfo *)cd->pQueueCreateInfos;
-        pc[cd->queueCreateInfoCount++] = (VkDeviceQueueCreateInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
-            .queueFamilyIndex = hwctx->qf[i].idx,
-            .queueCount = hwctx->qf[i].num,
-            .pQueuePriorities = weights,
-        };
-    }
-
-#if FF_API_VULKAN_FIXED_QUEUES
-FF_DISABLE_DEPRECATION_WARNINGS
-    /* Setup deprecated fields */
-    hwctx->queue_family_index        = -1;
-    hwctx->queue_family_comp_index   = -1;
-    hwctx->queue_family_tx_index     = -1;
-    hwctx->queue_family_encode_index = -1;
-    hwctx->queue_family_decode_index = -1;
-
-#define SET_OLD_QF(field, nb_field, type)             \
-    do {                                              \
-        if (field < 0 && hwctx->qf[i].flags & type) { \
-            field = hwctx->qf[i].idx;                 \
-            nb_field = hwctx->qf[i].num;              \
-        }                                             \
-    } while (0)
-
-    for (uint32_t i = 0; i < hwctx->nb_qf; i++) {
-        SET_OLD_QF(hwctx->queue_family_index, hwctx->nb_graphics_queues, VK_QUEUE_GRAPHICS_BIT);
-        SET_OLD_QF(hwctx->queue_family_comp_index, hwctx->nb_comp_queues, VK_QUEUE_COMPUTE_BIT);
-        SET_OLD_QF(hwctx->queue_family_tx_index, hwctx->nb_tx_queues, VK_QUEUE_TRANSFER_BIT);
-        SET_OLD_QF(hwctx->queue_family_encode_index, hwctx->nb_encode_queues, VK_QUEUE_VIDEO_ENCODE_BIT_KHR);
-        SET_OLD_QF(hwctx->queue_family_decode_index, hwctx->nb_decode_queues, VK_QUEUE_VIDEO_DECODE_BIT_KHR);
-    }
-
-#undef SET_OLD_QF
-FF_ENABLE_DEPRECATION_WARNINGS
-#endif
-
-    return 0;
-}
-
-/* Only resources created by vulkan_device_create should be released here,
- * resources created by vulkan_device_init should be released by
- * vulkan_device_uninit, to make sure we don't free user provided resources,
- * and there is no leak.
- */
-static void vulkan_device_free(AVHWDeviceContext *ctx)
-{
-    VulkanDevicePriv *p = ctx->hwctx;
-    AVVulkanDeviceContext *hwctx = &p->p;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-
-    if (hwctx->act_dev)
-        vk->DestroyDevice(hwctx->act_dev, hwctx->alloc);
-
-    if (p->debug_ctx)
-        vk->DestroyDebugUtilsMessengerEXT(hwctx->inst, p->debug_ctx,
-                                          hwctx->alloc);
-
-    if (hwctx->inst)
-        vk->DestroyInstance(hwctx->inst, hwctx->alloc);
-
-    if (p->libvulkan)
-        dlclose(p->libvulkan);
-
-    RELEASE_PROPS(hwctx->enabled_inst_extensions, hwctx->nb_enabled_inst_extensions);
-    RELEASE_PROPS(hwctx->enabled_dev_extensions, hwctx->nb_enabled_dev_extensions);
-}
-
-static void vulkan_device_uninit(AVHWDeviceContext *ctx)
-{
-    VulkanDevicePriv *p = ctx->hwctx;
-
-    for (uint32_t i = 0; i < p->nb_tot_qfs; i++) {
-        pthread_mutex_destroy(p->qf_mutex[i]);
-        av_freep(&p->qf_mutex[i]);
-    }
-    av_freep(&p->qf_mutex);
-
-    ff_vk_uninit(&p->vkctx);
-}
-
-static int vulkan_device_has_rebar(AVHWDeviceContext *ctx)
-{
-    VulkanDevicePriv *p = ctx->hwctx;
-    VkDeviceSize max_vram = 0, max_visible_vram = 0;
-
-    /* Get device memory properties */
-    for (int i = 0; i < p->mprops.memoryTypeCount; i++) {
-        const VkMemoryType type = p->mprops.memoryTypes[i];
-        const VkMemoryHeap heap = p->mprops.memoryHeaps[type.heapIndex];
-        if (!(type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT))
-            continue;
-        max_vram = FFMAX(max_vram, heap.size);
-        if (type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
-            max_visible_vram = FFMAX(max_visible_vram, heap.size);
-    }
-
-    return max_vram - max_visible_vram < 1024; /* 1 kB tolerance */
-}
-
-static int vulkan_device_create_internal(AVHWDeviceContext *ctx,
-                                         VulkanDeviceSelection *dev_select,
-                                         int disable_multiplane,
-                                         AVDictionary *opts, int flags)
-{
-    int err = 0;
-    VkResult ret;
-    AVDictionaryEntry *opt_d;
-    VulkanDevicePriv *p = ctx->hwctx;
-    AVVulkanDeviceContext *hwctx = &p->p;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-    enum FFVulkanDebugMode debug_mode = FF_VULKAN_DEBUG_NONE;
-    VulkanDeviceFeatures supported_feats = { 0 };
-    VkDeviceCreateInfo dev_info = {
-        .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
-    };
-
-    /* Create an instance if not given one */
-    if ((err = create_instance(ctx, opts, &debug_mode)))
-        goto end;
-
-    /* Find a physical device (if not given one) */
-    if ((err = find_device(ctx, dev_select)))
-        goto end;
-
-    /* Find and enable extensions for the physical device */
-    if ((err = check_extensions(ctx, 1, opts, &dev_info.ppEnabledExtensionNames,
-                                &dev_info.enabledExtensionCount, debug_mode))) {
-        for (int i = 0; i < dev_info.queueCreateInfoCount; i++)
-            av_free((void *)dev_info.pQueueCreateInfos[i].pQueuePriorities);
-        av_free((void *)dev_info.pQueueCreateInfos);
-        goto end;
-    }
-
-    /* Get supported memory types */
-    vk->GetPhysicalDeviceMemoryProperties(hwctx->phys_dev, &p->mprops);
-
-    /* Get all supported features for the physical device */
-    device_features_init(ctx, &supported_feats);
-    vk->GetPhysicalDeviceFeatures2(hwctx->phys_dev, &supported_feats.device);
-
-    /* Copy all needed features from those supported and activate them */
-    device_features_init(ctx, &p->feats);
-    device_features_copy_needed(&p->feats, &supported_feats);
-    dev_info.pNext = p->feats.device.pNext;
-    dev_info.pEnabledFeatures = &p->feats.device.features;
-
-    /* Setup enabled queue families */
-    if ((err = setup_queue_families(ctx, &dev_info)))
-        goto end;
-
-    /* Finally create the device */
-    ret = vk->CreateDevice(hwctx->phys_dev, &dev_info, hwctx->alloc,
-                           &hwctx->act_dev);
-
-    for (int i = 0; i < dev_info.queueCreateInfoCount; i++)
-        av_free((void *)dev_info.pQueueCreateInfos[i].pQueuePriorities);
-    av_free((void *)dev_info.pQueueCreateInfos);
-
-    if (ret != VK_SUCCESS) {
-        av_log(ctx, AV_LOG_ERROR, "Device creation failure: %s\n",
-               ff_vk_ret2str(ret));
-        for (int i = 0; i < dev_info.enabledExtensionCount; i++)
-            av_free((void *)dev_info.ppEnabledExtensionNames[i]);
-        av_free((void *)dev_info.ppEnabledExtensionNames);
-        err = AVERROR_EXTERNAL;
-        goto end;
-    }
-
-    /* Tiled images setting, use them by default */
-    opt_d = av_dict_get(opts, "linear_images", NULL, 0);
-    if (opt_d)
-        p->use_linear_images = strtol(opt_d->value, NULL, 10);
-
-    /* Limit queues to a given number if needed */
-    opt_d = av_dict_get(opts, "limit_queues", NULL, 0);
-    if (opt_d)
-        p->limit_queues = strtol(opt_d->value, NULL, 10);
-
-    /* The disable_multiplane argument takes precedent over the option */
-    p->disable_multiplane = disable_multiplane;
-    if (!p->disable_multiplane) {
-        opt_d = av_dict_get(opts, "disable_multiplane", NULL, 0);
-        if (opt_d)
-            p->disable_multiplane = strtol(opt_d->value, NULL, 10);
-    }
-
-    /* Disable host pointer imports (by default on nvidia) */
-    p->avoid_host_import = p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY;
-    opt_d = av_dict_get(opts, "avoid_host_import", NULL, 0);
-    if (opt_d)
-        p->avoid_host_import = strtol(opt_d->value, NULL, 10);
-
-    /* Set the public device feature struct and its pNext chain */
-    hwctx->device_features = p->feats.device;
-
-    /* Set the list of all active extensions */
-    hwctx->enabled_dev_extensions = dev_info.ppEnabledExtensionNames;
-    hwctx->nb_enabled_dev_extensions = dev_info.enabledExtensionCount;
-
-    /* The extension lists need to be freed */
-    ctx->free = vulkan_device_free;
-
-end:
-    return err;
-}
-
-static void lock_queue(AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index)
-{
-    VulkanDevicePriv *p = ctx->hwctx;
-    pthread_mutex_lock(&p->qf_mutex[queue_family][index]);
-}
-
-static void unlock_queue(AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index)
-{
-    VulkanDevicePriv *p = ctx->hwctx;
-    pthread_mutex_unlock(&p->qf_mutex[queue_family][index]);
-}
-
-static int vulkan_device_init(AVHWDeviceContext *ctx)
-{
-    int err = 0;
-    uint32_t qf_num;
-    VulkanDevicePriv *p = ctx->hwctx;
-    AVVulkanDeviceContext *hwctx = &p->p;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-    VkQueueFamilyProperties2 *qf;
-    VkQueueFamilyVideoPropertiesKHR *qf_vid;
-    VkPhysicalDeviceExternalSemaphoreInfo ext_sem_props_info;
-    int graph_index, comp_index, tx_index, enc_index, dec_index;
-
-    /* Set device extension flags */
-    for (int i = 0; i < hwctx->nb_enabled_dev_extensions; i++) {
-        for (int j = 0; j < FF_ARRAY_ELEMS(optional_device_exts); j++) {
-            if (!strcmp(hwctx->enabled_dev_extensions[i],
-                        optional_device_exts[j].name)) {
-                p->vkctx.extensions |= optional_device_exts[j].flag;
-                break;
-            }
-        }
-    }
-
-    err = ff_vk_load_functions(ctx, vk, p->vkctx.extensions, 1, 1);
-    if (err < 0) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to load functions!\n");
-        return err;
-    }
-
-    p->props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
-    p->props.pNext = &p->hprops;
-    p->hprops.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT;
-    p->hprops.pNext = &p->dprops;
-    p->dprops.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
-
-    vk->GetPhysicalDeviceProperties2(hwctx->phys_dev, &p->props);
-    av_log(ctx, AV_LOG_VERBOSE, "Using device: %s\n",
-           p->props.properties.deviceName);
-    av_log(ctx, AV_LOG_VERBOSE, "Alignments:\n");
-    av_log(ctx, AV_LOG_VERBOSE, "    optimalBufferCopyRowPitchAlignment: %"PRIu64"\n",
-           p->props.properties.limits.optimalBufferCopyRowPitchAlignment);
-    av_log(ctx, AV_LOG_VERBOSE, "    minMemoryMapAlignment:              %"SIZE_SPECIFIER"\n",
-           p->props.properties.limits.minMemoryMapAlignment);
-    av_log(ctx, AV_LOG_VERBOSE, "    nonCoherentAtomSize:                %"PRIu64"\n",
-           p->props.properties.limits.nonCoherentAtomSize);
-    if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY)
-        av_log(ctx, AV_LOG_VERBOSE, "    minImportedHostPointerAlignment:    %"PRIu64"\n",
-               p->hprops.minImportedHostPointerAlignment);
-
-    vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &qf_num, NULL);
-    if (!qf_num) {
-        av_log(ctx, AV_LOG_ERROR, "Failed to get queues!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    ext_sem_props_info = (VkPhysicalDeviceExternalSemaphoreInfo) {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
-    };
-
-    /* Opaque FD semaphore properties */
-    ext_sem_props_info.handleType =
-#ifdef _WIN32
-        IsWindows8OrGreater()
-            ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
-            : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT;
-#else
-        VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
-#endif
-    p->ext_sem_props_opaque.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES;
-    vk->GetPhysicalDeviceExternalSemaphoreProperties(hwctx->phys_dev,
-                                                     &ext_sem_props_info,
-                                                     &p->ext_sem_props_opaque);
-
-    qf = av_malloc_array(qf_num, sizeof(VkQueueFamilyProperties2));
-    if (!qf)
-        return AVERROR(ENOMEM);
-
-    qf_vid = av_malloc_array(qf_num, sizeof(VkQueueFamilyVideoPropertiesKHR));
-    if (!qf_vid) {
-        av_free(qf);
-        return AVERROR(ENOMEM);
-    }
-
-    for (uint32_t i = 0; i < qf_num; i++) {
-        qf_vid[i] = (VkQueueFamilyVideoPropertiesKHR) {
-            .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR,
-        };
-        qf[i] = (VkQueueFamilyProperties2) {
-            .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
-            .pNext = p->vkctx.extensions & FF_VK_EXT_VIDEO_QUEUE ? &qf_vid[i] : NULL,
-        };
-    }
-
-    vk->GetPhysicalDeviceQueueFamilyProperties2(hwctx->phys_dev, &qf_num, qf);
-
-    p->qf_mutex = av_calloc(qf_num, sizeof(*p->qf_mutex));
-    if (!p->qf_mutex) {
-        err = AVERROR(ENOMEM);
-        goto end;
-    }
-    p->nb_tot_qfs = qf_num;
-
-    for (uint32_t i = 0; i < qf_num; i++) {
-        p->qf_mutex[i] = av_calloc(qf[i].queueFamilyProperties.queueCount,
-                                   sizeof(**p->qf_mutex));
-        if (!p->qf_mutex[i]) {
-            err = AVERROR(ENOMEM);
-            goto end;
-        }
-        for (uint32_t j = 0; j < qf[i].queueFamilyProperties.queueCount; j++) {
-            err = pthread_mutex_init(&p->qf_mutex[i][j], NULL);
-            if (err != 0) {
-                av_log(ctx, AV_LOG_ERROR, "pthread_mutex_init failed : %s\n",
-                       av_err2str(err));
-                err = AVERROR(err);
-                goto end;
-            }
-        }
-    }
-
-#if FF_API_VULKAN_FIXED_QUEUES
-FF_DISABLE_DEPRECATION_WARNINGS
-    graph_index = hwctx->nb_graphics_queues ? hwctx->queue_family_index : -1;
-    comp_index  = hwctx->nb_comp_queues ? hwctx->queue_family_comp_index : -1;
-    tx_index    = hwctx->nb_tx_queues ? hwctx->queue_family_tx_index : -1;
-    dec_index   = hwctx->nb_decode_queues ? hwctx->queue_family_decode_index : -1;
-    enc_index   = hwctx->nb_encode_queues ? hwctx->queue_family_encode_index : -1;
-
-#define CHECK_QUEUE(type, required, fidx, ctx_qf, qc)                                           \
-    do {                                                                                        \
-        if (ctx_qf < 0 && required) {                                                           \
-            av_log(ctx, AV_LOG_ERROR, "%s queue family is required, but marked as missing"      \
-                   " in the context!\n", type);                                                 \
-            err = AVERROR(EINVAL);                                                              \
-            goto end;                                                                           \
-        } else if (fidx < 0 || ctx_qf < 0) {                                                    \
-            break;                                                                              \
-        } else if (ctx_qf >= qf_num) {                                                          \
-            av_log(ctx, AV_LOG_ERROR, "Invalid %s family index %i (device has %i families)!\n", \
-                   type, ctx_qf, qf_num);                                                       \
-            err = AVERROR(EINVAL);                                                              \
-            goto end;                                                                           \
-        }                                                                                       \
-                                                                                                \
-        av_log(ctx, AV_LOG_VERBOSE, "Using queue family %i (queues: %i)"                        \
-               " for%s%s%s%s%s\n",                                                              \
-               ctx_qf, qc,                                                                      \
-               ctx_qf == graph_index ? " graphics" : "",                                        \
-               ctx_qf == comp_index  ? " compute" : "",                                         \
-               ctx_qf == tx_index    ? " transfers" : "",                                       \
-               ctx_qf == enc_index   ? " encode" : "",                                          \
-               ctx_qf == dec_index   ? " decode" : "");                                         \
-        graph_index = (ctx_qf == graph_index) ? -1 : graph_index;                               \
-        comp_index  = (ctx_qf == comp_index)  ? -1 : comp_index;                                \
-        tx_index    = (ctx_qf == tx_index)    ? -1 : tx_index;                                  \
-        enc_index   = (ctx_qf == enc_index)   ? -1 : enc_index;                                 \
-        dec_index   = (ctx_qf == dec_index)   ? -1 : dec_index;                                 \
-    } while (0)
-
-    CHECK_QUEUE("graphics", 0, graph_index, hwctx->queue_family_index,        hwctx->nb_graphics_queues);
-    CHECK_QUEUE("compute",  1, comp_index,  hwctx->queue_family_comp_index,   hwctx->nb_comp_queues);
-    CHECK_QUEUE("upload",   1, tx_index,    hwctx->queue_family_tx_index,     hwctx->nb_tx_queues);
-    CHECK_QUEUE("decode",   0, dec_index,   hwctx->queue_family_decode_index, hwctx->nb_decode_queues);
-    CHECK_QUEUE("encode",   0, enc_index,   hwctx->queue_family_encode_index, hwctx->nb_encode_queues);
-
-#undef CHECK_QUEUE
-
-    /* Update the new queue family fields. If non-zero already,
-     * it means API users have set it. */
-    if (!hwctx->nb_qf) {
-#define ADD_QUEUE(ctx_qf, qc, flag)                                    \
-    do {                                                               \
-        if (ctx_qf != -1) {                                            \
-            hwctx->qf[hwctx->nb_qf++] = (AVVulkanDeviceQueueFamily) {  \
-                .idx = ctx_qf,                                         \
-                .num = qc,                                             \
-                .flags = flag,                                         \
-            };                                                         \
-        }                                                              \
-    } while (0)
-
-        ADD_QUEUE(hwctx->queue_family_index, hwctx->nb_graphics_queues, VK_QUEUE_GRAPHICS_BIT);
-        ADD_QUEUE(hwctx->queue_family_comp_index, hwctx->nb_comp_queues, VK_QUEUE_COMPUTE_BIT);
-        ADD_QUEUE(hwctx->queue_family_tx_index, hwctx->nb_tx_queues, VK_QUEUE_TRANSFER_BIT);
-        ADD_QUEUE(hwctx->queue_family_decode_index, hwctx->nb_decode_queues, VK_QUEUE_VIDEO_DECODE_BIT_KHR);
-        ADD_QUEUE(hwctx->queue_family_encode_index, hwctx->nb_encode_queues, VK_QUEUE_VIDEO_ENCODE_BIT_KHR);
-#undef ADD_QUEUE
-    }
-FF_ENABLE_DEPRECATION_WARNINGS
-#endif
-
-    for (int i = 0; i < hwctx->nb_qf; i++) {
-        if (!hwctx->qf[i].video_caps &&
-            hwctx->qf[i].flags & (VK_QUEUE_VIDEO_DECODE_BIT_KHR |
-                                  VK_QUEUE_VIDEO_ENCODE_BIT_KHR)) {
-            hwctx->qf[i].video_caps = qf_vid[hwctx->qf[i].idx].videoCodecOperations;
-        }
-    }
-
-    /* Setup array for pQueueFamilyIndices with used queue families */
-    p->nb_img_qfs = 0;
-    for (int i = 0; i < hwctx->nb_qf; i++) {
-        int seen = 0;
-        /* Make sure each entry is unique
-         * (VUID-VkBufferCreateInfo-sharingMode-01419) */
-        for (int j = (i - 1); j >= 0; j--) {
-            if (hwctx->qf[i].idx == hwctx->qf[j].idx) {
-                seen = 1;
-                break;
-            }
-        }
-        if (!seen)
-            p->img_qfs[p->nb_img_qfs++] = hwctx->qf[i].idx;
-    }
-
-    if (!hwctx->lock_queue)
-        hwctx->lock_queue = lock_queue;
-    if (!hwctx->unlock_queue)
-        hwctx->unlock_queue = unlock_queue;
-
-    /* Re-query device capabilities, in case the device was created externally */
-    vk->GetPhysicalDeviceMemoryProperties(hwctx->phys_dev, &p->mprops);
-
-    p->vkctx.device = ctx;
-    p->vkctx.hwctx = hwctx;
-
-    ff_vk_load_props(&p->vkctx);
-    p->compute_qf = ff_vk_qf_find(&p->vkctx, VK_QUEUE_COMPUTE_BIT, 0);
-    p->transfer_qf = ff_vk_qf_find(&p->vkctx, VK_QUEUE_TRANSFER_BIT, 0);
-
-    /* Re-query device capabilities, in case the device was created externally */
-    vk->GetPhysicalDeviceMemoryProperties(hwctx->phys_dev, &p->mprops);
-
-    /* Only use host image transfers if ReBAR is enabled */
-    p->disable_host_transfer = !vulkan_device_has_rebar(ctx);
-
-end:
-    av_free(qf_vid);
-    av_free(qf);
-    return err;
-}
-
-static int vulkan_device_create(AVHWDeviceContext *ctx, const char *device,
-                                AVDictionary *opts, int flags)
-{
-    VulkanDeviceSelection dev_select = { 0 };
-    if (device && device[0]) {
-        char *end = NULL;
-        dev_select.index = strtol(device, &end, 10);
-        if (end == device) {
-            dev_select.index = 0;
-            dev_select.name  = device;
-        }
-    }
-
-    return vulkan_device_create_internal(ctx, &dev_select, 0, opts, flags);
-}
-
-static int vulkan_device_derive(AVHWDeviceContext *ctx,
-                                AVHWDeviceContext *src_ctx,
-                                AVDictionary *opts, int flags)
-{
-    av_unused VulkanDeviceSelection dev_select = { 0 };
-
-    /* If there's only one device on the system, then even if its not covered
-     * by the following checks (e.g. non-PCIe ARM GPU), having an empty
-     * dev_select will mean it'll get picked. */
-    switch(src_ctx->type) {
-#if CONFIG_VAAPI
-    case AV_HWDEVICE_TYPE_VAAPI: {
-        AVVAAPIDeviceContext *src_hwctx = src_ctx->hwctx;
-        VADisplay dpy = src_hwctx->display;
-#if VA_CHECK_VERSION(1, 15, 0)
-        VAStatus vas;
-        VADisplayAttribute attr = {
-            .type = VADisplayPCIID,
-        };
-#endif
-        const char *vendor;
-
-#if VA_CHECK_VERSION(1, 15, 0)
-        vas = vaGetDisplayAttributes(dpy, &attr, 1);
-        if (vas == VA_STATUS_SUCCESS && attr.flags != VA_DISPLAY_ATTRIB_NOT_SUPPORTED)
-            dev_select.pci_device = (attr.value & 0xFFFF);
-#endif
-
-        if (!dev_select.pci_device) {
-            vendor = vaQueryVendorString(dpy);
-            if (!vendor) {
-                av_log(ctx, AV_LOG_ERROR, "Unable to get device info from VAAPI!\n");
-                return AVERROR_EXTERNAL;
-            }
-
-            if (strstr(vendor, "AMD"))
-                dev_select.vendor_id = 0x1002;
-        }
-
-        return vulkan_device_create_internal(ctx, &dev_select, 0, opts, flags);
-    }
-#endif
-#if CONFIG_LIBDRM
-    case AV_HWDEVICE_TYPE_DRM: {
-        int err;
-        struct stat drm_node_info;
-        drmDevice *drm_dev_info;
-        AVDRMDeviceContext *src_hwctx = src_ctx->hwctx;
-
-        err = fstat(src_hwctx->fd, &drm_node_info);
-        if (err) {
-            av_log(ctx, AV_LOG_ERROR, "Unable to get node info from DRM fd: %s!\n",
-                   av_err2str(AVERROR(errno)));
-            return AVERROR_EXTERNAL;
-        }
-
-        dev_select.drm_major = major(drm_node_info.st_dev);
-        dev_select.drm_minor = minor(drm_node_info.st_dev);
-        dev_select.has_drm   = 1;
-
-        err = drmGetDevice(src_hwctx->fd, &drm_dev_info);
-        if (err) {
-            av_log(ctx, AV_LOG_ERROR, "Unable to get device info from DRM fd: %s!\n",
-                   av_err2str(AVERROR(errno)));
-            return AVERROR_EXTERNAL;
-        }
-
-        if (drm_dev_info->bustype == DRM_BUS_PCI)
-            dev_select.pci_device = drm_dev_info->deviceinfo.pci->device_id;
-
-        drmFreeDevice(&drm_dev_info);
-
-        return vulkan_device_create_internal(ctx, &dev_select, 0, opts, flags);
-    }
-#endif
-#if CONFIG_CUDA
-    case AV_HWDEVICE_TYPE_CUDA: {
-        AVHWDeviceContext *cuda_cu = src_ctx;
-        AVCUDADeviceContext *src_hwctx = src_ctx->hwctx;
-        AVCUDADeviceContextInternal *cu_internal = src_hwctx->internal;
-        CudaFunctions *cu = cu_internal->cuda_dl;
-
-        int ret = CHECK_CU(cu->cuDeviceGetUuid((CUuuid *)&dev_select.uuid,
-                                               cu_internal->cuda_device));
-        if (ret < 0) {
-            av_log(ctx, AV_LOG_ERROR, "Unable to get UUID from CUDA!\n");
-            return AVERROR_EXTERNAL;
-        }
-
-        dev_select.has_uuid = 1;
-
-        /*
-         * CUDA is not able to import multiplane images, so always derive a
-         * Vulkan device with multiplane disabled.
-         */
-        return vulkan_device_create_internal(ctx, &dev_select, 1, opts, flags);
-    }
-#endif
-    default:
-        return AVERROR(ENOSYS);
-    }
-}
-
-static int vulkan_frames_get_constraints(AVHWDeviceContext *ctx,
-                                         const void *hwconfig,
-                                         AVHWFramesConstraints *constraints)
-{
-    int count = 0;
-    VulkanDevicePriv *p = ctx->hwctx;
-
-    for (enum AVPixelFormat i = 0; i < nb_vk_formats_list; i++) {
-        count += vkfmt_from_pixfmt2(ctx, vk_formats_list[i].pixfmt,
-                                    p->use_linear_images ? VK_IMAGE_TILING_LINEAR :
-                                                           VK_IMAGE_TILING_OPTIMAL,
-                                    NULL, NULL, NULL, NULL, p->disable_multiplane, 1) >= 0;
-    }
-
-    constraints->valid_sw_formats = av_malloc_array(count + 1,
-                                                    sizeof(enum AVPixelFormat));
-    if (!constraints->valid_sw_formats)
-        return AVERROR(ENOMEM);
-
-    count = 0;
-    for (enum AVPixelFormat i = 0; i < nb_vk_formats_list; i++) {
-        if (vkfmt_from_pixfmt2(ctx, vk_formats_list[i].pixfmt,
-                               p->use_linear_images ? VK_IMAGE_TILING_LINEAR :
-                                                      VK_IMAGE_TILING_OPTIMAL,
-                               NULL, NULL, NULL, NULL, p->disable_multiplane, 1) >= 0) {
-            constraints->valid_sw_formats[count++] = vk_formats_list[i].pixfmt;
-        }
-    }
-
-    constraints->valid_sw_formats[count++] = AV_PIX_FMT_NONE;
-
-    constraints->min_width  = 1;
-    constraints->min_height = 1;
-    constraints->max_width  = p->props.properties.limits.maxImageDimension2D;
-    constraints->max_height = p->props.properties.limits.maxImageDimension2D;
-
-    constraints->valid_hw_formats = av_malloc_array(2, sizeof(enum AVPixelFormat));
-    if (!constraints->valid_hw_formats)
-        return AVERROR(ENOMEM);
-
-    constraints->valid_hw_formats[0] = AV_PIX_FMT_VULKAN;
-    constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
-
-    return 0;
-}
-
-static int alloc_mem(AVHWDeviceContext *ctx, VkMemoryRequirements *req,
-                     VkMemoryPropertyFlagBits req_flags, const void *alloc_extension,
-                     VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
-{
-    VkResult ret;
-    int index = -1;
-    VulkanDevicePriv *p = ctx->hwctx;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-    AVVulkanDeviceContext *dev_hwctx = &p->p;
-    VkMemoryAllocateInfo alloc_info = {
-        .sType          = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
-        .pNext          = alloc_extension,
-        .allocationSize = req->size,
-    };
-
-    /* The vulkan spec requires memory types to be sorted in the "optimal"
-     * order, so the first matching type we find will be the best/fastest one */
-    for (int i = 0; i < p->mprops.memoryTypeCount; i++) {
-        const VkMemoryType *type = &p->mprops.memoryTypes[i];
-
-        /* The memory type must be supported by the requirements (bitfield) */
-        if (!(req->memoryTypeBits & (1 << i)))
-            continue;
-
-        /* The memory type flags must include our properties */
-        if ((type->propertyFlags & req_flags) != req_flags)
-            continue;
-
-        /* The memory type must be large enough */
-        if (req->size > p->mprops.memoryHeaps[type->heapIndex].size)
-            continue;
-
-        /* Found a suitable memory type */
-        index = i;
-        break;
-    }
-
-    if (index < 0) {
-        av_log(ctx, AV_LOG_ERROR, "No memory type found for flags 0x%x\n",
-               req_flags);
-        return AVERROR(EINVAL);
-    }
-
-    alloc_info.memoryTypeIndex = index;
-
-    ret = vk->AllocateMemory(dev_hwctx->act_dev, &alloc_info,
-                             dev_hwctx->alloc, mem);
-    if (ret != VK_SUCCESS) {
-        av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory: %s\n",
-               ff_vk_ret2str(ret));
-        return AVERROR(ENOMEM);
-    }
-
-    *mem_flags |= p->mprops.memoryTypes[index].propertyFlags;
-
-    return 0;
-}
-
-static void vulkan_free_internal(AVVkFrame *f)
-{
-    av_unused AVVkFrameInternal *internal = f->internal;
-
-#if CONFIG_CUDA
-    if (internal->cuda_fc_ref) {
-        AVHWFramesContext *cuda_fc = (AVHWFramesContext *)internal->cuda_fc_ref->data;
-        int planes = av_pix_fmt_count_planes(cuda_fc->sw_format);
-        AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx;
-        AVCUDADeviceContext *cuda_dev = cuda_cu->hwctx;
-        AVCUDADeviceContextInternal *cu_internal = cuda_dev->internal;
-        CudaFunctions *cu = cu_internal->cuda_dl;
-
-        for (int i = 0; i < planes; i++) {
-            if (internal->cu_sem[i])
-                CHECK_CU(cu->cuDestroyExternalSemaphore(internal->cu_sem[i]));
-            if (internal->cu_mma[i])
-                CHECK_CU(cu->cuMipmappedArrayDestroy(internal->cu_mma[i]));
-            if (internal->ext_mem[i])
-                CHECK_CU(cu->cuDestroyExternalMemory(internal->ext_mem[i]));
-#ifdef _WIN32
-            if (internal->ext_sem_handle[i])
-                CloseHandle(internal->ext_sem_handle[i]);
-            if (internal->ext_mem_handle[i])
-                CloseHandle(internal->ext_mem_handle[i]);
-#endif
-        }
-
-        av_buffer_unref(&internal->cuda_fc_ref);
-    }
-#endif
-
-    pthread_mutex_destroy(&internal->update_mutex);
-    av_freep(&f->internal);
-}
-
-static void vulkan_frame_free(AVHWFramesContext *hwfc, AVVkFrame *f)
-{
-    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
-    AVVulkanDeviceContext *hwctx = &p->p;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-    int nb_images = ff_vk_count_images(f);
-    int nb_sems = 0;
-
-    while (nb_sems < FF_ARRAY_ELEMS(f->sem) && f->sem[nb_sems])
-        nb_sems++;
-
-    if (nb_sems) {
-        VkSemaphoreWaitInfo sem_wait = {
-            .sType          = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
-            .flags          = 0x0,
-            .pSemaphores    = f->sem,
-            .pValues        = f->sem_value,
-            .semaphoreCount = nb_sems,
-        };
-
-        vk->WaitSemaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
-    }
-
-    vulkan_free_internal(f);
-
-    for (int i = 0; i < nb_images; i++) {
-        vk->DestroyImage(hwctx->act_dev,     f->img[i], hwctx->alloc);
-        vk->FreeMemory(hwctx->act_dev,       f->mem[i], hwctx->alloc);
-        vk->DestroySemaphore(hwctx->act_dev, f->sem[i], hwctx->alloc);
-    }
-
-    av_free(f);
-}
-
-static void vulkan_frame_free_cb(void *opaque, uint8_t *data)
-{
-    vulkan_frame_free(opaque, (AVVkFrame*)data);
-}
-
-static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f,
-                          void *alloc_pnext, size_t alloc_pnext_stride)
-{
-    int img_cnt = 0, err;
-    VkResult ret;
-    AVHWDeviceContext *ctx = hwfc->device_ctx;
-    VulkanDevicePriv *p = ctx->hwctx;
-    AVVulkanDeviceContext *hwctx = &p->p;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-    VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { { 0 } };
-
-    while (f->img[img_cnt]) {
-        int use_ded_mem;
-        VkImageMemoryRequirementsInfo2 req_desc = {
-            .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
-            .image = f->img[img_cnt],
-        };
-        VkMemoryDedicatedAllocateInfo ded_alloc = {
-            .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
-            .pNext = (void *)(((uint8_t *)alloc_pnext) + img_cnt*alloc_pnext_stride),
-        };
-        VkMemoryDedicatedRequirements ded_req = {
-            .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
-        };
-        VkMemoryRequirements2 req = {
-            .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
-            .pNext = &ded_req,
-        };
-
-        vk->GetImageMemoryRequirements2(hwctx->act_dev, &req_desc, &req);
-
-        if (f->tiling == VK_IMAGE_TILING_LINEAR)
-            req.memoryRequirements.size = FFALIGN(req.memoryRequirements.size,
-                                                  p->props.properties.limits.minMemoryMapAlignment);
-
-        /* In case the implementation prefers/requires dedicated allocation */
-        use_ded_mem = ded_req.prefersDedicatedAllocation |
-                      ded_req.requiresDedicatedAllocation;
-        if (use_ded_mem)
-            ded_alloc.image = f->img[img_cnt];
-
-        /* Allocate memory */
-        if ((err = alloc_mem(ctx, &req.memoryRequirements,
-                             f->tiling == VK_IMAGE_TILING_LINEAR ?
-                             VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
-                             VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
-                             use_ded_mem ? &ded_alloc : (void *)ded_alloc.pNext,
-                             &f->flags, &f->mem[img_cnt])))
-            return err;
-
-        f->size[img_cnt] = req.memoryRequirements.size;
-        bind_info[img_cnt].sType  = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
-        bind_info[img_cnt].image  = f->img[img_cnt];
-        bind_info[img_cnt].memory = f->mem[img_cnt];
-
-        img_cnt++;
-    }
-
-    /* Bind the allocated memory to the images */
-    ret = vk->BindImageMemory2(hwctx->act_dev, img_cnt, bind_info);
-    if (ret != VK_SUCCESS) {
-        av_log(ctx, AV_LOG_ERROR, "Failed to bind memory: %s\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-
-    return 0;
-}
-
-enum PrepMode {
-    PREP_MODE_GENERAL,
-    PREP_MODE_WRITE,
-    PREP_MODE_EXTERNAL_EXPORT,
-    PREP_MODE_EXTERNAL_IMPORT,
-    PREP_MODE_DECODING_DST,
-    PREP_MODE_DECODING_DPB,
-    PREP_MODE_ENCODING_DPB,
-};
-
-static int prepare_frame(AVHWFramesContext *hwfc, FFVkExecPool *ectx,
-                         AVVkFrame *frame, enum PrepMode pmode)
-{
-    int err;
-    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-    VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS];
-    int nb_img_bar = 0;
-
-    uint32_t dst_qf = p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0];
-    VkImageLayout new_layout;
-    VkAccessFlags2 new_access;
-    VkPipelineStageFlagBits2 src_stage = VK_PIPELINE_STAGE_2_NONE;
-
-    /* This is dirty - but it works. The vulkan.c dependency system doesn't
-     * free non-refcounted frames, and non-refcounted hardware frames cannot
-     * happen anywhere outside of here. */
-    AVBufferRef tmp_ref = {
-        .data = (uint8_t *)hwfc,
-    };
-    AVFrame tmp_frame = {
-        .data[0] = (uint8_t *)frame,
-        .hw_frames_ctx = &tmp_ref,
-    };
-
-    VkCommandBuffer cmd_buf;
-    FFVkExecContext *exec = ff_vk_exec_get(&p->vkctx, ectx);
-    cmd_buf = exec->buf;
-    ff_vk_exec_start(&p->vkctx, exec);
-
-    err = ff_vk_exec_add_dep_frame(&p->vkctx, exec, &tmp_frame,
-                                   VK_PIPELINE_STAGE_2_NONE,
-                                   VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
-    if (err < 0)
-        return err;
-
-    switch (pmode) {
-    case PREP_MODE_GENERAL:
-        new_layout = VK_IMAGE_LAYOUT_GENERAL;
-        new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
-        break;
-    case PREP_MODE_WRITE:
-        new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
-        new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
-        break;
-    case PREP_MODE_EXTERNAL_IMPORT:
-        new_layout = VK_IMAGE_LAYOUT_GENERAL;
-        new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
-        break;
-    case PREP_MODE_EXTERNAL_EXPORT:
-        new_layout = VK_IMAGE_LAYOUT_GENERAL;
-        new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
-        dst_qf     = VK_QUEUE_FAMILY_EXTERNAL_KHR;
-        src_stage  = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
-        break;
-    case PREP_MODE_DECODING_DST:
-        new_layout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR;
-        new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
-        break;
-    case PREP_MODE_DECODING_DPB:
-        new_layout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR;
-        new_access = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
-        break;
-    case PREP_MODE_ENCODING_DPB:
-        new_layout = VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR;
-        new_access = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
-        break;
-    }
-
-    ff_vk_frame_barrier(&p->vkctx, exec, &tmp_frame, img_bar, &nb_img_bar,
-                        src_stage,
-                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                        new_access, new_layout, dst_qf);
-
-    vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-            .pImageMemoryBarriers = img_bar,
-            .imageMemoryBarrierCount = nb_img_bar,
-        });
-
-    err = ff_vk_exec_submit(&p->vkctx, exec);
-    if (err < 0)
-        return err;
-
-    /* We can do this because there are no real dependencies */
-    ff_vk_exec_discard_deps(&p->vkctx, exec);
-
-    return 0;
-}
-
-static inline void get_plane_wh(uint32_t *w, uint32_t *h, enum AVPixelFormat format,
-                                int frame_w, int frame_h, int plane)
-{
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format);
-
-    /* Currently always true unless gray + alpha support is added */
-    if (!plane || (plane == 3) || desc->flags & AV_PIX_FMT_FLAG_RGB ||
-        !(desc->flags & AV_PIX_FMT_FLAG_PLANAR)) {
-        *w = frame_w;
-        *h = frame_h;
-        return;
-    }
-
-    *w = AV_CEIL_RSHIFT(frame_w, desc->log2_chroma_w);
-    *h = AV_CEIL_RSHIFT(frame_h, desc->log2_chroma_h);
-}
-
-static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame,
-                        VkImageTiling tiling, VkImageUsageFlagBits usage,
-                        VkImageCreateFlags flags, int nb_layers,
-                        void *create_pnext)
-{
-    int err;
-    VkResult ret;
-    AVVulkanFramesContext *hwfc_vk = hwfc->hwctx;
-    AVHWDeviceContext *ctx = hwfc->device_ctx;
-    VulkanDevicePriv *p = ctx->hwctx;
-    AVVulkanDeviceContext *hwctx = &p->p;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-    AVVkFrame *f;
-
-    VkSemaphoreTypeCreateInfo sem_type_info = {
-        .sType         = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
-        .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
-        .initialValue  = 0,
-    };
-    VkSemaphoreCreateInfo sem_spawn = {
-        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
-        .pNext = &sem_type_info,
-    };
-
-    VkExportSemaphoreCreateInfo ext_sem_info_opaque = {
-        .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
-#ifdef _WIN32
-        .handleTypes = IsWindows8OrGreater()
-            ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
-            : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
-#else
-        .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
-#endif
-    };
-
-    /* Check if exporting is supported before chaining any structs */
-    if (p->ext_sem_props_opaque.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) {
-        if (p->vkctx.extensions & (FF_VK_EXT_EXTERNAL_WIN32_SEM | FF_VK_EXT_EXTERNAL_FD_SEM))
-            ff_vk_link_struct(&sem_type_info, &ext_sem_info_opaque);
-    }
-
-    f = av_vk_frame_alloc();
-    if (!f) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to allocate memory for AVVkFrame!\n");
-        return AVERROR(ENOMEM);
-    }
-
-    // TODO: check width and height for alignment in case of multiplanar (must be mod-2 if subsampled)
-
-    /* Create the images */
-    for (int i = 0; (hwfc_vk->format[i] != VK_FORMAT_UNDEFINED); i++) {
-        VkImageCreateInfo create_info = {
-            .sType                 = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
-            .pNext                 = create_pnext,
-            .imageType             = VK_IMAGE_TYPE_2D,
-            .format                = hwfc_vk->format[i],
-            .extent.depth          = 1,
-            .mipLevels             = 1,
-            .arrayLayers           = nb_layers,
-            .flags                 = flags,
-            .tiling                = tiling,
-            .initialLayout         = VK_IMAGE_LAYOUT_UNDEFINED,
-            .usage                 = usage,
-            .samples               = VK_SAMPLE_COUNT_1_BIT,
-            .pQueueFamilyIndices   = p->img_qfs,
-            .queueFamilyIndexCount = p->nb_img_qfs,
-            .sharingMode           = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
-                                                         VK_SHARING_MODE_EXCLUSIVE,
-        };
-
-        get_plane_wh(&create_info.extent.width, &create_info.extent.height,
-                     hwfc->sw_format, hwfc->width, hwfc->height, i);
-
-        ret = vk->CreateImage(hwctx->act_dev, &create_info,
-                              hwctx->alloc, &f->img[i]);
-        if (ret != VK_SUCCESS) {
-            av_log(ctx, AV_LOG_ERROR, "Image creation failure: %s\n",
-                   ff_vk_ret2str(ret));
-            err = AVERROR(EINVAL);
-            goto fail;
-        }
-
-        /* Create semaphore */
-        ret = vk->CreateSemaphore(hwctx->act_dev, &sem_spawn,
-                                  hwctx->alloc, &f->sem[i]);
-        if (ret != VK_SUCCESS) {
-            av_log(hwctx, AV_LOG_ERROR, "Failed to create semaphore: %s\n",
-                   ff_vk_ret2str(ret));
-            err = AVERROR_EXTERNAL;
-            goto fail;
-        }
-
-        f->queue_family[i] = p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0];
-        f->layout[i] = create_info.initialLayout;
-        f->access[i] = 0x0;
-        f->sem_value[i] = 0;
-    }
-
-    f->flags     = 0x0;
-    f->tiling    = tiling;
-
-    *frame = f;
-    return 0;
-
-fail:
-    vulkan_frame_free(hwfc, f);
-    return err;
-}
-
-/* Checks if an export flag is enabled, and if it is ORs it with *iexp */
-static void try_export_flags(AVHWFramesContext *hwfc,
-                             VkExternalMemoryHandleTypeFlags *comp_handle_types,
-                             VkExternalMemoryHandleTypeFlagBits *iexp,
-                             VkExternalMemoryHandleTypeFlagBits exp)
-{
-    VkResult ret;
-    AVVulkanFramesContext *hwctx = hwfc->hwctx;
-    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
-    AVVulkanDeviceContext *dev_hwctx = &p->p;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-
-    const VkImageDrmFormatModifierListCreateInfoEXT *drm_mod_info =
-        ff_vk_find_struct(hwctx->create_pnext,
-                          VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
-    int has_mods = hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && drm_mod_info;
-    int nb_mods;
-
-    VkExternalImageFormatProperties eprops = {
-        .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
-    };
-    VkImageFormatProperties2 props = {
-        .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
-        .pNext = &eprops,
-    };
-    VkPhysicalDeviceImageDrmFormatModifierInfoEXT phy_dev_mod_info = {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
-        .pNext = NULL,
-        .pQueueFamilyIndices   = p->img_qfs,
-        .queueFamilyIndexCount = p->nb_img_qfs,
-        .sharingMode           = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
-                                                     VK_SHARING_MODE_EXCLUSIVE,
-    };
-    VkPhysicalDeviceExternalImageFormatInfo enext = {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
-        .handleType = exp,
-        .pNext = has_mods ? &phy_dev_mod_info : NULL,
-    };
-    VkPhysicalDeviceImageFormatInfo2 pinfo = {
-        .sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
-        .pNext  = !exp ? NULL : &enext,
-        .format = vk_find_format_entry(hwfc->sw_format)->vkf,
-        .type   = VK_IMAGE_TYPE_2D,
-        .tiling = hwctx->tiling,
-        .usage  = hwctx->usage,
-        .flags  = VK_IMAGE_CREATE_ALIAS_BIT,
-    };
-
-    nb_mods = has_mods ? drm_mod_info->drmFormatModifierCount : 1;
-    for (int i = 0; i < nb_mods; i++) {
-        if (has_mods)
-            phy_dev_mod_info.drmFormatModifier = drm_mod_info->pDrmFormatModifiers[i];
-
-        ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev,
-                                                        &pinfo, &props);
-
-        if (ret == VK_SUCCESS) {
-            *iexp |= exp;
-            *comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes;
-        }
-    }
-}
-
-static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size)
-{
-    int err;
-    AVVkFrame *f;
-    AVBufferRef *avbuf = NULL;
-    AVHWFramesContext *hwfc = opaque;
-    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
-    VulkanFramesPriv *fp = hwfc->hwctx;
-    AVVulkanFramesContext *hwctx = &fp->p;
-    VkExternalMemoryHandleTypeFlags e = 0x0;
-    VkExportMemoryAllocateInfo eminfo[AV_NUM_DATA_POINTERS];
-
-    VkExternalMemoryImageCreateInfo eiinfo = {
-        .sType       = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
-        .pNext       = hwctx->create_pnext,
-    };
-
-#ifdef _WIN32
-    if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY)
-        try_export_flags(hwfc, &eiinfo.handleTypes, &e, IsWindows8OrGreater()
-                             ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
-                             : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT);
-#else
-    if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY)
-        try_export_flags(hwfc, &eiinfo.handleTypes, &e,
-                         VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT);
-
-    if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_DMABUF_MEMORY &&
-        hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
-        try_export_flags(hwfc, &eiinfo.handleTypes, &e,
-                         VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
-#endif
-
-    for (int i = 0; i < av_pix_fmt_count_planes(hwfc->sw_format); i++) {
-        eminfo[i].sType       = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO;
-        eminfo[i].pNext       = hwctx->alloc_pnext[i];
-        eminfo[i].handleTypes = e;
-    }
-
-    err = create_frame(hwfc, &f, hwctx->tiling, hwctx->usage, hwctx->img_flags,
-                       hwctx->nb_layers,
-                       eiinfo.handleTypes ? &eiinfo : hwctx->create_pnext);
-    if (err)
-        return NULL;
-
-    err = alloc_bind_mem(hwfc, f, eminfo, sizeof(*eminfo));
-    if (err)
-        goto fail;
-
-    if ( (hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR) &&
-        !(hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR))
-        err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_DECODING_DPB);
-    else if (hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)
-        err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_DECODING_DST);
-    else if (hwctx->usage & VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR)
-        err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_ENCODING_DPB);
-    else if (hwctx->usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)
-        err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_WRITE);
-    else
-        err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_GENERAL);
-    if (err)
-        goto fail;
-
-    avbuf = av_buffer_create((uint8_t *)f, sizeof(AVVkFrame),
-                             vulkan_frame_free_cb, hwfc, 0);
-    if (!avbuf)
-        goto fail;
-
-    return avbuf;
-
-fail:
-    vulkan_frame_free(hwfc, f);
-    return NULL;
-}
-
-static void lock_frame(AVHWFramesContext *fc, AVVkFrame *vkf)
-{
-    pthread_mutex_lock(&vkf->internal->update_mutex);
-}
-
-static void unlock_frame(AVHWFramesContext *fc, AVVkFrame *vkf)
-{
-    pthread_mutex_unlock(&vkf->internal->update_mutex);
-}
-
-static void vulkan_frames_uninit(AVHWFramesContext *hwfc)
-{
-    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
-    VulkanFramesPriv *fp = hwfc->hwctx;
-
-    if (fp->modifier_info) {
-        if (fp->modifier_info->pDrmFormatModifiers)
-            av_freep(&fp->modifier_info->pDrmFormatModifiers);
-        av_freep(&fp->modifier_info);
-    }
-
-    ff_vk_exec_pool_free(&p->vkctx, &fp->compute_exec);
-    ff_vk_exec_pool_free(&p->vkctx, &fp->upload_exec);
-    ff_vk_exec_pool_free(&p->vkctx, &fp->download_exec);
-
-    av_buffer_pool_uninit(&fp->tmp);
-}
-
-static int vulkan_frames_init(AVHWFramesContext *hwfc)
-{
-    int err;
-    AVVkFrame *f;
-    VulkanFramesPriv *fp = hwfc->hwctx;
-    AVVulkanFramesContext *hwctx = &fp->p;
-    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
-    AVVulkanDeviceContext *dev_hwctx = &p->p;
-    VkImageUsageFlagBits supported_usage;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-    const struct FFVkFormatEntry *fmt;
-    int disable_multiplane = p->disable_multiplane ||
-                             (hwctx->flags & AV_VK_FRAME_FLAG_DISABLE_MULTIPLANE);
-
-    /* Defaults */
-    if (!hwctx->nb_layers)
-        hwctx->nb_layers = 1;
-
-    /* VK_IMAGE_TILING_OPTIMAL == 0, can't check for it really */
-    if (p->use_linear_images &&
-        (hwctx->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT))
-        hwctx->tiling = VK_IMAGE_TILING_LINEAR;
-
-
-    fmt = vk_find_format_entry(hwfc->sw_format);
-    if (!fmt) {
-        av_log(hwfc, AV_LOG_ERROR, "Unsupported pixel format: %s!\n",
-               av_get_pix_fmt_name(hwfc->sw_format));
-        return AVERROR(EINVAL);
-    }
-
-    if (hwctx->format[0] != VK_FORMAT_UNDEFINED) {
-        if (hwctx->format[0] != fmt->vkf) {
-            for (int i = 0; i < fmt->nb_images_fallback; i++) {
-                if (hwctx->format[i] != fmt->fallback[i]) {
-                    av_log(hwfc, AV_LOG_ERROR, "Incompatible Vulkan format given "
-                           "for the current sw_format %s!\n",
-                           av_get_pix_fmt_name(hwfc->sw_format));
-                    return AVERROR(EINVAL);
-                }
-            }
-        }
-
-        /* Check if the sw_format itself is supported */
-        err = vkfmt_from_pixfmt2(hwfc->device_ctx, hwfc->sw_format,
-                                 hwctx->tiling, NULL,
-                                 NULL, NULL, &supported_usage, 0,
-                                 !hwctx->usage ||
-                                 (hwctx->usage & VK_IMAGE_USAGE_STORAGE_BIT));
-        if (err < 0) {
-            av_log(hwfc, AV_LOG_ERROR, "Unsupported sw format: %s!\n",
-                   av_get_pix_fmt_name(hwfc->sw_format));
-            return AVERROR(EINVAL);
-        }
-    } else {
-        err = vkfmt_from_pixfmt2(hwfc->device_ctx, hwfc->sw_format,
-                                 hwctx->tiling, hwctx->format, NULL,
-                                 NULL, &supported_usage,
-                                 disable_multiplane,
-                                 !hwctx->usage ||
-                                 (hwctx->usage & VK_IMAGE_USAGE_STORAGE_BIT));
-        if (err < 0)
-            return err;
-    }
-
-    /* Nvidia is violating the spec because they thought no one would use this. */
-    if (p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
-        (((fmt->nb_images == 1) && (fmt->vk_planes > 1)) ||
-         (av_pix_fmt_desc_get(hwfc->sw_format)->nb_components == 1)))
-        supported_usage &= ~VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
-
-    /* Image usage flags */
-    if (!hwctx->usage) {
-        hwctx->usage = supported_usage & (VK_IMAGE_USAGE_TRANSFER_DST_BIT |
-                                          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) && !p->disable_host_transfer)
-            hwctx->usage |= supported_usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
-
-        /* 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.
-     * Only fill them in automatically if the image is not going to be used as
-     * a DPB-only image, and we have SAMPLED/STORAGE bits set. */
-    if (!hwctx->img_flags) {
-        int is_lone_dpb = ((hwctx->usage & VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR) ||
-                           ((hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR) &&
-                            !(hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)));
-        int sampleable = hwctx->usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
-                                         VK_IMAGE_USAGE_STORAGE_BIT);
-        hwctx->img_flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
-        if (sampleable && !is_lone_dpb) {
-            hwctx->img_flags |= VK_IMAGE_CREATE_ALIAS_BIT;
-            if ((fmt->vk_planes > 1) && (hwctx->format[0] == fmt->vkf))
-                hwctx->img_flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
-        }
-    }
-
-    /* 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->vkctx.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE |
-                                FF_VK_EXT_VIDEO_MAINTENANCE_1))) {
-        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;
-
-    if (!hwctx->unlock_frame)
-        hwctx->unlock_frame = unlock_frame;
-
-    err = ff_vk_exec_pool_init(&p->vkctx, p->compute_qf, &fp->compute_exec,
-                               p->compute_qf->num, 0, 0, 0, NULL);
-    if (err)
-        return err;
-
-    err = ff_vk_exec_pool_init(&p->vkctx, p->transfer_qf, &fp->upload_exec,
-                               p->transfer_qf->num*2, 0, 0, 0, NULL);
-    if (err)
-        return err;
-
-    err = ff_vk_exec_pool_init(&p->vkctx, p->transfer_qf, &fp->download_exec,
-                               p->transfer_qf->num, 0, 0, 0, NULL);
-    if (err)
-        return err;
-
-    /* Test to see if allocation will fail */
-    err = create_frame(hwfc, &f, hwctx->tiling, hwctx->usage, hwctx->img_flags,
-                       hwctx->nb_layers, hwctx->create_pnext);
-    if (err)
-        return err;
-
-    /* Collect `VkDrmFormatModifierPropertiesEXT` for each plane. Required for DRM export. */
-    if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS && hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
-        VkImageDrmFormatModifierPropertiesEXT drm_mod = {
-            .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
-        };
-        err = vk->GetImageDrmFormatModifierPropertiesEXT(dev_hwctx->act_dev, f->img[0],
-                                                        &drm_mod);
-        if (err != VK_SUCCESS) {
-            av_log(hwfc, AV_LOG_ERROR, "Failed to get image DRM format modifier properties");
-            vulkan_frame_free(hwfc, f);
-            return AVERROR_EXTERNAL;
-        }
-        for (int i = 0; i < fmt->vk_planes; ++i) {
-            VkDrmFormatModifierPropertiesListEXT modp;
-            VkFormatProperties2 fmtp;
-            VkDrmFormatModifierPropertiesEXT *mod_props = NULL;
-
-            modp = (VkDrmFormatModifierPropertiesListEXT) {
-                .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
-            };
-            fmtp = (VkFormatProperties2) {
-                .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
-                .pNext = &modp,
-            };
-
-            /* query drmFormatModifierCount by keeping pDrmFormatModifierProperties NULL */
-            vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev, fmt->fallback[i], &fmtp);
-
-            modp.pDrmFormatModifierProperties =
-                av_calloc(modp.drmFormatModifierCount, sizeof(*modp.pDrmFormatModifierProperties));
-            if (!modp.pDrmFormatModifierProperties) {
-                vulkan_frame_free(hwfc, f);
-                return AVERROR(ENOMEM);
-            }
-            vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev, fmt->fallback[i], &fmtp);
-
-            for (uint32_t i = 0; i < modp.drmFormatModifierCount; ++i) {
-                VkDrmFormatModifierPropertiesEXT *m = &modp.pDrmFormatModifierProperties[i];
-                if (m->drmFormatModifier == drm_mod.drmFormatModifier) {
-                    mod_props = m;
-                    break;
-                }
-            }
-
-            if (mod_props == NULL) {
-                av_log(hwfc, AV_LOG_ERROR, "No DRM format modifier properties found for modifier 0x%016"PRIx64"\n",
-                          drm_mod.drmFormatModifier);
-                av_free(modp.pDrmFormatModifierProperties);
-                vulkan_frame_free(hwfc, f);
-                return AVERROR_EXTERNAL;
-            }
-
-            fp->drm_format_modifier_properties[i] = *mod_props;
-            av_free(modp.pDrmFormatModifierProperties);
-        }
-    }
-
-    vulkan_frame_free(hwfc, f);
-
-    /* If user did not specify a pool, hwfc->pool will be set to the internal one
-     * in hwcontext.c just after this gets called */
-    if (!hwfc->pool) {
-        ffhwframesctx(hwfc)->pool_internal = av_buffer_pool_init2(sizeof(AVVkFrame),
-                                                                  hwfc, vulkan_pool_alloc,
-                                                                  NULL);
-        if (!ffhwframesctx(hwfc)->pool_internal)
-            return AVERROR(ENOMEM);
-    }
-
-    return 0;
-}
-
-static int vulkan_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
-{
-    frame->buf[0] = av_buffer_pool_get(hwfc->pool);
-    if (!frame->buf[0])
-        return AVERROR(ENOMEM);
-
-    frame->data[0] = frame->buf[0]->data;
-    frame->format  = AV_PIX_FMT_VULKAN;
-    frame->width   = hwfc->width;
-    frame->height  = hwfc->height;
-
-    return 0;
-}
-
-static int vulkan_transfer_get_formats(AVHWFramesContext *hwfc,
-                                       enum AVHWFrameTransferDirection dir,
-                                       enum AVPixelFormat **formats)
-{
-    enum AVPixelFormat *fmts;
-    int n = 2;
-
-#if CONFIG_CUDA
-    n++;
-#endif
-    fmts = av_malloc_array(n, sizeof(*fmts));
-    if (!fmts)
-        return AVERROR(ENOMEM);
-
-    n = 0;
-    fmts[n++] = hwfc->sw_format;
-#if CONFIG_CUDA
-    fmts[n++] = AV_PIX_FMT_CUDA;
-#endif
-    fmts[n++] = AV_PIX_FMT_NONE;
-
-    *formats = fmts;
-    return 0;
-}
-
-#if CONFIG_LIBDRM
-static void vulkan_unmap_from_drm(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap)
-{
-    vulkan_frame_free(hwfc, hwmap->priv);
-}
-
-static const struct {
-    uint32_t drm_fourcc;
-    VkFormat vk_format;
-} vulkan_drm_format_map[] = {
-    { DRM_FORMAT_R8,       VK_FORMAT_R8_UNORM       },
-    { DRM_FORMAT_R16,      VK_FORMAT_R16_UNORM      },
-    { DRM_FORMAT_GR88,     VK_FORMAT_R8G8_UNORM     },
-    { DRM_FORMAT_RG88,     VK_FORMAT_R8G8_UNORM     },
-    { DRM_FORMAT_GR1616,   VK_FORMAT_R16G16_UNORM   },
-    { DRM_FORMAT_RG1616,   VK_FORMAT_R16G16_UNORM   },
-    { DRM_FORMAT_ARGB8888, VK_FORMAT_B8G8R8A8_UNORM },
-    { DRM_FORMAT_XRGB8888, VK_FORMAT_B8G8R8A8_UNORM },
-    { DRM_FORMAT_ABGR8888, VK_FORMAT_R8G8B8A8_UNORM },
-    { DRM_FORMAT_XBGR8888, VK_FORMAT_R8G8B8A8_UNORM },
-    { DRM_FORMAT_ARGB2101010, VK_FORMAT_A2B10G10R10_UNORM_PACK32 },
-    { DRM_FORMAT_ABGR2101010, VK_FORMAT_A2R10G10B10_UNORM_PACK32 },
-    { DRM_FORMAT_XRGB2101010, VK_FORMAT_A2B10G10R10_UNORM_PACK32 },
-    { DRM_FORMAT_XBGR2101010, VK_FORMAT_A2R10G10B10_UNORM_PACK32 },
-
-    // All these DRM_FORMATs were added in the same libdrm commit.
-#ifdef DRM_FORMAT_XYUV8888
-    { DRM_FORMAT_XYUV8888, VK_FORMAT_R8G8B8A8_UNORM     },
-    { DRM_FORMAT_XVYU2101010, VK_FORMAT_A2R10G10B10_UNORM_PACK32 } ,
-    { DRM_FORMAT_XVYU12_16161616, VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 } ,
-    { DRM_FORMAT_XVYU16161616, VK_FORMAT_R16G16B16A16_UNORM } ,
-#endif
-};
-
-static inline VkFormat drm_to_vulkan_fmt(uint32_t drm_fourcc)
-{
-    for (int i = 0; i < FF_ARRAY_ELEMS(vulkan_drm_format_map); i++)
-        if (vulkan_drm_format_map[i].drm_fourcc == drm_fourcc)
-            return vulkan_drm_format_map[i].vk_format;
-    return VK_FORMAT_UNDEFINED;
-}
-
-static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **frame,
-                                          const AVFrame *src, int flags)
-{
-    int err = 0;
-    VkResult ret;
-    AVVkFrame *f;
-    int bind_counts = 0;
-    AVHWDeviceContext *ctx = hwfc->device_ctx;
-    VulkanDevicePriv *p = ctx->hwctx;
-    AVVulkanDeviceContext *hwctx = &p->p;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-    const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)src->data[0];
-    VkBindImageMemoryInfo bind_info[AV_DRM_MAX_PLANES];
-    VkBindImagePlaneMemoryInfo plane_info[AV_DRM_MAX_PLANES];
-
-    for (int i = 0; i < desc->nb_layers; i++) {
-        if (drm_to_vulkan_fmt(desc->layers[i].format) == VK_FORMAT_UNDEFINED) {
-            av_log(ctx, AV_LOG_ERROR, "Unsupported DMABUF layer format %#08x!\n",
-                   desc->layers[i].format);
-            return AVERROR(EINVAL);
-        }
-    }
-
-    if (!(f = av_vk_frame_alloc())) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to allocate memory for AVVkFrame!\n");
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    f->tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
-
-    for (int i = 0; i < desc->nb_layers; i++) {
-        const int planes = desc->layers[i].nb_planes;
-
-        /* Semaphore */
-        VkSemaphoreTypeCreateInfo sem_type_info = {
-            .sType         = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
-            .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
-            .initialValue  = 0,
-        };
-        VkSemaphoreCreateInfo sem_spawn = {
-            .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
-            .pNext = &sem_type_info,
-        };
-
-        /* Image creation */
-        VkSubresourceLayout ext_img_layouts[AV_DRM_MAX_PLANES];
-        VkImageDrmFormatModifierExplicitCreateInfoEXT ext_img_mod_spec = {
-            .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
-            .drmFormatModifier = desc->objects[0].format_modifier,
-            .drmFormatModifierPlaneCount = planes,
-            .pPlaneLayouts = (const VkSubresourceLayout *)&ext_img_layouts,
-        };
-        VkExternalMemoryImageCreateInfo ext_img_spec = {
-            .sType       = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
-            .pNext       = &ext_img_mod_spec,
-            .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
-        };
-        VkImageCreateInfo create_info = {
-            .sType                 = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
-            .pNext                 = &ext_img_spec,
-            .imageType             = VK_IMAGE_TYPE_2D,
-            .format                = drm_to_vulkan_fmt(desc->layers[i].format),
-            .extent.depth          = 1,
-            .mipLevels             = 1,
-            .arrayLayers           = 1,
-            .flags                 = 0x0,
-            .tiling                = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
-            .initialLayout         = VK_IMAGE_LAYOUT_UNDEFINED, /* specs say so */
-            .usage                 = 0x0, /* filled in below */
-            .samples               = VK_SAMPLE_COUNT_1_BIT,
-            .pQueueFamilyIndices   = p->img_qfs,
-            .queueFamilyIndexCount = p->nb_img_qfs,
-            .sharingMode           = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
-                                                         VK_SHARING_MODE_EXCLUSIVE,
-        };
-
-        /* Image format verification */
-        VkExternalImageFormatProperties ext_props = {
-            .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
-        };
-        VkImageFormatProperties2 props_ret = {
-            .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
-            .pNext = &ext_props,
-        };
-        VkPhysicalDeviceImageDrmFormatModifierInfoEXT props_drm_mod = {
-            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
-            .drmFormatModifier = ext_img_mod_spec.drmFormatModifier,
-            .pQueueFamilyIndices = create_info.pQueueFamilyIndices,
-            .queueFamilyIndexCount = create_info.queueFamilyIndexCount,
-            .sharingMode = create_info.sharingMode,
-        };
-        VkPhysicalDeviceExternalImageFormatInfo props_ext = {
-            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
-            .pNext = &props_drm_mod,
-            .handleType = ext_img_spec.handleTypes,
-        };
-        VkPhysicalDeviceImageFormatInfo2 fmt_props;
-
-        if (flags & AV_HWFRAME_MAP_READ)
-            create_info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT |
-                                 VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
-        if (flags & AV_HWFRAME_MAP_WRITE)
-            create_info.usage |= VK_IMAGE_USAGE_STORAGE_BIT |
-                                 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
-
-        fmt_props = (VkPhysicalDeviceImageFormatInfo2) {
-            .sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
-            .pNext  = &props_ext,
-            .format = create_info.format,
-            .type   = create_info.imageType,
-            .tiling = create_info.tiling,
-            .usage  = create_info.usage,
-            .flags  = create_info.flags,
-        };
-
-        /* Check if importing is possible for this combination of parameters */
-        ret = vk->GetPhysicalDeviceImageFormatProperties2(hwctx->phys_dev,
-                                                          &fmt_props, &props_ret);
-        if (ret != VK_SUCCESS) {
-            av_log(ctx, AV_LOG_ERROR, "Cannot map DRM frame to Vulkan: %s\n",
-                   ff_vk_ret2str(ret));
-            err = AVERROR_EXTERNAL;
-            goto fail;
-        }
-
-        /* Set the image width/height */
-        get_plane_wh(&create_info.extent.width, &create_info.extent.height,
-                     hwfc->sw_format, src->width, src->height, i);
-
-        /* Set the subresource layout based on the layer properties */
-        for (int j = 0; j < planes; j++) {
-            ext_img_layouts[j].offset     = desc->layers[i].planes[j].offset;
-            ext_img_layouts[j].rowPitch   = desc->layers[i].planes[j].pitch;
-            ext_img_layouts[j].size       = 0; /* The specs say so for all 3 */
-            ext_img_layouts[j].arrayPitch = 0;
-            ext_img_layouts[j].depthPitch = 0;
-        }
-
-        /* Create image */
-        ret = vk->CreateImage(hwctx->act_dev, &create_info,
-                              hwctx->alloc, &f->img[i]);
-        if (ret != VK_SUCCESS) {
-            av_log(ctx, AV_LOG_ERROR, "Image creation failure: %s\n",
-                   ff_vk_ret2str(ret));
-            err = AVERROR(EINVAL);
-            goto fail;
-        }
-
-        ret = vk->CreateSemaphore(hwctx->act_dev, &sem_spawn,
-                                  hwctx->alloc, &f->sem[i]);
-        if (ret != VK_SUCCESS) {
-            av_log(hwctx, AV_LOG_ERROR, "Failed to create semaphore: %s\n",
-                   ff_vk_ret2str(ret));
-            err = AVERROR_EXTERNAL;
-            goto fail;
-        }
-
-        f->queue_family[i] = VK_QUEUE_FAMILY_EXTERNAL;
-        f->layout[i] = create_info.initialLayout;
-        f->access[i] = 0x0;
-        f->sem_value[i] = 0;
-    }
-
-    for (int i = 0; i < desc->nb_layers; i++) {
-        /* Memory requirements */
-        VkImageMemoryRequirementsInfo2 req_desc = {
-            .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
-            .image = f->img[i],
-        };
-        VkMemoryDedicatedRequirements ded_req = {
-            .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
-        };
-        VkMemoryRequirements2 req2 = {
-            .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
-            .pNext = &ded_req,
-        };
-
-        /* Allocation/importing */
-        VkMemoryFdPropertiesKHR fdmp = {
-            .sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR,
-        };
-        /* This assumes that a layer will never be constructed from multiple
-         * objects. If that was to happen in the real world, this code would
-         * need to import each plane separately.
-         */
-        VkImportMemoryFdInfoKHR idesc = {
-            .sType      = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
-            .fd         = dup(desc->objects[desc->layers[i].planes[0].object_index].fd),
-            .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
-        };
-        VkMemoryDedicatedAllocateInfo ded_alloc = {
-            .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
-            .pNext = &idesc,
-            .image = req_desc.image,
-        };
-
-        /* Get object properties */
-        ret = vk->GetMemoryFdPropertiesKHR(hwctx->act_dev,
-                                           VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
-                                           idesc.fd, &fdmp);
-        if (ret != VK_SUCCESS) {
-            av_log(hwfc, AV_LOG_ERROR, "Failed to get FD properties: %s\n",
-                   ff_vk_ret2str(ret));
-            err = AVERROR_EXTERNAL;
-            close(idesc.fd);
-            goto fail;
-        }
-
-        vk->GetImageMemoryRequirements2(hwctx->act_dev, &req_desc, &req2);
-
-        /* Only a single bit must be set, not a range, and it must match */
-        req2.memoryRequirements.memoryTypeBits = fdmp.memoryTypeBits;
-
-        err = alloc_mem(ctx, &req2.memoryRequirements,
-                        VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
-                        (ded_req.prefersDedicatedAllocation ||
-                         ded_req.requiresDedicatedAllocation) ?
-                            &ded_alloc : ded_alloc.pNext,
-                        &f->flags, &f->mem[i]);
-        if (err) {
-            close(idesc.fd);
-            return err;
-        }
-
-        f->size[i] = req2.memoryRequirements.size;
-    }
-
-    for (int i = 0; i < desc->nb_layers; i++) {
-        const int planes = desc->layers[i].nb_planes;
-        for (int j = 0; j < planes; j++) {
-            VkImageAspectFlagBits aspect = j == 0 ? VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT :
-                                           j == 1 ? VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT :
-                                                    VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT;
-
-            plane_info[bind_counts].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO;
-            plane_info[bind_counts].pNext = NULL;
-            plane_info[bind_counts].planeAspect = aspect;
-
-            bind_info[bind_counts].sType  = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
-            bind_info[bind_counts].pNext  = planes > 1 ? &plane_info[bind_counts] : NULL;
-            bind_info[bind_counts].image  = f->img[i];
-            bind_info[bind_counts].memory = f->mem[i];
-
-            /* Offset is already signalled via pPlaneLayouts above */
-            bind_info[bind_counts].memoryOffset = 0;
-
-            bind_counts++;
-        }
-    }
-
-    /* Bind the allocated memory to the images */
-    ret = vk->BindImageMemory2(hwctx->act_dev, bind_counts, bind_info);
-    if (ret != VK_SUCCESS) {
-        av_log(ctx, AV_LOG_ERROR, "Failed to bind memory: %s\n",
-               ff_vk_ret2str(ret));
-        err = AVERROR_EXTERNAL;
-        goto fail;
-    }
-
-    *frame = f;
-
-    return 0;
-
-fail:
-    vulkan_frame_free(hwfc, f);
-
-    return err;
-}
-
-static int vulkan_map_from_drm_frame_sync(AVHWFramesContext *hwfc, AVFrame *dst,
-                                          const AVFrame *src, int flags)
-{
-    int err;
-    VkResult ret;
-    AVHWDeviceContext *ctx = hwfc->device_ctx;
-    VulkanDevicePriv *p = ctx->hwctx;
-    VulkanFramesPriv *fp = hwfc->hwctx;
-    AVVulkanDeviceContext *hwctx = &p->p;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-
-    const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)src->data[0];
-
-#ifdef DMA_BUF_IOCTL_EXPORT_SYNC_FILE
-    if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_SEM) {
-        VkCommandBuffer cmd_buf;
-        FFVkExecContext *exec;
-        VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS];
-        VkSemaphore drm_sync_sem[AV_DRM_MAX_PLANES] = { 0 };
-        int nb_img_bar = 0;
-
-        for (int i = 0; i < desc->nb_objects; i++) {
-            VkSemaphoreTypeCreateInfo sem_type_info = {
-                .sType         = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
-                .semaphoreType = VK_SEMAPHORE_TYPE_BINARY,
-            };
-            VkSemaphoreCreateInfo sem_spawn = {
-                .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
-                .pNext = &sem_type_info,
-            };
-            VkImportSemaphoreFdInfoKHR import_info;
-            struct dma_buf_export_sync_file implicit_fd_info = {
-                .flags = DMA_BUF_SYNC_READ,
-                .fd = -1,
-            };
-
-            if (ioctl(desc->objects[i].fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE,
-                      &implicit_fd_info)) {
-                err = AVERROR(errno);
-                av_log(hwctx, AV_LOG_ERROR, "Failed to retrieve implicit DRM sync file: %s\n",
-                       av_err2str(err));
-                for (; i >= 0; i--)
-                    vk->DestroySemaphore(hwctx->act_dev, drm_sync_sem[i], hwctx->alloc);
-                return err;
-            }
-
-            ret = vk->CreateSemaphore(hwctx->act_dev, &sem_spawn,
-                                      hwctx->alloc, &drm_sync_sem[i]);
-            if (ret != VK_SUCCESS) {
-                av_log(hwctx, AV_LOG_ERROR, "Failed to create semaphore: %s\n",
-                       ff_vk_ret2str(ret));
-                err = AVERROR_EXTERNAL;
-                for (; i >= 0; i--)
-                    vk->DestroySemaphore(hwctx->act_dev, drm_sync_sem[i], hwctx->alloc);
-                return err;
-            }
-
-            import_info = (VkImportSemaphoreFdInfoKHR) {
-                .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
-                .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
-                .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
-                .semaphore = drm_sync_sem[i],
-                .fd = implicit_fd_info.fd,
-            };
-
-            ret = vk->ImportSemaphoreFdKHR(hwctx->act_dev, &import_info);
-            if (ret != VK_SUCCESS) {
-                av_log(hwctx, AV_LOG_ERROR, "Failed to import semaphore: %s\n",
-                       ff_vk_ret2str(ret));
-                err = AVERROR_EXTERNAL;
-                for (; i >= 0; i--)
-                    vk->DestroySemaphore(hwctx->act_dev, drm_sync_sem[i], hwctx->alloc);
-                return err;
-            }
-        }
-
-        exec = ff_vk_exec_get(&p->vkctx, &fp->compute_exec);
-        cmd_buf = exec->buf;
-
-        ff_vk_exec_start(&p->vkctx, exec);
-
-        /* Ownership of semaphores is passed */
-        err = ff_vk_exec_add_dep_bool_sem(&p->vkctx, exec,
-                                          drm_sync_sem, desc->nb_objects,
-                                          VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, 1);
-        if (err < 0)
-            return err;
-
-        err = ff_vk_exec_add_dep_frame(&p->vkctx, exec, dst,
-                                       VK_PIPELINE_STAGE_2_NONE,
-                                       VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
-        if (err < 0)
-            return err;
-
-        ff_vk_frame_barrier(&p->vkctx, exec, dst, img_bar, &nb_img_bar,
-                            VK_PIPELINE_STAGE_2_NONE,
-                            VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                            ((flags & AV_HWFRAME_MAP_READ) ?
-                             VK_ACCESS_2_SHADER_SAMPLED_READ_BIT : 0x0) |
-                            ((flags & AV_HWFRAME_MAP_WRITE) ?
-                             VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT : 0x0),
-                            VK_IMAGE_LAYOUT_GENERAL,
-                            p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0]);
-
-        vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
-                .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-                .pImageMemoryBarriers = img_bar,
-                .imageMemoryBarrierCount = nb_img_bar,
-            });
-
-        err = ff_vk_exec_submit(&p->vkctx, exec);
-        if (err < 0)
-            return err;
-    } else
-#endif
-    {
-        AVVkFrame *f = (AVVkFrame *)dst->data[0];
-        av_log(hwctx, AV_LOG_WARNING, "No support for synchronization when importing DMA-BUFs, "
-                                      "image may be corrupted.\n");
-        err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_EXTERNAL_IMPORT);
-        if (err)
-            return err;
-    }
-
-    return 0;
-}
-
-static int vulkan_map_from_drm(AVHWFramesContext *hwfc, AVFrame *dst,
-                               const AVFrame *src, int flags)
-{
-    int err = 0;
-    AVVkFrame *f;
-
-    if ((err = vulkan_map_from_drm_frame_desc(hwfc, &f, src, flags)))
-        return err;
-
-    /* The unmapping function will free this */
-    dst->data[0] = (uint8_t *)f;
-    dst->width   = src->width;
-    dst->height  = src->height;
-
-    err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
-                                &vulkan_unmap_from_drm, f);
-    if (err < 0)
-        goto fail;
-
-    err = vulkan_map_from_drm_frame_sync(hwfc, dst, src, flags);
-    if (err < 0)
-        return err;
-
-    av_log(hwfc, AV_LOG_DEBUG, "Mapped DRM object to Vulkan!\n");
-
-    return 0;
-
-fail:
-    vulkan_frame_free(hwfc->device_ctx->hwctx, f);
-    dst->data[0] = NULL;
-    return err;
-}
-
-#if CONFIG_VAAPI
-static int vulkan_map_from_vaapi(AVHWFramesContext *dst_fc,
-                                 AVFrame *dst, const AVFrame *src,
-                                 int flags)
-{
-    int err;
-    AVFrame *tmp = av_frame_alloc();
-    AVHWFramesContext *vaapi_fc = (AVHWFramesContext*)src->hw_frames_ctx->data;
-    AVVAAPIDeviceContext *vaapi_ctx = vaapi_fc->device_ctx->hwctx;
-    VASurfaceID surface_id = (VASurfaceID)(uintptr_t)src->data[3];
-
-    if (!tmp)
-        return AVERROR(ENOMEM);
-
-    /* We have to sync since like the previous comment said, no semaphores */
-    vaSyncSurface(vaapi_ctx->display, surface_id);
-
-    tmp->format = AV_PIX_FMT_DRM_PRIME;
-
-    err = av_hwframe_map(tmp, src, flags);
-    if (err < 0)
-        goto fail;
-
-    err = vulkan_map_from_drm(dst_fc, dst, tmp, flags);
-    if (err < 0)
-        goto fail;
-
-    err = ff_hwframe_map_replace(dst, src);
-
-fail:
-    av_frame_free(&tmp);
-    return err;
-}
-#endif
-#endif
-
-#if CONFIG_CUDA
-static int export_mem_to_cuda(AVHWDeviceContext *ctx,
-                              AVHWDeviceContext *cuda_cu, CudaFunctions *cu,
-                              AVVkFrameInternal *dst_int, int idx,
-                              VkDeviceMemory mem, size_t size)
-{
-    VkResult ret;
-    VulkanDevicePriv *p = ctx->hwctx;
-    AVVulkanDeviceContext *hwctx = &p->p;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-
-#ifdef _WIN32
-    CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = {
-        .type = IsWindows8OrGreater()
-                ? CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32
-                : CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT,
-            .size = size,
-    };
-    VkMemoryGetWin32HandleInfoKHR export_info = {
-        .sType      = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR,
-        .memory     = mem,
-        .handleType = IsWindows8OrGreater()
-            ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
-            : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
-    };
-
-    ret = vk->GetMemoryWin32HandleKHR(hwctx->act_dev, &export_info,
-                                      &ext_desc.handle.win32.handle);
-    if (ret != VK_SUCCESS) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to export the image as a Win32 Handle: %s!\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-    dst_int->ext_mem_handle[idx] = ext_desc.handle.win32.handle;
-#else
-    CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = {
-        .type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD,
-        .size = size,
-    };
-    VkMemoryGetFdInfoKHR export_info = {
-        .sType      = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
-        .memory     = mem,
-        .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
-    };
-
-    ret = vk->GetMemoryFdKHR(hwctx->act_dev, &export_info,
-                             &ext_desc.handle.fd);
-    if (ret != VK_SUCCESS) {
-        av_log(ctx, AV_LOG_ERROR, "Unable to export the image as a FD: %s!\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-#endif
-
-    ret = CHECK_CU(cu->cuImportExternalMemory(&dst_int->ext_mem[idx], &ext_desc));
-    if (ret < 0) {
-#ifndef _WIN32
-        close(ext_desc.handle.fd);
-#endif
-        return AVERROR_EXTERNAL;
-    }
-
-    return 0;
-}
-
-static int export_sem_to_cuda(AVHWDeviceContext *ctx,
-                              AVHWDeviceContext *cuda_cu, CudaFunctions *cu,
-                              AVVkFrameInternal *dst_int, int idx,
-                              VkSemaphore sem)
-{
-    VkResult ret;
-    VulkanDevicePriv *p = ctx->hwctx;
-    AVVulkanDeviceContext *hwctx = &p->p;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-
-#ifdef _WIN32
-    VkSemaphoreGetWin32HandleInfoKHR sem_export = {
-        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR,
-        .semaphore = sem,
-        .handleType = IsWindows8OrGreater()
-                      ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
-                      : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
-    };
-    CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = {
-        .type = 10 /* TODO: CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_WIN32 */,
-    };
-#else
-    VkSemaphoreGetFdInfoKHR sem_export = {
-        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
-        .semaphore = sem,
-        .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
-    };
-    CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = {
-        .type = 9 /* TODO: CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_FD */,
-    };
-#endif
-
-#ifdef _WIN32
-    ret = vk->GetSemaphoreWin32HandleKHR(hwctx->act_dev, &sem_export,
-                                         &ext_sem_desc.handle.win32.handle);
-#else
-    ret = vk->GetSemaphoreFdKHR(hwctx->act_dev, &sem_export,
-                                &ext_sem_desc.handle.fd);
-#endif
-    if (ret != VK_SUCCESS) {
-        av_log(ctx, AV_LOG_ERROR, "Failed to export semaphore: %s\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-#ifdef _WIN32
-    dst_int->ext_sem_handle[idx] = ext_sem_desc.handle.win32.handle;
-#endif
-
-    ret = CHECK_CU(cu->cuImportExternalSemaphore(&dst_int->cu_sem[idx],
-                                                 &ext_sem_desc));
-    if (ret < 0) {
-#ifndef _WIN32
-        close(ext_sem_desc.handle.fd);
-#endif
-        return AVERROR_EXTERNAL;
-    }
-
-    return 0;
-}
-
-static int vulkan_export_to_cuda(AVHWFramesContext *hwfc,
-                                 AVBufferRef *cuda_hwfc,
-                                 const AVFrame *frame)
-{
-    int err;
-    VkResult ret;
-    AVVkFrame *dst_f;
-    AVVkFrameInternal *dst_int;
-    AVHWDeviceContext *ctx = hwfc->device_ctx;
-    const int planes = av_pix_fmt_count_planes(hwfc->sw_format);
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format);
-    VulkanDevicePriv *p = ctx->hwctx;
-    AVVulkanDeviceContext *hwctx = &p->p;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-    int nb_images;
-
-    AVHWFramesContext *cuda_fc = (AVHWFramesContext*)cuda_hwfc->data;
-    AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx;
-    AVCUDADeviceContext *cuda_dev = cuda_cu->hwctx;
-    AVCUDADeviceContextInternal *cu_internal = cuda_dev->internal;
-    CudaFunctions *cu = cu_internal->cuda_dl;
-    CUarray_format cufmt = desc->comp[0].depth > 8 ? CU_AD_FORMAT_UNSIGNED_INT16 :
-                                                     CU_AD_FORMAT_UNSIGNED_INT8;
-
-    dst_f = (AVVkFrame *)frame->data[0];
-    dst_int = dst_f->internal;
-
-    if (!dst_int->cuda_fc_ref) {
-        size_t offsets[3] = { 0 };
-
-        dst_int->cuda_fc_ref = av_buffer_ref(cuda_hwfc);
-        if (!dst_int->cuda_fc_ref)
-            return AVERROR(ENOMEM);
-
-        nb_images = ff_vk_count_images(dst_f);
-        for (int i = 0; i < nb_images; i++) {
-            err = export_mem_to_cuda(ctx, cuda_cu, cu, dst_int, i,
-                                     dst_f->mem[i], dst_f->size[i]);
-            if (err < 0)
-                goto fail;
-
-            err = export_sem_to_cuda(ctx, cuda_cu, cu, dst_int, i,
-                                     dst_f->sem[i]);
-            if (err < 0)
-                goto fail;
-        }
-
-        if (nb_images != planes) {
-            for (int i = 0; i < planes; i++) {
-                VkImageSubresource subres = {
-                    .aspectMask = i == 2 ? VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT :
-                                  i == 1 ? VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT :
-                                           VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT
-                };
-                VkSubresourceLayout layout = { 0 };
-                vk->GetImageSubresourceLayout(hwctx->act_dev, dst_f->img[FFMIN(i, nb_images - 1)],
-                                              &subres, &layout);
-                offsets[i] = layout.offset;
-            }
-        }
-
-        for (int i = 0; i < planes; i++) {
-            CUDA_EXTERNAL_MEMORY_MIPMAPPED_ARRAY_DESC tex_desc = {
-                .offset = offsets[i],
-                .arrayDesc = {
-                    .Depth = 0,
-                    .Format = cufmt,
-                    .NumChannels = 1 + ((planes == 2) && i),
-                    .Flags = 0,
-                },
-                .numLevels = 1,
-            };
-            int p_w, p_h;
-
-            get_plane_wh(&p_w, &p_h, hwfc->sw_format, hwfc->width, hwfc->height, i);
-            tex_desc.arrayDesc.Width = p_w;
-            tex_desc.arrayDesc.Height = p_h;
-
-            ret = CHECK_CU(cu->cuExternalMemoryGetMappedMipmappedArray(&dst_int->cu_mma[i],
-                                                                       dst_int->ext_mem[FFMIN(i, nb_images - 1)],
-                                                                       &tex_desc));
-            if (ret < 0) {
-                err = AVERROR_EXTERNAL;
-                goto fail;
-            }
-
-            ret = CHECK_CU(cu->cuMipmappedArrayGetLevel(&dst_int->cu_array[i],
-                                                        dst_int->cu_mma[i], 0));
-            if (ret < 0) {
-                err = AVERROR_EXTERNAL;
-                goto fail;
-            }
-
-        }
-    }
-
-    return 0;
-
-fail:
-    vulkan_free_internal(dst_f);
-    return err;
-}
-
-static int vulkan_transfer_data_from_cuda(AVHWFramesContext *hwfc,
-                                          AVFrame *dst, const AVFrame *src)
-{
-    int err;
-    CUcontext dummy;
-    AVVkFrame *dst_f;
-    AVVkFrameInternal *dst_int;
-    VulkanFramesPriv *fp = hwfc->hwctx;
-    const int planes = av_pix_fmt_count_planes(hwfc->sw_format);
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format);
-
-    AVHWFramesContext *cuda_fc = (AVHWFramesContext*)src->hw_frames_ctx->data;
-    AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx;
-    AVCUDADeviceContext *cuda_dev = cuda_cu->hwctx;
-    AVCUDADeviceContextInternal *cu_internal = cuda_dev->internal;
-    CudaFunctions *cu = cu_internal->cuda_dl;
-    CUDA_EXTERNAL_SEMAPHORE_WAIT_PARAMS s_w_par[AV_NUM_DATA_POINTERS] = { 0 };
-    CUDA_EXTERNAL_SEMAPHORE_SIGNAL_PARAMS s_s_par[AV_NUM_DATA_POINTERS] = { 0 };
-
-    dst_f = (AVVkFrame *)dst->data[0];
-
-    err = prepare_frame(hwfc, &fp->upload_exec, dst_f, PREP_MODE_EXTERNAL_EXPORT);
-    if (err < 0)
-        return err;
-
-    err = CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx));
-    if (err < 0)
-        return err;
-
-    err = vulkan_export_to_cuda(hwfc, src->hw_frames_ctx, dst);
-    if (err < 0) {
-        CHECK_CU(cu->cuCtxPopCurrent(&dummy));
-        return err;
-    }
-
-    dst_int = dst_f->internal;
-
-    for (int i = 0; i < planes; i++) {
-        s_w_par[i].params.fence.value = dst_f->sem_value[i] + 0;
-        s_s_par[i].params.fence.value = dst_f->sem_value[i] + 1;
-    }
-
-    err = CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par,
-                                                     planes, cuda_dev->stream));
-    if (err < 0)
-        goto fail;
-
-    for (int i = 0; i < planes; i++) {
-        CUDA_MEMCPY2D cpy = {
-            .srcMemoryType = CU_MEMORYTYPE_DEVICE,
-            .srcDevice     = (CUdeviceptr)src->data[i],
-            .srcPitch      = src->linesize[i],
-            .srcY          = 0,
-
-            .dstMemoryType = CU_MEMORYTYPE_ARRAY,
-            .dstArray      = dst_int->cu_array[i],
-        };
-
-        int p_w, p_h;
-        get_plane_wh(&p_w, &p_h, hwfc->sw_format, hwfc->width, hwfc->height, i);
-
-        cpy.WidthInBytes = p_w * desc->comp[i].step;
-        cpy.Height = p_h;
-
-        err = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream));
-        if (err < 0)
-            goto fail;
-    }
-
-    err = CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par,
-                                                       planes, cuda_dev->stream));
-    if (err < 0)
-        goto fail;
-
-    for (int i = 0; i < planes; i++)
-        dst_f->sem_value[i]++;
-
-    CHECK_CU(cu->cuCtxPopCurrent(&dummy));
-
-    av_log(hwfc, AV_LOG_VERBOSE, "Transferred CUDA image to Vulkan!\n");
-
-    return err = prepare_frame(hwfc, &fp->upload_exec, dst_f, PREP_MODE_EXTERNAL_IMPORT);
-
-fail:
-    CHECK_CU(cu->cuCtxPopCurrent(&dummy));
-    vulkan_free_internal(dst_f);
-    av_buffer_unref(&dst->buf[0]);
-    return err;
-}
-#endif
-
-static int vulkan_map_to(AVHWFramesContext *hwfc, AVFrame *dst,
-                         const AVFrame *src, int flags)
-{
-    av_unused VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
-
-    switch (src->format) {
-#if CONFIG_LIBDRM
-#if CONFIG_VAAPI
-    case AV_PIX_FMT_VAAPI:
-        if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS)
-            return vulkan_map_from_vaapi(hwfc, dst, src, flags);
-        else
-            return AVERROR(ENOSYS);
-#endif
-    case AV_PIX_FMT_DRM_PRIME:
-        if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS)
-            return vulkan_map_from_drm(hwfc, dst, src, flags);
-        else
-            return AVERROR(ENOSYS);
-#endif
-    default:
-        return AVERROR(ENOSYS);
-    }
-}
-
-#if CONFIG_LIBDRM
-typedef struct VulkanDRMMapping {
-    AVDRMFrameDescriptor drm_desc;
-    AVVkFrame *source;
-} VulkanDRMMapping;
-
-static void vulkan_unmap_to_drm(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap)
-{
-    AVDRMFrameDescriptor *drm_desc = hwmap->priv;
-
-    for (int i = 0; i < drm_desc->nb_objects; i++)
-        close(drm_desc->objects[i].fd);
-
-    av_free(drm_desc);
-}
-
-static inline uint32_t vulkan_fmt_to_drm(VkFormat vkfmt)
-{
-    for (int i = 0; i < FF_ARRAY_ELEMS(vulkan_drm_format_map); i++)
-        if (vulkan_drm_format_map[i].vk_format == vkfmt)
-            return vulkan_drm_format_map[i].drm_fourcc;
-    return DRM_FORMAT_INVALID;
-}
-
-#define MAX_MEMORY_PLANES 4
-static VkImageAspectFlags plane_index_to_aspect(int plane) {
-    if (plane == 0) return VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT;
-    if (plane == 1) return VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT;
-    if (plane == 2) return VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT;
-    if (plane == 3) return VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT;
-
-    av_assert2 (0 && "Invalid plane index");
-    return VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT;
-}
-
-static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst,
-                             const AVFrame *src, int flags)
-{
-    int err = 0;
-    VkResult ret;
-    AVVkFrame *f = (AVVkFrame *)src->data[0];
-    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
-    AVVulkanDeviceContext *hwctx = &p->p;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-    VulkanFramesPriv *fp = hwfc->hwctx;
-    const int planes = av_pix_fmt_count_planes(hwfc->sw_format);
-    VkImageDrmFormatModifierPropertiesEXT drm_mod = {
-        .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
-    };
-    VkSemaphoreWaitInfo wait_info = {
-        .sType          = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
-        .flags          = 0x0,
-        .semaphoreCount = planes,
-    };
-
-    AVDRMFrameDescriptor *drm_desc = av_mallocz(sizeof(*drm_desc));
-    if (!drm_desc)
-        return AVERROR(ENOMEM);
-
-    err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_EXTERNAL_EXPORT);
-    if (err < 0)
-        goto end;
-
-    /* Wait for the operation to finish so we can cleanly export it. */
-    wait_info.pSemaphores = f->sem;
-    wait_info.pValues     = f->sem_value;
-
-    vk->WaitSemaphores(hwctx->act_dev, &wait_info, UINT64_MAX);
-
-    err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, &vulkan_unmap_to_drm, drm_desc);
-    if (err < 0)
-        goto end;
-
-    ret = vk->GetImageDrmFormatModifierPropertiesEXT(hwctx->act_dev, f->img[0],
-                                                     &drm_mod);
-    if (ret != VK_SUCCESS) {
-        av_log(hwfc, AV_LOG_ERROR, "Failed to retrieve DRM format modifier!\n");
-        err = AVERROR_EXTERNAL;
-        goto end;
-    }
-
-    for (int i = 0; (i < planes) && (f->mem[i]); i++) {
-        VkMemoryGetFdInfoKHR export_info = {
-            .sType      = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
-            .memory     = f->mem[i],
-            .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
-        };
-
-        ret = vk->GetMemoryFdKHR(hwctx->act_dev, &export_info,
-                                 &drm_desc->objects[i].fd);
-        if (ret != VK_SUCCESS) {
-            av_log(hwfc, AV_LOG_ERROR, "Unable to export the image as a FD!\n");
-            err = AVERROR_EXTERNAL;
-            goto end;
-        }
-
-        drm_desc->nb_objects++;
-        drm_desc->objects[i].size = f->size[i];
-        drm_desc->objects[i].format_modifier = drm_mod.drmFormatModifier;
-    }
-
-    drm_desc->nb_layers = planes;
-    for (int i = 0; i < drm_desc->nb_layers; i++) {
-        VkFormat plane_vkfmt = av_vkfmt_from_pixfmt(hwfc->sw_format)[i];
-
-        drm_desc->layers[i].format = vulkan_fmt_to_drm(plane_vkfmt);
-        drm_desc->layers[i].nb_planes = fp->drm_format_modifier_properties[i].drmFormatModifierPlaneCount;
-
-        if (drm_desc->layers[i].nb_planes > MAX_MEMORY_PLANES) {
-            av_log(hwfc, AV_LOG_ERROR, "Too many memory planes for DRM format!\n");
-            err = AVERROR_EXTERNAL;
-            goto end;
-        }
-
-        for (int j = 0; j < drm_desc->layers[i].nb_planes; j++) {
-            VkSubresourceLayout layout;
-            VkImageSubresource sub = {
-                .aspectMask = plane_index_to_aspect(j),
-            };
-
-            drm_desc->layers[i].planes[j].object_index = FFMIN(i, drm_desc->nb_objects - 1);
-
-            vk->GetImageSubresourceLayout(hwctx->act_dev, f->img[i], &sub, &layout);
-            drm_desc->layers[i].planes[j].offset = layout.offset;
-            drm_desc->layers[i].planes[j].pitch  = layout.rowPitch;
-        }
-
-        if (drm_desc->layers[i].format == DRM_FORMAT_INVALID) {
-            av_log(hwfc, AV_LOG_ERROR, "Cannot map to DRM layer, unsupported!\n");
-            err = AVERROR_PATCHWELCOME;
-            goto end;
-        }
-
-
-        if (f->tiling == VK_IMAGE_TILING_OPTIMAL)
-            continue;
-
-    }
-
-    dst->width   = src->width;
-    dst->height  = src->height;
-    dst->data[0] = (uint8_t *)drm_desc;
-
-    av_log(hwfc, AV_LOG_VERBOSE, "Mapped AVVkFrame to a DRM object!\n");
-
-    return 0;
-
-end:
-    av_free(drm_desc);
-    return err;
-}
-
-#if CONFIG_VAAPI
-static int vulkan_map_to_vaapi(AVHWFramesContext *hwfc, AVFrame *dst,
-                               const AVFrame *src, int flags)
-{
-    int err;
-    AVFrame *tmp = av_frame_alloc();
-    if (!tmp)
-        return AVERROR(ENOMEM);
-
-    tmp->format = AV_PIX_FMT_DRM_PRIME;
-
-    err = vulkan_map_to_drm(hwfc, tmp, src, flags);
-    if (err < 0)
-        goto fail;
-
-    err = av_hwframe_map(dst, tmp, flags);
-    if (err < 0)
-        goto fail;
-
-    err = ff_hwframe_map_replace(dst, src);
-
-fail:
-    av_frame_free(&tmp);
-    return err;
-}
-#endif
-#endif
-
-static int vulkan_map_from(AVHWFramesContext *hwfc, AVFrame *dst,
-                           const AVFrame *src, int flags)
-{
-    av_unused VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
-
-    switch (dst->format) {
-#if CONFIG_LIBDRM
-    case AV_PIX_FMT_DRM_PRIME:
-        if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS)
-            return vulkan_map_to_drm(hwfc, dst, src, flags);
-        else
-            return AVERROR(ENOSYS);
-#if CONFIG_VAAPI
-    case AV_PIX_FMT_VAAPI:
-        if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS)
-            return vulkan_map_to_vaapi(hwfc, dst, src, flags);
-        else
-            return AVERROR(ENOSYS);
-#endif
-#endif
-    default:
-        break;
-    }
-    return AVERROR(ENOSYS);
-}
-
-static int copy_buffer_data(AVHWFramesContext *hwfc, AVBufferRef *buf,
-                            AVFrame *swf, VkBufferImageCopy *region,
-                            int planes, int upload)
-{
-    VkResult ret;
-    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-    AVVulkanDeviceContext *hwctx = &p->p;
-
-    FFVkBuffer *vkbuf = (FFVkBuffer *)buf->data;
-
-    const VkMappedMemoryRange flush_info = {
-        .sType  = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
-        .memory = vkbuf->mem,
-        .size   = VK_WHOLE_SIZE,
-    };
-
-    if (!upload && !(vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
-        ret = vk->InvalidateMappedMemoryRanges(hwctx->act_dev, 1,
-                                               &flush_info);
-        if (ret != VK_SUCCESS) {
-            av_log(hwfc, AV_LOG_ERROR, "Failed to invalidate buffer data: %s\n",
-                   ff_vk_ret2str(ret));
-            return AVERROR_EXTERNAL;
-        }
-    }
-
-    if (upload) {
-        for (int i = 0; i < planes; i++)
-            av_image_copy_plane(vkbuf->mapped_mem + region[i].bufferOffset,
-                                region[i].bufferRowLength,
-                                swf->data[i],
-                                swf->linesize[i],
-                                swf->linesize[i],
-                                region[i].imageExtent.height);
-    } else {
-        for (int i = 0; i < planes; i++)
-            av_image_copy_plane(swf->data[i],
-                                swf->linesize[i],
-                                vkbuf->mapped_mem + region[i].bufferOffset,
-                                region[i].bufferRowLength,
-                                swf->linesize[i],
-                                region[i].imageExtent.height);
-    }
-
-    if (upload && !(vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
-        ret = vk->FlushMappedMemoryRanges(hwctx->act_dev, 1,
-                                          &flush_info);
-        if (ret != VK_SUCCESS) {
-            av_log(hwfc, AV_LOG_ERROR, "Failed to flush buffer data: %s\n",
-                   ff_vk_ret2str(ret));
-            return AVERROR_EXTERNAL;
-        }
-    }
-
-    return 0;
-}
-
-static int get_plane_buf(AVHWFramesContext *hwfc, AVBufferRef **dst,
-                         AVFrame *swf, VkBufferImageCopy *region, int upload)
-{
-    int err;
-    uint32_t p_w, p_h;
-    VulkanFramesPriv *fp = hwfc->hwctx;
-    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
-    const int planes = av_pix_fmt_count_planes(swf->format);
-    VkBufferUsageFlags buf_usage = upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
-                                            VK_BUFFER_USAGE_TRANSFER_DST_BIT;
-
-    size_t buf_offset = 0;
-    for (int i = 0; i < planes; i++) {
-        get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
-
-        region[i] = (VkBufferImageCopy) {
-            .bufferOffset = buf_offset,
-            .bufferRowLength = FFALIGN(swf->linesize[i],
-                                       p->props.properties.limits.optimalBufferCopyRowPitchAlignment),
-            .bufferImageHeight = p_h,
-            .imageSubresource.layerCount = 1,
-            .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
-            /* Rest of the fields adjusted/filled in later */
-        };
-
-        buf_offset += FFALIGN(p_h*region[i].bufferRowLength,
-                              p->props.properties.limits.optimalBufferCopyOffsetAlignment);
-    }
-
-    err = ff_vk_get_pooled_buffer(&p->vkctx, &fp->tmp, dst, buf_usage,
-                                  NULL, buf_offset,
-                                  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
-                                  VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
-    if (err < 0)
-        return err;
-
-    return 0;
-}
-
-static int host_map_frame(AVHWFramesContext *hwfc, AVBufferRef **dst, int *nb_bufs,
-                          AVFrame *swf, VkBufferImageCopy *region, int upload)
-{
-    int err;
-    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
-
-    int nb_src_bufs;
-    const int planes = av_pix_fmt_count_planes(swf->format);
-    VkBufferUsageFlags buf_usage = upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
-                                            VK_BUFFER_USAGE_TRANSFER_DST_BIT;
-
-    /* We can't host map images with negative strides */
-    for (int i = 0; i < planes; i++)
-        if (swf->linesize[i] < 0)
-            return AVERROR(EINVAL);
-
-    /* Count the number of buffers in the software frame */
-    nb_src_bufs = 0;
-    while (swf->buf[nb_src_bufs])
-        nb_src_bufs++;
-
-    /* Single buffer contains all planes */
-    if (nb_src_bufs == 1) {
-        err = ff_vk_host_map_buffer(&p->vkctx, &dst[0],
-                                    swf->data[0], swf->buf[0],
-                                    buf_usage);
-        if (err < 0)
-            return err;
-        (*nb_bufs)++;
-
-        for (int i = 0; i < planes; i++)
-            region[i].bufferOffset = ((FFVkBuffer *)dst[0]->data)->virtual_offset +
-                                     swf->data[i] - swf->data[0];
-    } else if (nb_src_bufs == planes) { /* One buffer per plane */
-        for (int i = 0; i < planes; i++) {
-            err = ff_vk_host_map_buffer(&p->vkctx, &dst[i],
-                                        swf->data[i], swf->buf[i],
-                                        buf_usage);
-            if (err < 0)
-                goto fail;
-            (*nb_bufs)++;
-
-            region[i].bufferOffset = ((FFVkBuffer *)dst[i]->data)->virtual_offset;
-        }
-    } else {
-        /* Weird layout (3 planes, 2 buffers), patch welcome, fallback to copy */
-        return AVERROR_PATCHWELCOME;
-    }
-
-    return 0;
-
-fail:
-    for (int i = 0; i < (*nb_bufs); i++)
-        av_buffer_unref(&dst[i]);
-    return err;
-}
-
-static int vulkan_transfer_host(AVHWFramesContext *hwfc, AVFrame *hwf,
-                                AVFrame *swf, int upload)
-{
-    VulkanFramesPriv *fp = hwfc->hwctx;
-    AVVulkanFramesContext *hwfc_vk = &fp->p;
-    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);
-
-    VkSemaphoreWaitInfo sem_wait;
-    VkHostImageLayoutTransitionInfoEXT layout_ch_info[AV_NUM_DATA_POINTERS];
-    int nb_layout_ch = 0;
-
-    hwfc_vk->lock_frame(hwfc, hwf_vk);
-
-    for (int i = 0; i < nb_images; i++) {
-        int compat = 0;
-        for (int j = 0; j < p->vkctx.host_image_props.copySrcLayoutCount; j++) {
-            if (hwf_vk->layout[i] == p->vkctx.host_image_props.pCopySrcLayouts[j]) {
-                compat = 1;
-                break;
-            }
-        }
-        if (compat)
-            continue;
-
-        layout_ch_info[nb_layout_ch] = (VkHostImageLayoutTransitionInfoEXT) {
-            .sType = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,
-            .image = hwf_vk->img[i],
-            .oldLayout = hwf_vk->layout[i],
-            .newLayout = VK_IMAGE_LAYOUT_GENERAL,
-            .subresourceRange = {
-                .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
-                .levelCount = 1,
-                .layerCount = 1,
-            },
-        };
-
-        hwf_vk->layout[i] = layout_ch_info[nb_layout_ch].newLayout;
-        nb_layout_ch++;
-    }
-
-    sem_wait = (VkSemaphoreWaitInfo) {
-        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
-        .pSemaphores = hwf_vk->sem,
-        .pValues = hwf_vk->sem_value,
-        .semaphoreCount = nb_images,
-    };
-
-    vk->WaitSemaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
-
-    if (nb_layout_ch)
-        vk->TransitionImageLayoutEXT(hwctx->act_dev,
-                                     nb_layout_ch, layout_ch_info);
-
-    if (upload) {
-        VkMemoryToImageCopyEXT region_info = {
-            .sType = VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT,
-            .imageSubresource = {
-                .layerCount = 1,
-            },
-        };
-        VkCopyMemoryToImageInfoEXT copy_info = {
-            .sType = VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO_EXT,
-            .flags = VK_HOST_IMAGE_COPY_MEMCPY_EXT,
-            .regionCount = 1,
-            .pRegions = &region_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, &copy_info);
-        }
-    } else {
-        VkImageToMemoryCopyEXT region_info = {
-            .sType = VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT,
-            .imageSubresource = {
-                .layerCount = 1,
-            },
-        };
-        VkCopyImageToMemoryInfoEXT copy_info = {
-            .sType = VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO_EXT,
-            .flags = VK_HOST_IMAGE_COPY_MEMCPY_EXT,
-            .regionCount = 1,
-            .pRegions = &region_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, &copy_info);
-        }
-    }
-
-    hwfc_vk->unlock_frame(hwfc, hwf_vk);
-
-    return 0;
-}
-
-static int vulkan_transfer_frame(AVHWFramesContext *hwfc,
-                                 AVFrame *swf, AVFrame *hwf,
-                                 int upload)
-{
-    int err;
-    VulkanFramesPriv *fp = hwfc->hwctx;
-    AVVulkanFramesContext *hwctx = &fp->p;
-    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
-    FFVulkanFunctions *vk = &p->vkctx.vkfn;
-
-    int host_mapped = 0;
-
-    AVVkFrame *hwf_vk = (AVVkFrame *)hwf->data[0];
-    VkBufferImageCopy region[AV_NUM_DATA_POINTERS]; // always one per plane
-
-    const int planes = av_pix_fmt_count_planes(swf->format);
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(swf->format);
-    const int nb_images = ff_vk_count_images(hwf_vk);
-
-    VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS];
-    int nb_img_bar = 0;
-
-    AVBufferRef *bufs[AV_NUM_DATA_POINTERS];
-    int nb_bufs = 0;
-
-    VkCommandBuffer cmd_buf;
-    FFVkExecContext *exec;
-
-    /* Sanity checking */
-    if ((swf->format != AV_PIX_FMT_NONE && !av_vkfmt_from_pixfmt(swf->format))) {
-        av_log(hwfc, AV_LOG_ERROR, "Unsupported software frame pixel format!\n");
-        return AVERROR(EINVAL);
-    }
-
-    if (swf->width > hwfc->width || swf->height > hwfc->height)
-        return AVERROR(EINVAL);
-
-    if (hwctx->usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT)
-        return vulkan_transfer_host(hwfc, hwf, swf, upload);
-
-    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);
-
-        /* Buffer region for this plane */
-        region[i] = (VkBufferImageCopy) {
-            .bufferOffset = 0,
-            .bufferRowLength = swf->linesize[i],
-            .bufferImageHeight = p_h,
-            .imageSubresource.layerCount = 1,
-            .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
-            /* Rest of the fields adjusted/filled in later */
-        };
-    }
-
-    /* Setup buffers first */
-    if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY && !p->avoid_host_import) {
-        err = host_map_frame(hwfc, bufs, &nb_bufs, swf, region, upload);
-        if (err >= 0)
-            host_mapped = 1;
-    }
-
-    if (!host_mapped) {
-        err = get_plane_buf(hwfc, &bufs[0], swf, region, upload);
-        if (err < 0)
-            goto end;
-        nb_bufs = 1;
-
-        if (upload) {
-            err = copy_buffer_data(hwfc, bufs[0], swf, region, planes, 1);
-            if (err < 0)
-                goto end;
-        }
-    }
-
-    exec = ff_vk_exec_get(&p->vkctx, &fp->upload_exec);
-    cmd_buf = exec->buf;
-
-    ff_vk_exec_start(&p->vkctx, exec);
-
-    /* Prep destination Vulkan frame */
-    err = ff_vk_exec_add_dep_frame(&p->vkctx, exec, hwf,
-                                   VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                   VK_PIPELINE_STAGE_2_TRANSFER_BIT);
-    if (err < 0)
-        goto end;
-
-    /* No need to declare buf deps for synchronous transfers (downloads) */
-    if (upload) {
-        /* Add the software frame backing the buffers if we're host mapping */
-        if (host_mapped) {
-            err = ff_vk_exec_add_dep_sw_frame(&p->vkctx, exec, swf);
-            if (err < 0) {
-                ff_vk_exec_discard_deps(&p->vkctx, exec);
-                goto end;
-            }
-        }
-
-        /* Add the buffers as a dependency */
-        err = ff_vk_exec_add_dep_buf(&p->vkctx, exec, bufs, nb_bufs, 1);
-        if (err < 0) {
-            ff_vk_exec_discard_deps(&p->vkctx, exec);
-            goto end;
-        }
-    }
-
-    ff_vk_frame_barrier(&p->vkctx, exec, hwf, img_bar, &nb_img_bar,
-                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                        VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,
-                        upload ? VK_ACCESS_TRANSFER_WRITE_BIT :
-                                 VK_ACCESS_TRANSFER_READ_BIT,
-                        upload ? VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL :
-                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
-                        p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0]);
-
-    vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-            .pImageMemoryBarriers = img_bar,
-            .imageMemoryBarrierCount = nb_img_bar,
-    });
-
-    for (int i = 0; i < planes; i++) {
-        int buf_idx = FFMIN(i, (nb_bufs - 1));
-        int img_idx = FFMIN(i, (nb_images - 1));
-        FFVkBuffer *vkbuf = (FFVkBuffer *)bufs[buf_idx]->data;
-
-        uint32_t orig_stride = region[i].bufferRowLength;
-        region[i].bufferRowLength /= desc->comp[i].step;
-        region[i].imageSubresource.aspectMask = ff_vk_aspect_flag(hwf, i);
-
-        if (upload)
-            vk->CmdCopyBufferToImage(cmd_buf, vkbuf->buf,
-                                     hwf_vk->img[img_idx],
-                                     img_bar[img_idx].newLayout,
-                                     1, &region[i]);
-        else
-            vk->CmdCopyImageToBuffer(cmd_buf, hwf_vk->img[img_idx],
-                                     img_bar[img_idx].newLayout,
-                                     vkbuf->buf,
-                                     1, &region[i]);
-
-        region[i].bufferRowLength = orig_stride;
-    }
-
-    err = ff_vk_exec_submit(&p->vkctx, exec);
-    if (err < 0) {
-        ff_vk_exec_discard_deps(&p->vkctx, exec);
-    } else if (!upload) {
-        ff_vk_exec_wait(&p->vkctx, exec);
-        if (!host_mapped)
-            err = copy_buffer_data(hwfc, bufs[0], swf, region, planes, 0);
-    }
-
-end:
-    for (int i = 0; i < nb_bufs; i++)
-        av_buffer_unref(&bufs[i]);
-
-    return err;
-}
-
-static int vulkan_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst,
-                                   const AVFrame *src)
-{
-    av_unused VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
-
-    switch (src->format) {
-#if CONFIG_CUDA
-    case AV_PIX_FMT_CUDA:
-#ifdef _WIN32
-        if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) &&
-            (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM))
-#else
-        if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) &&
-            (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_SEM))
-#endif
-            return vulkan_transfer_data_from_cuda(hwfc, dst, src);
-#endif
-    default:
-        if (src->hw_frames_ctx)
-            return AVERROR(ENOSYS);
-        else
-            return vulkan_transfer_frame(hwfc, (AVFrame *)src, dst, 1);
-    }
-}
-
-#if CONFIG_CUDA
-static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst,
-                                        const AVFrame *src)
-{
-    int err;
-    CUcontext dummy;
-    AVVkFrame *dst_f;
-    AVVkFrameInternal *dst_int;
-    VulkanFramesPriv *fp = hwfc->hwctx;
-    const int planes = av_pix_fmt_count_planes(hwfc->sw_format);
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format);
-    int nb_images;
-
-    AVHWFramesContext *cuda_fc = (AVHWFramesContext*)dst->hw_frames_ctx->data;
-    AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx;
-    AVCUDADeviceContext *cuda_dev = cuda_cu->hwctx;
-    AVCUDADeviceContextInternal *cu_internal = cuda_dev->internal;
-    CudaFunctions *cu = cu_internal->cuda_dl;
-    CUDA_EXTERNAL_SEMAPHORE_WAIT_PARAMS s_w_par[AV_NUM_DATA_POINTERS] = { 0 };
-    CUDA_EXTERNAL_SEMAPHORE_SIGNAL_PARAMS s_s_par[AV_NUM_DATA_POINTERS] = { 0 };
-
-    dst_f = (AVVkFrame *)src->data[0];
-    nb_images = ff_vk_count_images(dst_f);
-
-    err = prepare_frame(hwfc, &fp->upload_exec, dst_f, PREP_MODE_EXTERNAL_EXPORT);
-    if (err < 0)
-        return err;
-
-    err = CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx));
-    if (err < 0)
-        return err;
-
-    err = vulkan_export_to_cuda(hwfc, dst->hw_frames_ctx, src);
-    if (err < 0) {
-        CHECK_CU(cu->cuCtxPopCurrent(&dummy));
-        return err;
-    }
-
-    dst_int = dst_f->internal;
-
-    for (int i = 0; i < planes; i++) {
-        s_w_par[i].params.fence.value = dst_f->sem_value[i] + 0;
-        s_s_par[i].params.fence.value = dst_f->sem_value[i] + 1;
-    }
-
-    err = CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par,
-                                                     nb_images, cuda_dev->stream));
-    if (err < 0)
-        goto fail;
-
-    for (int i = 0; i < planes; i++) {
-        CUDA_MEMCPY2D cpy = {
-            .dstMemoryType = CU_MEMORYTYPE_DEVICE,
-            .dstDevice     = (CUdeviceptr)dst->data[i],
-            .dstPitch      = dst->linesize[i],
-            .dstY          = 0,
-
-            .srcMemoryType = CU_MEMORYTYPE_ARRAY,
-            .srcArray      = dst_int->cu_array[i],
-        };
-
-        int w, h;
-        get_plane_wh(&w, &h, hwfc->sw_format, hwfc->width, hwfc->height, i);
-
-        cpy.WidthInBytes = w * desc->comp[i].step;
-        cpy.Height = h;
-
-        err = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream));
-        if (err < 0)
-            goto fail;
-    }
-
-    err = CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par,
-                                                       nb_images, cuda_dev->stream));
-    if (err < 0)
-        goto fail;
-
-    for (int i = 0; i < planes; i++)
-        dst_f->sem_value[i]++;
-
-    CHECK_CU(cu->cuCtxPopCurrent(&dummy));
-
-    av_log(hwfc, AV_LOG_VERBOSE, "Transferred Vulkan image to CUDA!\n");
-
-    return prepare_frame(hwfc, &fp->upload_exec, dst_f, PREP_MODE_EXTERNAL_IMPORT);
-
-fail:
-    CHECK_CU(cu->cuCtxPopCurrent(&dummy));
-    vulkan_free_internal(dst_f);
-    av_buffer_unref(&dst->buf[0]);
-    return err;
-}
-#endif
-
-static int vulkan_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst,
-                                     const AVFrame *src)
-{
-    av_unused VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
-
-    switch (dst->format) {
-#if CONFIG_CUDA
-    case AV_PIX_FMT_CUDA:
-#ifdef _WIN32
-        if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) &&
-            (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM))
-#else
-        if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) &&
-            (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_SEM))
-#endif
-            return vulkan_transfer_data_to_cuda(hwfc, dst, src);
-#endif
-    default:
-        if (dst->hw_frames_ctx)
-            return AVERROR(ENOSYS);
-        else
-            return vulkan_transfer_frame(hwfc, dst, (AVFrame *)src, 0);
-    }
-}
-
-static int vulkan_frames_derive_to(AVHWFramesContext *dst_fc,
-                                   AVHWFramesContext *src_fc, int flags)
-{
-    return vulkan_frames_init(dst_fc);
-}
-
-AVVkFrame *av_vk_frame_alloc(void)
-{
-    int err;
-    AVVkFrame *f = av_mallocz(sizeof(AVVkFrame));
-    if (!f)
-        return NULL;
-
-    f->internal = av_mallocz(sizeof(*f->internal));
-    if (!f->internal) {
-        av_free(f);
-        return NULL;
-    }
-
-    err = pthread_mutex_init(&f->internal->update_mutex, NULL);
-    if (err != 0) {
-        av_free(f->internal);
-        av_free(f);
-        return NULL;
-    }
-
-    return f;
-}
-
-const HWContextType ff_hwcontext_type_vulkan = {
-    .type                   = AV_HWDEVICE_TYPE_VULKAN,
-    .name                   = "Vulkan",
-
-    .device_hwctx_size      = sizeof(VulkanDevicePriv),
-    .frames_hwctx_size      = sizeof(VulkanFramesPriv),
-
-    .device_init            = &vulkan_device_init,
-    .device_uninit          = &vulkan_device_uninit,
-    .device_create          = &vulkan_device_create,
-    .device_derive          = &vulkan_device_derive,
-
-    .frames_get_constraints = &vulkan_frames_get_constraints,
-    .frames_init            = vulkan_frames_init,
-    .frames_get_buffer      = vulkan_get_buffer,
-    .frames_uninit          = vulkan_frames_uninit,
-
-    .transfer_get_formats   = vulkan_transfer_get_formats,
-    .transfer_data_to       = vulkan_transfer_data_to,
-    .transfer_data_from     = vulkan_transfer_data_from,
-
-    .map_to                 = vulkan_map_to,
-    .map_from               = vulkan_map_from,
-    .frames_derive_to       = &vulkan_frames_derive_to,
-
-    .pix_fmts = (const enum AVPixelFormat []) {
-        AV_PIX_FMT_VULKAN,
-        AV_PIX_FMT_NONE
-    },
-};
-- 
2.49.1


From 93ee15398bfca4b5e884145d2a1673a632196ad3 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:15:26 +0000
Subject: [PATCH 040/118] Changing vulkan file directory

---
 libavutil/vulkan/hwcontext_vulkan.c | 4790 +++++++++++++++++++++++++++
 1 file changed, 4790 insertions(+)
 create mode 100644 libavutil/vulkan/hwcontext_vulkan.c

diff --git a/libavutil/vulkan/hwcontext_vulkan.c b/libavutil/vulkan/hwcontext_vulkan.c
new file mode 100644
index 0000000000..858bbaba12
--- /dev/null
+++ b/libavutil/vulkan/hwcontext_vulkan.c
@@ -0,0 +1,4790 @@
+/*
+ * Copyright (c) Lynne
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define VK_NO_PROTOTYPES
+#define VK_ENABLE_BETA_EXTENSIONS
+
+#ifdef _WIN32
+#include <windows.h> /* Included to prevent conflicts with CreateSemaphore */
+#include <versionhelpers.h>
+#include "compat/w32dlfcn.h"
+#else
+#include <dlfcn.h>
+#include <unistd.h>
+#endif
+
+#include "libavutil/thread.h"
+
+#include "libavutil/config.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/avstring.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/hwcontext.h"
+#include "libavutil/hwcontext_internal.h"
+#include "hwcontext_vulkan.h"
+#include "libavutil/mem.h"
+
+#include "vulkan.h"
+#include "vulkan_loader.h"
+
+#if CONFIG_VAAPI
+#include "hwcontext_vaapi.h"
+#endif
+
+#if CONFIG_LIBDRM
+#if CONFIG_VAAPI
+#include <va/va_drmcommon.h>
+#endif
+#ifdef __linux__
+#include <sys/sysmacros.h>
+#endif
+#include <sys/stat.h>
+#include <xf86drm.h>
+#include <drm_fourcc.h>
+#include "hwcontext_drm.h"
+#endif
+
+#if HAVE_LINUX_DMA_BUF_H
+#include <sys/ioctl.h>
+#include <linux/dma-buf.h>
+#endif
+
+#if CONFIG_CUDA
+#include "hwcontext_cuda_internal.h"
+#include "cuda_check.h"
+#define CHECK_CU(x) FF_CUDA_CHECK_DL(cuda_cu, cu, x)
+#endif
+
+typedef struct VulkanDeviceFeatures {
+    VkPhysicalDeviceFeatures2 device;
+
+    VkPhysicalDeviceVulkan11Features vulkan_1_1;
+    VkPhysicalDeviceVulkan12Features vulkan_1_2;
+    VkPhysicalDeviceVulkan13Features vulkan_1_3;
+    VkPhysicalDeviceTimelineSemaphoreFeatures timeline_semaphore;
+    VkPhysicalDeviceShaderSubgroupRotateFeaturesKHR subgroup_rotate;
+    VkPhysicalDeviceHostImageCopyFeaturesEXT host_image_copy;
+
+#ifdef VK_KHR_shader_expect_assume
+    VkPhysicalDeviceShaderExpectAssumeFeaturesKHR expect_assume;
+#endif
+
+    VkPhysicalDeviceVideoMaintenance1FeaturesKHR video_maintenance_1;
+#ifdef VK_KHR_video_maintenance2
+    VkPhysicalDeviceVideoMaintenance2FeaturesKHR video_maintenance_2;
+#endif
+#ifdef VK_KHR_video_decode_vp9
+    VkPhysicalDeviceVideoDecodeVP9FeaturesKHR vp9_decode;
+#endif
+#ifdef VK_KHR_video_encode_av1
+    VkPhysicalDeviceVideoEncodeAV1FeaturesKHR av1_encode;
+#endif
+
+    VkPhysicalDeviceShaderObjectFeaturesEXT shader_object;
+    VkPhysicalDeviceCooperativeMatrixFeaturesKHR cooperative_matrix;
+    VkPhysicalDeviceDescriptorBufferFeaturesEXT descriptor_buffer;
+    VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float;
+
+#ifdef VK_KHR_shader_relaxed_extended_instruction
+    VkPhysicalDeviceShaderRelaxedExtendedInstructionFeaturesKHR relaxed_extended_instruction;
+#endif
+} VulkanDeviceFeatures;
+
+typedef struct VulkanDevicePriv {
+    /**
+     * The public AVVulkanDeviceContext. See hwcontext_vulkan.h for it.
+     */
+    AVVulkanDeviceContext p;
+
+    /* Vulkan library and loader functions */
+    void *libvulkan;
+
+    FFVulkanContext    vkctx;
+    AVVulkanDeviceQueueFamily *compute_qf;
+    AVVulkanDeviceQueueFamily *transfer_qf;
+
+    /* Properties */
+    VkPhysicalDeviceProperties2 props;
+    VkPhysicalDeviceMemoryProperties mprops;
+    VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops;
+    VkPhysicalDeviceDriverProperties dprops;
+
+    /* Opaque FD external semaphore properties */
+    VkExternalSemaphoreProperties ext_sem_props_opaque;
+
+    /* Enabled features */
+    VulkanDeviceFeatures feats;
+
+    /* Queues */
+    pthread_mutex_t **qf_mutex;
+    uint32_t nb_tot_qfs;
+    uint32_t img_qfs[64];
+    uint32_t nb_img_qfs;
+
+    /* Debug callback */
+    VkDebugUtilsMessengerEXT debug_ctx;
+
+    /* Settings */
+    int use_linear_images;
+
+    /* Option to allocate all image planes in a single allocation */
+    int contiguous_planes;
+
+    /* Disable multiplane images */
+    int disable_multiplane;
+
+    /* Disable host image transfer */
+    int disable_host_transfer;
+
+    /* Prefer memcpy over dynamic host pointer imports */
+    int avoid_host_import;
+
+    /* Maximum queues */
+    int limit_queues;
+} VulkanDevicePriv;
+
+typedef struct VulkanFramesPriv {
+    /**
+     * The public AVVulkanFramesContext. See hwcontext_vulkan.h for it.
+     */
+    AVVulkanFramesContext p;
+
+    /* Image conversions */
+    FFVkExecPool compute_exec;
+
+    /* Image transfers */
+    FFVkExecPool upload_exec;
+    FFVkExecPool download_exec;
+
+    /* Temporary buffer pools */
+    AVBufferPool *tmp;
+
+    /* Modifier info list to free at uninit */
+    VkImageDrmFormatModifierListCreateInfoEXT *modifier_info;
+
+    /* Properties for DRM modifier for each plane in the image */
+    VkDrmFormatModifierPropertiesEXT drm_format_modifier_properties[5];
+} VulkanFramesPriv;
+
+typedef struct AVVkFrameInternal {
+    pthread_mutex_t update_mutex;
+
+#if CONFIG_CUDA
+    /* Importing external memory into cuda is really expensive so we keep the
+     * memory imported all the time */
+    AVBufferRef *cuda_fc_ref; /* Need to keep it around for uninit */
+    CUexternalMemory ext_mem[AV_NUM_DATA_POINTERS];
+    CUmipmappedArray cu_mma[AV_NUM_DATA_POINTERS];
+    CUarray cu_array[AV_NUM_DATA_POINTERS];
+    CUexternalSemaphore cu_sem[AV_NUM_DATA_POINTERS];
+#ifdef _WIN32
+    HANDLE ext_mem_handle[AV_NUM_DATA_POINTERS];
+    HANDLE ext_sem_handle[AV_NUM_DATA_POINTERS];
+#endif
+#endif
+} AVVkFrameInternal;
+
+/* Initialize all structs in VulkanDeviceFeatures */
+static void device_features_init(AVHWDeviceContext *ctx, VulkanDeviceFeatures *feats)
+{
+    VulkanDevicePriv *p = ctx->hwctx;
+    FFVulkanContext *s = &p->vkctx;
+
+    feats->device = (VkPhysicalDeviceFeatures2) {
+        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
+    };
+
+    FF_VK_STRUCT_EXT(s, &feats->device, &feats->vulkan_1_1, FF_VK_EXT_NO_FLAG,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES);
+    FF_VK_STRUCT_EXT(s, &feats->device, &feats->vulkan_1_2, FF_VK_EXT_NO_FLAG,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES);
+    FF_VK_STRUCT_EXT(s, &feats->device, &feats->vulkan_1_3, FF_VK_EXT_NO_FLAG,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES);
+
+    FF_VK_STRUCT_EXT(s, &feats->device, &feats->timeline_semaphore, FF_VK_EXT_PORTABILITY_SUBSET,
+                     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,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES_KHR);
+#endif
+
+    FF_VK_STRUCT_EXT(s, &feats->device, &feats->video_maintenance_1, FF_VK_EXT_VIDEO_MAINTENANCE_1,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR);
+#ifdef VK_KHR_video_maintenance2
+    FF_VK_STRUCT_EXT(s, &feats->device, &feats->video_maintenance_2, FF_VK_EXT_VIDEO_MAINTENANCE_2,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_2_FEATURES_KHR);
+#endif
+#ifdef VK_KHR_video_decode_vp9
+    FF_VK_STRUCT_EXT(s, &feats->device, &feats->vp9_decode, FF_VK_EXT_VIDEO_DECODE_VP9,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_DECODE_VP9_FEATURES_KHR);
+#endif
+#ifdef VK_KHR_video_encode_av1
+    FF_VK_STRUCT_EXT(s, &feats->device, &feats->av1_encode, FF_VK_EXT_VIDEO_ENCODE_AV1,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_AV1_FEATURES_KHR);
+#endif
+
+    FF_VK_STRUCT_EXT(s, &feats->device, &feats->shader_object, FF_VK_EXT_SHADER_OBJECT,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT);
+    FF_VK_STRUCT_EXT(s, &feats->device, &feats->cooperative_matrix, FF_VK_EXT_COOP_MATRIX,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR);
+    FF_VK_STRUCT_EXT(s, &feats->device, &feats->descriptor_buffer, FF_VK_EXT_DESCRIPTOR_BUFFER,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT);
+    FF_VK_STRUCT_EXT(s, &feats->device, &feats->atomic_float, FF_VK_EXT_ATOMIC_FLOAT,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT);
+
+#ifdef VK_KHR_shader_relaxed_extended_instruction
+    FF_VK_STRUCT_EXT(s, &feats->device, &feats->relaxed_extended_instruction, FF_VK_EXT_RELAXED_EXTENDED_INSTR,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_RELAXED_EXTENDED_INSTRUCTION_FEATURES_KHR);
+#endif
+}
+
+/* Copy all needed device features */
+static void device_features_copy_needed(VulkanDeviceFeatures *dst, VulkanDeviceFeatures *src)
+{
+#define COPY_VAL(VAL)        \
+    do {                     \
+        dst->VAL = src->VAL; \
+    } while (0)              \
+
+    COPY_VAL(device.features.shaderImageGatherExtended);
+    COPY_VAL(device.features.shaderStorageImageReadWithoutFormat);
+    COPY_VAL(device.features.shaderStorageImageWriteWithoutFormat);
+    COPY_VAL(device.features.fragmentStoresAndAtomics);
+    COPY_VAL(device.features.vertexPipelineStoresAndAtomics);
+    COPY_VAL(device.features.shaderInt64);
+    COPY_VAL(device.features.shaderInt16);
+    COPY_VAL(device.features.shaderFloat64);
+    COPY_VAL(device.features.shaderStorageImageReadWithoutFormat);
+    COPY_VAL(device.features.shaderStorageImageWriteWithoutFormat);
+
+    COPY_VAL(vulkan_1_1.samplerYcbcrConversion);
+    COPY_VAL(vulkan_1_1.storagePushConstant16);
+    COPY_VAL(vulkan_1_1.storageBuffer16BitAccess);
+    COPY_VAL(vulkan_1_1.uniformAndStorageBuffer16BitAccess);
+
+    COPY_VAL(vulkan_1_2.timelineSemaphore);
+    COPY_VAL(vulkan_1_2.scalarBlockLayout);
+    COPY_VAL(vulkan_1_2.bufferDeviceAddress);
+    COPY_VAL(vulkan_1_2.hostQueryReset);
+    COPY_VAL(vulkan_1_2.storagePushConstant8);
+    COPY_VAL(vulkan_1_2.shaderInt8);
+    COPY_VAL(vulkan_1_2.storageBuffer8BitAccess);
+    COPY_VAL(vulkan_1_2.uniformAndStorageBuffer8BitAccess);
+    COPY_VAL(vulkan_1_2.shaderFloat16);
+    COPY_VAL(vulkan_1_2.shaderBufferInt64Atomics);
+    COPY_VAL(vulkan_1_2.shaderSharedInt64Atomics);
+    COPY_VAL(vulkan_1_2.vulkanMemoryModel);
+    COPY_VAL(vulkan_1_2.vulkanMemoryModelDeviceScope);
+    COPY_VAL(vulkan_1_2.uniformBufferStandardLayout);
+
+    COPY_VAL(vulkan_1_3.dynamicRendering);
+    COPY_VAL(vulkan_1_3.maintenance4);
+    COPY_VAL(vulkan_1_3.synchronization2);
+    COPY_VAL(vulkan_1_3.computeFullSubgroups);
+    COPY_VAL(vulkan_1_3.subgroupSizeControl);
+    COPY_VAL(vulkan_1_3.shaderZeroInitializeWorkgroupMemory);
+    COPY_VAL(vulkan_1_3.dynamicRendering);
+
+    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
+    COPY_VAL(video_maintenance_2.videoMaintenance2);
+#endif
+
+#ifdef VK_KHR_video_decode_vp9
+    COPY_VAL(vp9_decode.videoDecodeVP9);
+#endif
+
+#ifdef VK_KHR_video_encode_av1
+    COPY_VAL(av1_encode.videoEncodeAV1);
+#endif
+
+    COPY_VAL(shader_object.shaderObject);
+
+    COPY_VAL(cooperative_matrix.cooperativeMatrix);
+
+    COPY_VAL(descriptor_buffer.descriptorBuffer);
+    COPY_VAL(descriptor_buffer.descriptorBufferPushDescriptors);
+
+    COPY_VAL(atomic_float.shaderBufferFloat32Atomics);
+    COPY_VAL(atomic_float.shaderBufferFloat32AtomicAdd);
+
+#ifdef VK_KHR_shader_relaxed_extended_instruction
+    COPY_VAL(relaxed_extended_instruction.shaderRelaxedExtendedInstruction);
+#endif
+
+#ifdef VK_KHR_shader_expect_assume
+    COPY_VAL(expect_assume.shaderExpectAssume);
+#endif
+
+#undef COPY_VAL
+}
+
+#define ASPECT_2PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT)
+#define ASPECT_3PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT)
+
+static const struct FFVkFormatEntry {
+    VkFormat vkf;
+    enum AVPixelFormat pixfmt;
+    VkImageAspectFlags aspect;
+    int vk_planes;
+    int nb_images;
+    int nb_images_fallback;
+    const VkFormat fallback[5];
+} vk_formats_list[] = {
+    /* Gray formats */
+    { VK_FORMAT_R8_UNORM,   AV_PIX_FMT_GRAY8,   VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8_UNORM   } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GRAY10,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM  } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GRAY12,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM  } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GRAY14,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM  } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GRAY16,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM  } },
+    { VK_FORMAT_R32_UINT,   AV_PIX_FMT_GRAY32,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32_UINT   } },
+    { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GRAYF32, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32_SFLOAT } },
+
+    /* RGB formats */
+    { VK_FORMAT_B8G8R8A8_UNORM,           AV_PIX_FMT_BGRA,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B8G8R8A8_UNORM           } },
+    { VK_FORMAT_R8G8B8A8_UNORM,           AV_PIX_FMT_RGBA,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM           } },
+    { VK_FORMAT_R8G8B8_UNORM,             AV_PIX_FMT_RGB24,   VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8_UNORM             } },
+    { VK_FORMAT_B8G8R8_UNORM,             AV_PIX_FMT_BGR24,   VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B8G8R8_UNORM             } },
+    { VK_FORMAT_R16G16B16_UNORM,          AV_PIX_FMT_RGB48,   VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16_UNORM          } },
+    { VK_FORMAT_R16G16B16A16_UNORM,       AV_PIX_FMT_RGBA64,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM       } },
+    { VK_FORMAT_R5G6B5_UNORM_PACK16,      AV_PIX_FMT_RGB565,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R5G6B5_UNORM_PACK16      } },
+    { VK_FORMAT_B5G6R5_UNORM_PACK16,      AV_PIX_FMT_BGR565,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B5G6R5_UNORM_PACK16      } },
+    { VK_FORMAT_B8G8R8A8_UNORM,           AV_PIX_FMT_BGR0,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B8G8R8A8_UNORM           } },
+    { VK_FORMAT_R8G8B8A8_UNORM,           AV_PIX_FMT_RGB0,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM           } },
+    { VK_FORMAT_A2R10G10B10_UNORM_PACK32, AV_PIX_FMT_X2RGB10, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_A2R10G10B10_UNORM_PACK32 } },
+    { VK_FORMAT_A2B10G10R10_UNORM_PACK32, AV_PIX_FMT_X2BGR10, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_A2B10G10R10_UNORM_PACK32 } },
+    { VK_FORMAT_R32G32B32_SFLOAT,         AV_PIX_FMT_RGBF32,  VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32G32B32_SFLOAT         } },
+    { VK_FORMAT_R32G32B32A32_SFLOAT,      AV_PIX_FMT_RGBAF32, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32G32B32A32_SFLOAT      } },
+    { VK_FORMAT_R32G32B32_UINT,           AV_PIX_FMT_RGB96,   VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32G32B32_UINT           } },
+    { VK_FORMAT_R32G32B32A32_UINT,        AV_PIX_FMT_RGBA128, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32G32B32A32_UINT        } },
+
+    /* Planar RGB */
+    { VK_FORMAT_R8_UNORM,   AV_PIX_FMT_GBRP,     VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM   } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRP10,   VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRP12,   VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRP14,   VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRP16,   VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
+    { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GBRPF32,  VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } },
+
+    /* Planar RGB + Alpha */
+    { VK_FORMAT_R8_UNORM,   AV_PIX_FMT_GBRAP,    VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM   } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRAP10,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRAP12,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRAP14,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRAP16,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
+    { VK_FORMAT_R32_UINT,   AV_PIX_FMT_GBRAP32,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R32_UINT,   VK_FORMAT_R32_UINT,   VK_FORMAT_R32_UINT,   VK_FORMAT_R32_UINT   } },
+    { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GBRAPF32, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } },
+
+    /* Bayer */
+    { VK_FORMAT_R16_UNORM, AV_PIX_FMT_BAYER_RGGB16, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM } },
+
+    /* Two-plane 420 YUV at 8, 10, 12 and 16 bits */
+    { VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,                  AV_PIX_FMT_NV12, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R8_UNORM,  VK_FORMAT_R8G8_UNORM   } },
+    { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, AV_PIX_FMT_P010, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
+    { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, AV_PIX_FMT_P012, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
+    { VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,               AV_PIX_FMT_P016, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
+
+    /* Two-plane 422 YUV at 8, 10 and 16 bits */
+    { VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,                  AV_PIX_FMT_NV16, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R8_UNORM,  VK_FORMAT_R8G8_UNORM   } },
+    { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, AV_PIX_FMT_P210, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
+    { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, AV_PIX_FMT_P212, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
+    { VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,               AV_PIX_FMT_P216, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
+
+    /* Two-plane 444 YUV at 8, 10 and 16 bits */
+    { VK_FORMAT_G8_B8R8_2PLANE_444_UNORM,                  AV_PIX_FMT_NV24, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R8_UNORM,  VK_FORMAT_R8G8_UNORM   } },
+    { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16, AV_PIX_FMT_P410, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
+    { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16, AV_PIX_FMT_P412, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
+    { VK_FORMAT_G16_B16R16_2PLANE_444_UNORM,               AV_PIX_FMT_P416, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
+
+    /* Three-plane 420, 422, 444 at 8, 10, 12 and 16 bits */
+    { VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,    AV_PIX_FMT_YUV420P,   ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM  } },
+    { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P10, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P12, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P16, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,    AV_PIX_FMT_YUV422P,   ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM  } },
+    { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P10, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P12, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P16, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,    AV_PIX_FMT_YUV444P,   ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM,  VK_FORMAT_R8_UNORM  } },
+    { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P10, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P12, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+    { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P16, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
+
+    /* Single plane 422 at 8, 10, 12 and 16 bits */
+    { VK_FORMAT_G8B8G8R8_422_UNORM,                     AV_PIX_FMT_YUYV422, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM     } },
+    { VK_FORMAT_B8G8R8G8_422_UNORM,                     AV_PIX_FMT_UYVY422, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM     } },
+    { VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, AV_PIX_FMT_Y210,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
+    { VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, AV_PIX_FMT_Y212,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
+    { VK_FORMAT_G16B16G16R16_422_UNORM,                 AV_PIX_FMT_Y216,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
+
+    /* Planar YUVA 420 at 8, 10 and 16 bits */
+    { VK_FORMAT_R8_UNORM,   AV_PIX_FMT_YUVA420P,    VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM   } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_YUVA420P10,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_YUVA420P16,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
+
+    /* Planar YUVA 422 at 8, 10, 12 and 16 bits */
+    { VK_FORMAT_R8_UNORM,   AV_PIX_FMT_YUVA422P,    VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM   } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_YUVA422P10,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_YUVA422P12,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_YUVA422P16,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
+
+    /* Planar YUVA 444 at 8, 10, 12 and 16 bits */
+    { VK_FORMAT_R8_UNORM,   AV_PIX_FMT_YUVA444P,    VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM   } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_YUVA444P10,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_YUVA444P12,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_YUVA444P16,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
+
+    /* Single plane 444 at 8, 10, 12 and 16 bits */
+    { VK_FORMAT_B8G8R8A8_UNORM,                         AV_PIX_FMT_UYVA,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B8G8R8A8_UNORM     } },
+    { VK_FORMAT_A2R10G10B10_UNORM_PACK32,               AV_PIX_FMT_XV30,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
+    { VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,     AV_PIX_FMT_XV36,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
+    { VK_FORMAT_R16G16B16A16_UNORM,                     AV_PIX_FMT_XV48,    VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
+};
+static const int nb_vk_formats_list = FF_ARRAY_ELEMS(vk_formats_list);
+
+const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p)
+{
+    for (int i = 0; i < nb_vk_formats_list; i++)
+        if (vk_formats_list[i].pixfmt == p)
+            return vk_formats_list[i].fallback;
+    return NULL;
+}
+
+static const struct FFVkFormatEntry *vk_find_format_entry(enum AVPixelFormat p)
+{
+    for (int i = 0; i < nb_vk_formats_list; i++)
+        if (vk_formats_list[i].pixfmt == p)
+            return &vk_formats_list[i];
+    return NULL;
+}
+
+static int vkfmt_from_pixfmt2(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p,
+                              VkImageTiling tiling,
+                              VkFormat fmts[AV_NUM_DATA_POINTERS], /* Output format list */
+                              int *nb_images,                      /* Output number of images */
+                              VkImageAspectFlags *aspect,          /* Output aspect */
+                              VkImageUsageFlags *supported_usage,  /* Output supported usage */
+                              int disable_multiplane, int need_storage)
+{
+    VulkanDevicePriv *priv = dev_ctx->hwctx;
+    AVVulkanDeviceContext *hwctx = &priv->p;
+    FFVulkanFunctions *vk = &priv->vkctx.vkfn;
+
+    const VkFormatFeatureFlagBits2 basic_flags = VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT |
+                                                 VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT  |
+                                                 VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT;
+
+    for (int i = 0; i < nb_vk_formats_list; i++) {
+        if (vk_formats_list[i].pixfmt == p) {
+            VkFormatProperties3 fprops = {
+                .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3,
+            };
+            VkFormatProperties2 prop = {
+                .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
+                .pNext = &fprops,
+            };
+            VkFormatFeatureFlagBits2 feats_primary, feats_secondary;
+            int basics_primary = 0, basics_secondary = 0;
+            int storage_primary = 0, storage_secondary = 0;
+
+            vk->GetPhysicalDeviceFormatProperties2(hwctx->phys_dev,
+                                                   vk_formats_list[i].vkf,
+                                                   &prop);
+
+            feats_primary = tiling == VK_IMAGE_TILING_LINEAR ?
+                             fprops.linearTilingFeatures : fprops.optimalTilingFeatures;
+            basics_primary = (feats_primary & basic_flags) == basic_flags;
+            storage_primary = !!(feats_primary & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT);
+
+            if (vk_formats_list[i].vkf != vk_formats_list[i].fallback[0]) {
+                vk->GetPhysicalDeviceFormatProperties2(hwctx->phys_dev,
+                                                       vk_formats_list[i].fallback[0],
+                                                       &prop);
+                feats_secondary = tiling == VK_IMAGE_TILING_LINEAR ?
+                                  fprops.linearTilingFeatures : fprops.optimalTilingFeatures;
+                basics_secondary = (feats_secondary & basic_flags) == basic_flags;
+                storage_secondary = !!(feats_secondary & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT);
+            } else {
+                basics_secondary = basics_primary;
+                storage_secondary = storage_primary;
+            }
+
+            if (basics_primary &&
+                !(disable_multiplane && vk_formats_list[i].vk_planes > 1) &&
+                (!need_storage || (need_storage && (storage_primary | storage_secondary)))) {
+                if (fmts) {
+                    if (vk_formats_list[i].nb_images > 1) {
+                        for (int j = 0; j < vk_formats_list[i].nb_images_fallback; j++)
+                            fmts[j] = vk_formats_list[i].fallback[j];
+                    } else {
+                        fmts[0] = vk_formats_list[i].vkf;
+                    }
+                }
+                if (nb_images)
+                    *nb_images = 1;
+                if (aspect)
+                    *aspect = vk_formats_list[i].aspect;
+                if (supported_usage)
+                    *supported_usage = ff_vk_map_feats_to_usage(feats_primary) |
+                                       ((need_storage && (storage_primary | storage_secondary)) ?
+                                        VK_IMAGE_USAGE_STORAGE_BIT : 0);
+                return 0;
+            } else if (basics_secondary &&
+                       (!need_storage || (need_storage && storage_secondary))) {
+                if (fmts) {
+                    for (int j = 0; j < vk_formats_list[i].nb_images_fallback; j++)
+                        fmts[j] = vk_formats_list[i].fallback[j];
+                }
+                if (nb_images)
+                    *nb_images = vk_formats_list[i].nb_images_fallback;
+                if (aspect)
+                    *aspect = vk_formats_list[i].aspect;
+                if (supported_usage)
+                    *supported_usage = ff_vk_map_feats_to_usage(feats_secondary);
+                return 0;
+            } else {
+                return AVERROR(ENOTSUP);
+            }
+        }
+    }
+
+    return AVERROR(EINVAL);
+}
+
+#if CONFIG_VULKAN_STATIC
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance,
+                                                               const char *pName);
+#endif
+
+static int load_libvulkan(AVHWDeviceContext *ctx)
+{
+    VulkanDevicePriv *p = ctx->hwctx;
+    AVVulkanDeviceContext *hwctx = &p->p;
+
+#if CONFIG_VULKAN_STATIC
+    hwctx->get_proc_addr = vkGetInstanceProcAddr;
+#else
+    static const char *lib_names[] = {
+#if defined(_WIN32)
+        "vulkan-1.dll",
+#elif defined(__APPLE__)
+        "libvulkan.dylib",
+        "libvulkan.1.dylib",
+        "libMoltenVK.dylib",
+#else
+        "libvulkan.so.1",
+        "libvulkan.so",
+#endif
+    };
+
+    for (int i = 0; i < FF_ARRAY_ELEMS(lib_names); i++) {
+        p->libvulkan = dlopen(lib_names[i], RTLD_NOW | RTLD_LOCAL);
+        if (p->libvulkan)
+            break;
+    }
+
+    if (!p->libvulkan) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to open the libvulkan library!\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    hwctx->get_proc_addr = (PFN_vkGetInstanceProcAddr)dlsym(p->libvulkan, "vkGetInstanceProcAddr");
+#endif /* CONFIG_VULKAN_STATIC */
+
+    return 0;
+}
+
+typedef struct VulkanOptExtension {
+    const char *name;
+    FFVulkanExtensions flag;
+} VulkanOptExtension;
+
+static const VulkanOptExtension optional_instance_exts[] = {
+    { VK_EXT_LAYER_SETTINGS_EXTENSION_NAME,                   FF_VK_EXT_NO_FLAG                },
+#ifdef __APPLE__
+    { VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,          FF_VK_EXT_NO_FLAG                },
+#endif
+};
+
+static const VulkanOptExtension optional_device_exts[] = {
+    /* Misc or required by other extensions */
+    { VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME,               FF_VK_EXT_PORTABILITY_SUBSET     },
+    { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME,                  FF_VK_EXT_PUSH_DESCRIPTOR        },
+    { VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME,                FF_VK_EXT_DESCRIPTOR_BUFFER      },
+    { VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME,              FF_VK_EXT_DEVICE_DRM             },
+    { VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME,              FF_VK_EXT_ATOMIC_FLOAT           },
+    { VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME,               FF_VK_EXT_COOP_MATRIX            },
+    { VK_EXT_SHADER_OBJECT_EXTENSION_NAME,                    FF_VK_EXT_SHADER_OBJECT          },
+    { VK_KHR_SHADER_SUBGROUP_ROTATE_EXTENSION_NAME,           FF_VK_EXT_SUBGROUP_ROTATE        },
+#ifdef VK_KHR_shader_expect_assume
+    { VK_KHR_SHADER_EXPECT_ASSUME_EXTENSION_NAME,             FF_VK_EXT_EXPECT_ASSUME          },
+#endif
+    { 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    },
+#endif
+
+    /* Imports/exports */
+    { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,               FF_VK_EXT_EXTERNAL_FD_MEMORY     },
+    { VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME,          FF_VK_EXT_EXTERNAL_DMABUF_MEMORY },
+    { VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME,        FF_VK_EXT_DRM_MODIFIER_FLAGS     },
+    { VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,            FF_VK_EXT_EXTERNAL_FD_SEM        },
+    { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME,             FF_VK_EXT_EXTERNAL_HOST_MEMORY   },
+#ifdef _WIN32
+    { VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,            FF_VK_EXT_EXTERNAL_WIN32_MEMORY  },
+    { VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME,         FF_VK_EXT_EXTERNAL_WIN32_SEM     },
+#endif
+
+    /* Video encoding/decoding */
+    { VK_KHR_VIDEO_QUEUE_EXTENSION_NAME,                      FF_VK_EXT_VIDEO_QUEUE            },
+    { VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME,               FF_VK_EXT_VIDEO_ENCODE_QUEUE     },
+    { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME,               FF_VK_EXT_VIDEO_DECODE_QUEUE     },
+    { VK_KHR_VIDEO_ENCODE_H264_EXTENSION_NAME,                FF_VK_EXT_VIDEO_ENCODE_H264      },
+    { VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME,                FF_VK_EXT_VIDEO_DECODE_H264      },
+    { VK_KHR_VIDEO_ENCODE_H265_EXTENSION_NAME,                FF_VK_EXT_VIDEO_ENCODE_H265      },
+    { VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME,                FF_VK_EXT_VIDEO_DECODE_H265      },
+#ifdef VK_KHR_video_decode_vp9
+    { VK_KHR_VIDEO_DECODE_VP9_EXTENSION_NAME,                 FF_VK_EXT_VIDEO_DECODE_VP9       },
+#endif
+#ifdef VK_KHR_video_encode_av1
+    { VK_KHR_VIDEO_ENCODE_AV1_EXTENSION_NAME,                 FF_VK_EXT_VIDEO_ENCODE_AV1       },
+#endif
+    { VK_KHR_VIDEO_DECODE_AV1_EXTENSION_NAME,                 FF_VK_EXT_VIDEO_DECODE_AV1       },
+};
+
+static VkBool32 VKAPI_CALL vk_dbg_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
+                                           VkDebugUtilsMessageTypeFlagsEXT messageType,
+                                           const VkDebugUtilsMessengerCallbackDataEXT *data,
+                                           void *priv)
+{
+    int l;
+    AVHWDeviceContext *ctx = priv;
+
+    /* Ignore false positives */
+    switch (data->messageIdNumber) {
+    case 0x086974c1: /* BestPractices-vkCreateCommandPool-command-buffer-reset */
+    case 0xfd92477a: /* BestPractices-vkAllocateMemory-small-allocation */
+    case 0x618ab1e7: /* VUID-VkImageViewCreateInfo-usage-02275 */
+    case 0x30f4ac70: /* VUID-VkImageCreateInfo-pNext-06811 */
+        return VK_FALSE;
+    default:
+        break;
+    }
+
+    switch (severity) {
+    case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: l = AV_LOG_VERBOSE; break;
+    case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:    l = AV_LOG_INFO;    break;
+    case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: l = AV_LOG_WARNING; break;
+    case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:   l = AV_LOG_ERROR;   break;
+    default:                                              l = AV_LOG_DEBUG;   break;
+    }
+
+    av_log(ctx, l, "%s\n", data->pMessage);
+    for (int i = 0; i < data->cmdBufLabelCount; i++)
+        av_log(ctx, l, "\t%i: %s\n", i, data->pCmdBufLabels[i].pLabelName);
+
+    return VK_FALSE;
+}
+
+#define ADD_VAL_TO_LIST(list, count, val)                                      \
+    do {                                                                       \
+        list = av_realloc_array(list, sizeof(*list), ++count);                 \
+        if (!list) {                                                           \
+            err = AVERROR(ENOMEM);                                             \
+            goto fail;                                                         \
+        }                                                                      \
+        list[count - 1] = av_strdup(val);                                      \
+        if (!list[count - 1]) {                                                \
+            err = AVERROR(ENOMEM);                                             \
+            goto fail;                                                         \
+        }                                                                      \
+    } while(0)
+
+#define RELEASE_PROPS(props, count)                                            \
+    if (props) {                                                               \
+        for (int i = 0; i < count; i++)                                        \
+            av_free((void *)((props)[i]));                                     \
+        av_free((void *)props);                                                \
+    }
+
+enum FFVulkanDebugMode {
+    FF_VULKAN_DEBUG_NONE = 0,
+    /* Standard GPU-assisted validation */
+    FF_VULKAN_DEBUG_VALIDATE = 1,
+    /* Passes printfs in shaders to the debug callback */
+    FF_VULKAN_DEBUG_PRINTF = 2,
+    /* Enables extra printouts */
+    FF_VULKAN_DEBUG_PRACTICES = 3,
+    /* Disables validation but keeps shader debug info and optimizations */
+    FF_VULKAN_DEBUG_PROFILE = 4,
+
+    FF_VULKAN_DEBUG_NB,
+};
+
+static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts,
+                            const char * const **dst, uint32_t *num,
+                            enum FFVulkanDebugMode debug_mode)
+{
+    const char *tstr;
+    const char **extension_names = NULL;
+    VulkanDevicePriv *p = ctx->hwctx;
+    AVVulkanDeviceContext *hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+    int err = 0, found, extensions_found = 0;
+
+    const char *mod;
+    int optional_exts_num;
+    uint32_t sup_ext_count;
+    char *user_exts_str = NULL;
+    AVDictionaryEntry *user_exts;
+    VkExtensionProperties *sup_ext;
+    const VulkanOptExtension *optional_exts;
+
+    if (!dev) {
+        mod = "instance";
+        optional_exts = optional_instance_exts;
+        optional_exts_num = FF_ARRAY_ELEMS(optional_instance_exts);
+        user_exts = av_dict_get(opts, "instance_extensions", NULL, 0);
+        if (user_exts) {
+            user_exts_str = av_strdup(user_exts->value);
+            if (!user_exts_str) {
+                err = AVERROR(ENOMEM);
+                goto fail;
+            }
+        }
+        vk->EnumerateInstanceExtensionProperties(NULL, &sup_ext_count, NULL);
+        sup_ext = av_malloc_array(sup_ext_count, sizeof(VkExtensionProperties));
+        if (!sup_ext)
+            return AVERROR(ENOMEM);
+        vk->EnumerateInstanceExtensionProperties(NULL, &sup_ext_count, sup_ext);
+    } else {
+        mod = "device";
+        optional_exts = optional_device_exts;
+        optional_exts_num = FF_ARRAY_ELEMS(optional_device_exts);
+        user_exts = av_dict_get(opts, "device_extensions", NULL, 0);
+        if (user_exts) {
+            user_exts_str = av_strdup(user_exts->value);
+            if (!user_exts_str) {
+                err = AVERROR(ENOMEM);
+                goto fail;
+            }
+        }
+        vk->EnumerateDeviceExtensionProperties(hwctx->phys_dev, NULL,
+                                               &sup_ext_count, NULL);
+        sup_ext = av_malloc_array(sup_ext_count, sizeof(VkExtensionProperties));
+        if (!sup_ext)
+            return AVERROR(ENOMEM);
+        vk->EnumerateDeviceExtensionProperties(hwctx->phys_dev, NULL,
+                                               &sup_ext_count, sup_ext);
+    }
+
+    for (int i = 0; i < optional_exts_num; i++) {
+        tstr = optional_exts[i].name;
+        found = 0;
+
+        /* Intel has had a bad descriptor buffer implementation for a while */
+        if (p->dprops.driverID == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA &&
+            !strcmp(tstr, VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME))
+            continue;
+
+        if (dev &&
+            ((debug_mode == FF_VULKAN_DEBUG_VALIDATE) ||
+             (debug_mode == FF_VULKAN_DEBUG_PRINTF) ||
+             (debug_mode == FF_VULKAN_DEBUG_PRACTICES)) &&
+            !strcmp(tstr, VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME)) {
+            continue;
+        }
+
+        for (int j = 0; j < sup_ext_count; j++) {
+            if (!strcmp(tstr, sup_ext[j].extensionName)) {
+                found = 1;
+                break;
+            }
+        }
+        if (!found)
+            continue;
+
+        av_log(ctx, AV_LOG_VERBOSE, "Using %s extension %s\n", mod, tstr);
+        p->vkctx.extensions |= optional_exts[i].flag;
+        ADD_VAL_TO_LIST(extension_names, extensions_found, tstr);
+    }
+
+    if (!dev &&
+        ((debug_mode == FF_VULKAN_DEBUG_VALIDATE) ||
+         (debug_mode == FF_VULKAN_DEBUG_PRINTF) ||
+         (debug_mode == FF_VULKAN_DEBUG_PRACTICES))) {
+        tstr = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
+        found = 0;
+        for (int j = 0; j < sup_ext_count; j++) {
+            if (!strcmp(tstr, sup_ext[j].extensionName)) {
+                found = 1;
+                break;
+            }
+        }
+        if (found) {
+            av_log(ctx, AV_LOG_VERBOSE, "Using %s extension %s\n", mod, tstr);
+            ADD_VAL_TO_LIST(extension_names, extensions_found, tstr);
+        } else {
+            av_log(ctx, AV_LOG_ERROR, "Debug extension \"%s\" not found!\n",
+                   tstr);
+            err = AVERROR(EINVAL);
+            goto fail;
+        }
+    }
+
+#ifdef VK_KHR_shader_relaxed_extended_instruction
+    if (((debug_mode == FF_VULKAN_DEBUG_PRINTF) ||
+         (debug_mode == FF_VULKAN_DEBUG_PROFILE)) && dev) {
+        tstr = VK_KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION_EXTENSION_NAME;
+        found = 0;
+        for (int j = 0; j < sup_ext_count; j++) {
+            if (!strcmp(tstr, sup_ext[j].extensionName)) {
+                found = 1;
+                break;
+            }
+        }
+        if (found) {
+            av_log(ctx, AV_LOG_VERBOSE, "Using %s extension %s\n", mod, tstr);
+            ADD_VAL_TO_LIST(extension_names, extensions_found, tstr);
+        } else {
+            av_log(ctx, AV_LOG_ERROR, "Debug_printf/profile enabled, but extension \"%s\" not found!\n",
+                   tstr);
+            err = AVERROR(EINVAL);
+            goto fail;
+        }
+    }
+#endif
+
+    if (user_exts_str) {
+        char *save, *token = av_strtok(user_exts_str, "+", &save);
+        while (token) {
+            found = 0;
+            for (int j = 0; j < sup_ext_count; j++) {
+                if (!strcmp(token, sup_ext[j].extensionName)) {
+                    found = 1;
+                    break;
+                }
+            }
+            if (found) {
+                av_log(ctx, AV_LOG_VERBOSE, "Using %s extension \"%s\"\n", mod, token);
+                ADD_VAL_TO_LIST(extension_names, extensions_found, token);
+            } else {
+                av_log(ctx, AV_LOG_WARNING, "%s extension \"%s\" not found, excluding.\n",
+                       mod, token);
+            }
+            token = av_strtok(NULL, "+", &save);
+        }
+    }
+
+    *dst = extension_names;
+    *num = extensions_found;
+
+    av_free(user_exts_str);
+    av_free(sup_ext);
+    return 0;
+
+fail:
+    RELEASE_PROPS(extension_names, extensions_found);
+    av_free(user_exts_str);
+    av_free(sup_ext);
+    return err;
+}
+
+static int check_layers(AVHWDeviceContext *ctx, AVDictionary *opts,
+                        const char * const **dst, uint32_t *num,
+                        enum FFVulkanDebugMode *debug_mode)
+{
+    int err = 0;
+    VulkanDevicePriv *priv = ctx->hwctx;
+    FFVulkanFunctions *vk = &priv->vkctx.vkfn;
+
+    static const char layer_standard_validation[] = { "VK_LAYER_KHRONOS_validation" };
+    int layer_standard_validation_found = 0;
+
+    uint32_t sup_layer_count;
+    VkLayerProperties *sup_layers;
+
+    AVDictionaryEntry *user_layers = av_dict_get(opts, "layers", NULL, 0);
+    char *user_layers_str = NULL;
+    char *save, *token;
+
+    const char **enabled_layers = NULL;
+    uint32_t enabled_layers_count = 0;
+
+    AVDictionaryEntry *debug_opt = av_dict_get(opts, "debug", NULL, 0);
+    enum FFVulkanDebugMode mode;
+
+    *debug_mode = mode = FF_VULKAN_DEBUG_NONE;
+
+    /* Get a list of all layers */
+    vk->EnumerateInstanceLayerProperties(&sup_layer_count, NULL);
+    sup_layers = av_malloc_array(sup_layer_count, sizeof(VkLayerProperties));
+    if (!sup_layers)
+        return AVERROR(ENOMEM);
+    vk->EnumerateInstanceLayerProperties(&sup_layer_count, sup_layers);
+
+    av_log(ctx, AV_LOG_VERBOSE, "Supported layers:\n");
+    for (int i = 0; i < sup_layer_count; i++)
+        av_log(ctx, AV_LOG_VERBOSE, "\t%s\n", sup_layers[i].layerName);
+
+    /* If no user layers or debug layers are given, return */
+    if (!debug_opt && !user_layers)
+        goto end;
+
+    /* Check for any properly supported validation layer */
+    if (debug_opt) {
+        if (!strcmp(debug_opt->value, "profile")) {
+            mode = FF_VULKAN_DEBUG_PROFILE;
+        } else if (!strcmp(debug_opt->value, "printf")) {
+            mode = FF_VULKAN_DEBUG_PRINTF;
+        } else if (!strcmp(debug_opt->value, "validate")) {
+            mode = FF_VULKAN_DEBUG_VALIDATE;
+        } else if (!strcmp(debug_opt->value, "practices")) {
+            mode = FF_VULKAN_DEBUG_PRACTICES;
+        } else {
+            char *end_ptr = NULL;
+            int idx = strtol(debug_opt->value, &end_ptr, 10);
+            if (end_ptr == debug_opt->value || end_ptr[0] != '\0' ||
+                idx < 0 || idx >= FF_VULKAN_DEBUG_NB) {
+                av_log(ctx, AV_LOG_ERROR, "Invalid debugging mode \"%s\"\n",
+                       debug_opt->value);
+                err = AVERROR(EINVAL);
+                goto end;
+            }
+            mode = idx;
+        }
+    }
+
+    /* If mode is VALIDATE or PRINTF, try to find the standard validation layer extension */
+    if ((mode == FF_VULKAN_DEBUG_VALIDATE) ||
+        (mode == FF_VULKAN_DEBUG_PRINTF) ||
+        (mode == FF_VULKAN_DEBUG_PRACTICES)) {
+        for (int i = 0; i < sup_layer_count; i++) {
+            if (!strcmp(layer_standard_validation, sup_layers[i].layerName)) {
+                av_log(ctx, AV_LOG_VERBOSE, "Standard validation layer %s is enabled\n",
+                       layer_standard_validation);
+                ADD_VAL_TO_LIST(enabled_layers, enabled_layers_count, layer_standard_validation);
+                *debug_mode = mode;
+                layer_standard_validation_found = 1;
+                break;
+            }
+        }
+        if (!layer_standard_validation_found) {
+            av_log(ctx, AV_LOG_ERROR,
+                   "Validation Layer \"%s\" not supported\n", layer_standard_validation);
+            err = AVERROR(ENOTSUP);
+            goto end;
+        }
+    } else if (mode == FF_VULKAN_DEBUG_PROFILE) {
+        *debug_mode = mode;
+    }
+
+    /* Process any custom layers enabled */
+    if (user_layers) {
+        int found;
+
+        user_layers_str = av_strdup(user_layers->value);
+        if (!user_layers_str) {
+            err = AVERROR(ENOMEM);
+            goto fail;
+        }
+
+        token = av_strtok(user_layers_str, "+", &save);
+        while (token) {
+            found = 0;
+
+            /* If debug=1/2 was specified as an option, skip this layer */
+            if (!strcmp(layer_standard_validation, token) && layer_standard_validation_found) {
+                token = av_strtok(NULL, "+", &save);
+                break;
+            }
+
+            /* Try to find the layer in the list of supported layers */
+            for (int j = 0; j < sup_layer_count; j++) {
+                if (!strcmp(token, sup_layers[j].layerName)) {
+                    found = 1;
+                    break;
+                }
+            }
+
+            if (found) {
+                av_log(ctx, AV_LOG_VERBOSE, "Using layer: %s\n", token);
+                ADD_VAL_TO_LIST(enabled_layers, enabled_layers_count, token);
+
+                /* If debug was not set as an option, force it */
+                if (!strcmp(layer_standard_validation, token))
+                    *debug_mode = FF_VULKAN_DEBUG_VALIDATE;
+            } else {
+                av_log(ctx, AV_LOG_ERROR,
+                       "Layer \"%s\" not supported\n", token);
+                err = AVERROR(EINVAL);
+                goto end;
+            }
+
+            token = av_strtok(NULL, "+", &save);
+        }
+    }
+
+fail:
+end:
+    av_free(sup_layers);
+    av_free(user_layers_str);
+
+    if (err < 0) {
+        RELEASE_PROPS(enabled_layers, enabled_layers_count);
+    } else {
+        *dst = enabled_layers;
+        *num = enabled_layers_count;
+    }
+
+    return err;
+}
+
+/* Creates a VkInstance */
+static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts,
+                           enum FFVulkanDebugMode *debug_mode)
+{
+    int err = 0;
+    VkResult ret;
+    VulkanDevicePriv *p = ctx->hwctx;
+    AVVulkanDeviceContext *hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+    VkApplicationInfo application_info = {
+        .sType              = VK_STRUCTURE_TYPE_APPLICATION_INFO,
+        .pApplicationName   = "ffmpeg",
+        .applicationVersion = VK_MAKE_VERSION(LIBAVUTIL_VERSION_MAJOR,
+                                              LIBAVUTIL_VERSION_MINOR,
+                                              LIBAVUTIL_VERSION_MICRO),
+        .pEngineName        = "libavutil",
+        .apiVersion         = VK_API_VERSION_1_3,
+        .engineVersion      = VK_MAKE_VERSION(LIBAVUTIL_VERSION_MAJOR,
+                                              LIBAVUTIL_VERSION_MINOR,
+                                              LIBAVUTIL_VERSION_MICRO),
+    };
+    VkValidationFeaturesEXT validation_features = {
+        .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
+    };
+    VkInstanceCreateInfo inst_props = {
+        .sType            = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+        .pApplicationInfo = &application_info,
+    };
+
+    if (!hwctx->get_proc_addr) {
+        err = load_libvulkan(ctx);
+        if (err < 0)
+            return err;
+    }
+
+    err = ff_vk_load_functions(ctx, vk, p->vkctx.extensions, 0, 0);
+    if (err < 0) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to load instance enumeration functions!\n");
+        return err;
+    }
+
+    err = check_layers(ctx, opts, &inst_props.ppEnabledLayerNames,
+                       &inst_props.enabledLayerCount, debug_mode);
+    if (err)
+        goto fail;
+
+    /* Check for present/missing extensions */
+    err = check_extensions(ctx, 0, opts, &inst_props.ppEnabledExtensionNames,
+                           &inst_props.enabledExtensionCount, *debug_mode);
+    hwctx->enabled_inst_extensions = inst_props.ppEnabledExtensionNames;
+    hwctx->nb_enabled_inst_extensions = inst_props.enabledExtensionCount;
+    if (err < 0)
+        goto fail;
+
+    /* Enable debug features if needed */
+    if (*debug_mode == FF_VULKAN_DEBUG_VALIDATE) {
+        static const VkValidationFeatureEnableEXT feat_list_validate[] = {
+            VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
+            VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT,
+            VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT,
+        };
+        validation_features.pEnabledValidationFeatures = feat_list_validate;
+        validation_features.enabledValidationFeatureCount = FF_ARRAY_ELEMS(feat_list_validate);
+        inst_props.pNext = &validation_features;
+    } else if (*debug_mode == FF_VULKAN_DEBUG_PRINTF) {
+        static const VkValidationFeatureEnableEXT feat_list_debug[] = {
+            VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
+            VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT,
+            VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT,
+        };
+        validation_features.pEnabledValidationFeatures = feat_list_debug;
+        validation_features.enabledValidationFeatureCount = FF_ARRAY_ELEMS(feat_list_debug);
+        inst_props.pNext = &validation_features;
+    } else if (*debug_mode == FF_VULKAN_DEBUG_PRACTICES) {
+        static const VkValidationFeatureEnableEXT feat_list_practices[] = {
+            VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
+            VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
+        };
+        validation_features.pEnabledValidationFeatures = feat_list_practices;
+        validation_features.enabledValidationFeatureCount = FF_ARRAY_ELEMS(feat_list_practices);
+        inst_props.pNext = &validation_features;
+    }
+
+#ifdef __APPLE__
+    for (int i = 0; i < inst_props.enabledExtensionCount; i++) {
+        if (!strcmp(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
+                    inst_props.ppEnabledExtensionNames[i])) {
+            inst_props.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
+            break;
+        }
+    }
+#endif
+
+    /* Try to create the instance */
+    ret = vk->CreateInstance(&inst_props, hwctx->alloc, &hwctx->inst);
+
+    /* Check for errors */
+    if (ret != VK_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Instance creation failure: %s\n",
+               ff_vk_ret2str(ret));
+        err = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+    err = ff_vk_load_functions(ctx, vk, p->vkctx.extensions, 1, 0);
+    if (err < 0) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to load instance functions!\n");
+        goto fail;
+    }
+
+    /* Setup debugging callback if needed */
+    if ((*debug_mode == FF_VULKAN_DEBUG_VALIDATE) ||
+        (*debug_mode == FF_VULKAN_DEBUG_PRINTF) ||
+        (*debug_mode == FF_VULKAN_DEBUG_PRACTICES)) {
+        VkDebugUtilsMessengerCreateInfoEXT dbg = {
+            .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
+            .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
+                               VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT    |
+                               VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
+                               VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
+            .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT    |
+                           VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
+                           VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
+            .pfnUserCallback = vk_dbg_callback,
+            .pUserData = ctx,
+        };
+
+        vk->CreateDebugUtilsMessengerEXT(hwctx->inst, &dbg,
+                                         hwctx->alloc, &p->debug_ctx);
+    }
+
+    err = 0;
+
+fail:
+    RELEASE_PROPS(inst_props.ppEnabledLayerNames, inst_props.enabledLayerCount);
+    return err;
+}
+
+typedef struct VulkanDeviceSelection {
+    uint8_t uuid[VK_UUID_SIZE]; /* Will use this first unless !has_uuid */
+    int has_uuid;
+    uint32_t drm_major; /* Will use this second unless !has_drm */
+    uint32_t drm_minor; /* Will use this second unless !has_drm */
+    uint32_t has_drm; /* has drm node info */
+    const char *name; /* Will use this third unless NULL */
+    uint32_t pci_device; /* Will use this fourth unless 0x0 */
+    uint32_t vendor_id; /* Last resort to find something deterministic */
+    int index; /* Finally fall back to index */
+} VulkanDeviceSelection;
+
+static const char *vk_dev_type(enum VkPhysicalDeviceType type)
+{
+    switch (type) {
+    case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: return "integrated";
+    case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:   return "discrete";
+    case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:    return "virtual";
+    case VK_PHYSICAL_DEVICE_TYPE_CPU:            return "software";
+    default:                                     return "unknown";
+    }
+}
+
+/* Finds a device */
+static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select)
+{
+    int err = 0, choice = -1;
+    uint32_t num;
+    VkResult ret;
+    VulkanDevicePriv *p = ctx->hwctx;
+    AVVulkanDeviceContext *hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+    VkPhysicalDevice *devices = NULL;
+    VkPhysicalDeviceIDProperties *idp = NULL;
+    VkPhysicalDeviceProperties2 *prop = NULL;
+    VkPhysicalDeviceDriverProperties *driver_prop = NULL;
+    VkPhysicalDeviceDrmPropertiesEXT *drm_prop = NULL;
+
+    ret = vk->EnumeratePhysicalDevices(hwctx->inst, &num, NULL);
+    if (ret != VK_SUCCESS || !num) {
+        av_log(ctx, AV_LOG_ERROR, "No devices found: %s!\n", ff_vk_ret2str(ret));
+        return AVERROR(ENODEV);
+    }
+
+    devices = av_malloc_array(num, sizeof(VkPhysicalDevice));
+    if (!devices)
+        return AVERROR(ENOMEM);
+
+    ret = vk->EnumeratePhysicalDevices(hwctx->inst, &num, devices);
+    if (ret != VK_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Failed enumerating devices: %s\n",
+               ff_vk_ret2str(ret));
+        err = AVERROR(ENODEV);
+        goto end;
+    }
+
+    prop = av_calloc(num, sizeof(*prop));
+    if (!prop) {
+        err = AVERROR(ENOMEM);
+        goto end;
+    }
+
+    idp = av_calloc(num, sizeof(*idp));
+    if (!idp) {
+        err = AVERROR(ENOMEM);
+        goto end;
+    }
+
+    driver_prop = av_calloc(num, sizeof(*driver_prop));
+    if (!driver_prop) {
+        err = AVERROR(ENOMEM);
+        goto end;
+    }
+
+    if (p->vkctx.extensions & FF_VK_EXT_DEVICE_DRM) {
+        drm_prop = av_calloc(num, sizeof(*drm_prop));
+        if (!drm_prop) {
+            err = AVERROR(ENOMEM);
+            goto end;
+        }
+    }
+
+    av_log(ctx, AV_LOG_VERBOSE, "GPU listing:\n");
+    for (int i = 0; i < num; i++) {
+        if (p->vkctx.extensions & FF_VK_EXT_DEVICE_DRM) {
+            drm_prop[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT;
+            driver_prop[i].pNext = &drm_prop[i];
+        }
+        driver_prop[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
+        idp[i].pNext = &driver_prop[i];
+        idp[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
+        prop[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+        prop[i].pNext = &idp[i];
+
+        vk->GetPhysicalDeviceProperties2(devices[i], &prop[i]);
+        av_log(ctx, AV_LOG_VERBOSE, "    %d: %s (%s) (0x%x)\n", i,
+               prop[i].properties.deviceName,
+               vk_dev_type(prop[i].properties.deviceType),
+               prop[i].properties.deviceID);
+    }
+
+    if (select->has_uuid) {
+        for (int i = 0; i < num; i++) {
+            if (!strncmp(idp[i].deviceUUID, select->uuid, VK_UUID_SIZE)) {
+                choice = i;
+                goto end;
+             }
+        }
+        av_log(ctx, AV_LOG_ERROR, "Unable to find device by given UUID!\n");
+        err = AVERROR(ENODEV);
+        goto end;
+    } else if ((p->vkctx.extensions & FF_VK_EXT_DEVICE_DRM) && select->has_drm) {
+        for (int i = 0; i < num; i++) {
+            if ((select->drm_major == drm_prop[i].primaryMajor &&
+                 select->drm_minor == drm_prop[i].primaryMinor) ||
+                (select->drm_major == drm_prop[i].renderMajor &&
+                 select->drm_minor == drm_prop[i].renderMinor)) {
+                choice = i;
+                goto end;
+             }
+        }
+        av_log(ctx, AV_LOG_ERROR, "Unable to find device by given DRM node numbers %i:%i!\n",
+               select->drm_major, select->drm_minor);
+        err = AVERROR(ENODEV);
+        goto end;
+    } else if (select->name) {
+        av_log(ctx, AV_LOG_VERBOSE, "Requested device: %s\n", select->name);
+        for (int i = 0; i < num; i++) {
+            if (strstr(prop[i].properties.deviceName, select->name)) {
+                choice = i;
+                goto end;
+             }
+        }
+        av_log(ctx, AV_LOG_ERROR, "Unable to find device \"%s\"!\n",
+               select->name);
+        err = AVERROR(ENODEV);
+        goto end;
+    } else if (select->pci_device) {
+        av_log(ctx, AV_LOG_VERBOSE, "Requested device: 0x%x\n", select->pci_device);
+        for (int i = 0; i < num; i++) {
+            if (select->pci_device == prop[i].properties.deviceID) {
+                choice = i;
+                goto end;
+            }
+        }
+        av_log(ctx, AV_LOG_ERROR, "Unable to find device with PCI ID 0x%x!\n",
+               select->pci_device);
+        err = AVERROR(EINVAL);
+        goto end;
+    } else if (select->vendor_id) {
+        av_log(ctx, AV_LOG_VERBOSE, "Requested vendor: 0x%x\n", select->vendor_id);
+        for (int i = 0; i < num; i++) {
+            if (select->vendor_id == prop[i].properties.vendorID) {
+                choice = i;
+                goto end;
+            }
+        }
+        av_log(ctx, AV_LOG_ERROR, "Unable to find device with Vendor ID 0x%x!\n",
+               select->vendor_id);
+        err = AVERROR(ENODEV);
+        goto end;
+    } else {
+        if (select->index < num) {
+            choice = select->index;
+            goto end;
+        }
+        av_log(ctx, AV_LOG_ERROR, "Unable to find device with index %i!\n",
+               select->index);
+        err = AVERROR(ENODEV);
+        goto end;
+    }
+
+end:
+    if (choice > -1) {
+        av_log(ctx, AV_LOG_VERBOSE, "Device %d selected: %s (%s) (0x%x)\n",
+               choice, prop[choice].properties.deviceName,
+               vk_dev_type(prop[choice].properties.deviceType),
+               prop[choice].properties.deviceID);
+        hwctx->phys_dev = devices[choice];
+        p->props = prop[choice];
+        p->props.pNext = NULL;
+        p->dprops = driver_prop[choice];
+        p->dprops.pNext = NULL;
+    }
+
+    av_free(devices);
+    av_free(prop);
+    av_free(idp);
+    av_free(drm_prop);
+    av_free(driver_prop);
+
+    return err;
+}
+
+/* Picks the least used qf with the fewest unneeded flags, or -1 if none found */
+static inline int pick_queue_family(VkQueueFamilyProperties2 *qf, uint32_t num_qf,
+                                    VkQueueFlagBits flags)
+{
+    int index = -1;
+    uint32_t min_score = UINT32_MAX;
+
+    for (int i = 0; i < num_qf; i++) {
+        VkQueueFlagBits qflags = qf[i].queueFamilyProperties.queueFlags;
+
+        /* Per the spec, reporting transfer caps is optional for these 2 types */
+        if ((flags & VK_QUEUE_TRANSFER_BIT) &&
+            (qflags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT)))
+            qflags |= VK_QUEUE_TRANSFER_BIT;
+
+        if (qflags & flags) {
+            uint32_t score = av_popcount(qflags) + qf[i].queueFamilyProperties.timestampValidBits;
+            if (score < min_score) {
+                index = i;
+                min_score = score;
+            }
+        }
+    }
+
+    if (index > -1)
+        qf[index].queueFamilyProperties.timestampValidBits++;
+
+    return index;
+}
+
+static inline int pick_video_queue_family(VkQueueFamilyProperties2 *qf,
+                                          VkQueueFamilyVideoPropertiesKHR *qf_vid, uint32_t num_qf,
+                                          VkVideoCodecOperationFlagBitsKHR flags)
+{
+    int index = -1;
+    uint32_t min_score = UINT32_MAX;
+
+    for (int i = 0; i < num_qf; i++) {
+        const VkQueueFlagBits qflags = qf[i].queueFamilyProperties.queueFlags;
+        const VkQueueFlagBits vflags = qf_vid[i].videoCodecOperations;
+
+        if (!(qflags & (VK_QUEUE_VIDEO_ENCODE_BIT_KHR | VK_QUEUE_VIDEO_DECODE_BIT_KHR)))
+            continue;
+
+        if (vflags & flags) {
+            uint32_t score = av_popcount(vflags) + qf[i].queueFamilyProperties.timestampValidBits;
+            if (score < min_score) {
+                index = i;
+                min_score = score;
+            }
+        }
+    }
+
+    if (index > -1)
+        qf[index].queueFamilyProperties.timestampValidBits++;
+
+    return index;
+}
+
+static int setup_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd)
+{
+    uint32_t num;
+    VulkanDevicePriv *p = ctx->hwctx;
+    AVVulkanDeviceContext *hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+
+    VkQueueFamilyProperties2 *qf = NULL;
+    VkQueueFamilyVideoPropertiesKHR *qf_vid = NULL;
+
+    /* First get the number of queue families */
+    vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &num, NULL);
+    if (!num) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to get queues!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    /* Then allocate memory */
+    qf = av_malloc_array(num, sizeof(VkQueueFamilyProperties2));
+    if (!qf)
+        return AVERROR(ENOMEM);
+
+    qf_vid = av_malloc_array(num, sizeof(VkQueueFamilyVideoPropertiesKHR));
+    if (!qf_vid)
+        return AVERROR(ENOMEM);
+
+    for (uint32_t i = 0; i < num; i++) {
+        qf_vid[i] = (VkQueueFamilyVideoPropertiesKHR) {
+            .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR,
+        };
+        qf[i] = (VkQueueFamilyProperties2) {
+            .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
+            .pNext = p->vkctx.extensions & FF_VK_EXT_VIDEO_QUEUE ? &qf_vid[i] : NULL,
+        };
+    }
+
+    /* Finally retrieve the queue families */
+    vk->GetPhysicalDeviceQueueFamilyProperties2(hwctx->phys_dev, &num, qf);
+
+    av_log(ctx, AV_LOG_VERBOSE, "Queue families:\n");
+    for (int i = 0; i < num; i++) {
+        av_log(ctx, AV_LOG_VERBOSE, "    %i:%s%s%s%s%s%s%s%s (queues: %i)\n", i,
+               ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_GRAPHICS_BIT) ? " graphics" : "",
+               ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_COMPUTE_BIT) ? " compute" : "",
+               ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_TRANSFER_BIT) ? " transfer" : "",
+               ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_VIDEO_ENCODE_BIT_KHR) ? " encode" : "",
+               ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_VIDEO_DECODE_BIT_KHR) ? " decode" : "",
+               ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_SPARSE_BINDING_BIT) ? " sparse" : "",
+               ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_OPTICAL_FLOW_BIT_NV) ? " optical_flow" : "",
+               ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_PROTECTED_BIT) ? " protected" : "",
+               qf[i].queueFamilyProperties.queueCount);
+
+        /* We use this field to keep a score of how many times we've used that
+         * queue family in order to make better choices. */
+        qf[i].queueFamilyProperties.timestampValidBits = 0;
+    }
+
+    hwctx->nb_qf = 0;
+
+    /* Pick each queue family to use. */
+#define PICK_QF(type, vid_op)                                            \
+    do {                                                                 \
+        uint32_t i;                                                      \
+        uint32_t idx;                                                    \
+                                                                         \
+        if (vid_op)                                                      \
+            idx = pick_video_queue_family(qf, qf_vid, num, vid_op);      \
+        else                                                             \
+            idx = pick_queue_family(qf, num, type);                      \
+                                                                         \
+        if (idx == -1)                                                   \
+            continue;                                                    \
+                                                                         \
+        for (i = 0; i < hwctx->nb_qf; i++) {                             \
+            if (hwctx->qf[i].idx == idx) {                               \
+                hwctx->qf[i].flags |= type;                              \
+                hwctx->qf[i].video_caps |= vid_op;                       \
+                break;                                                   \
+            }                                                            \
+        }                                                                \
+        if (i == hwctx->nb_qf) {                                         \
+            hwctx->qf[i].idx = idx;                                      \
+            hwctx->qf[i].num = qf[idx].queueFamilyProperties.queueCount; \
+            if (p->limit_queues ||                                       \
+                p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY) { \
+                int max = p->limit_queues;                               \
+                if (type == VK_QUEUE_GRAPHICS_BIT)                       \
+                    hwctx->qf[i].num = FFMIN(hwctx->qf[i].num,           \
+                                             max ? max : 1);             \
+                else if (max)                                            \
+                    hwctx->qf[i].num = FFMIN(hwctx->qf[i].num, max);     \
+            }                                                            \
+            hwctx->qf[i].flags = type;                                   \
+            hwctx->qf[i].video_caps = vid_op;                            \
+            hwctx->nb_qf++;                                              \
+        }                                                                \
+    } while (0)
+
+    PICK_QF(VK_QUEUE_GRAPHICS_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR);
+    PICK_QF(VK_QUEUE_COMPUTE_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR);
+    PICK_QF(VK_QUEUE_TRANSFER_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR);
+
+    PICK_QF(VK_QUEUE_VIDEO_ENCODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR);
+    PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR);
+
+    PICK_QF(VK_QUEUE_VIDEO_ENCODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR);
+    PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR);
+
+#ifdef VK_KHR_video_decode_vp9
+    PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_VP9_BIT_KHR);
+#endif
+
+#ifdef VK_KHR_video_encode_av1
+    PICK_QF(VK_QUEUE_VIDEO_ENCODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR);
+#endif
+    PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR);
+
+    av_free(qf);
+    av_free(qf_vid);
+
+#undef PICK_QF
+
+    cd->pQueueCreateInfos = av_malloc_array(hwctx->nb_qf,
+                                            sizeof(VkDeviceQueueCreateInfo));
+    if (!cd->pQueueCreateInfos)
+        return AVERROR(ENOMEM);
+
+    for (uint32_t i = 0; i < hwctx->nb_qf; i++) {
+        int dup = 0;
+        float *weights = NULL;
+        VkDeviceQueueCreateInfo *pc;
+        for (uint32_t j = 0; j < cd->queueCreateInfoCount; j++) {
+            if (hwctx->qf[i].idx == cd->pQueueCreateInfos[j].queueFamilyIndex) {
+                dup = 1;
+                break;
+            }
+        }
+        if (dup)
+            continue;
+
+        weights = av_malloc_array(hwctx->qf[i].num, sizeof(float));
+        if (!weights) {
+            for (uint32_t j = 0; j < cd->queueCreateInfoCount; j++)
+                av_free((void *)cd->pQueueCreateInfos[i].pQueuePriorities);
+            av_free((void *)cd->pQueueCreateInfos);
+            return AVERROR(ENOMEM);
+        }
+
+        for (uint32_t j = 0; j < hwctx->qf[i].num; j++)
+            weights[j] = 1.0;
+
+        pc = (VkDeviceQueueCreateInfo *)cd->pQueueCreateInfos;
+        pc[cd->queueCreateInfoCount++] = (VkDeviceQueueCreateInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+            .queueFamilyIndex = hwctx->qf[i].idx,
+            .queueCount = hwctx->qf[i].num,
+            .pQueuePriorities = weights,
+        };
+    }
+
+#if FF_API_VULKAN_FIXED_QUEUES
+FF_DISABLE_DEPRECATION_WARNINGS
+    /* Setup deprecated fields */
+    hwctx->queue_family_index        = -1;
+    hwctx->queue_family_comp_index   = -1;
+    hwctx->queue_family_tx_index     = -1;
+    hwctx->queue_family_encode_index = -1;
+    hwctx->queue_family_decode_index = -1;
+
+#define SET_OLD_QF(field, nb_field, type)             \
+    do {                                              \
+        if (field < 0 && hwctx->qf[i].flags & type) { \
+            field = hwctx->qf[i].idx;                 \
+            nb_field = hwctx->qf[i].num;              \
+        }                                             \
+    } while (0)
+
+    for (uint32_t i = 0; i < hwctx->nb_qf; i++) {
+        SET_OLD_QF(hwctx->queue_family_index, hwctx->nb_graphics_queues, VK_QUEUE_GRAPHICS_BIT);
+        SET_OLD_QF(hwctx->queue_family_comp_index, hwctx->nb_comp_queues, VK_QUEUE_COMPUTE_BIT);
+        SET_OLD_QF(hwctx->queue_family_tx_index, hwctx->nb_tx_queues, VK_QUEUE_TRANSFER_BIT);
+        SET_OLD_QF(hwctx->queue_family_encode_index, hwctx->nb_encode_queues, VK_QUEUE_VIDEO_ENCODE_BIT_KHR);
+        SET_OLD_QF(hwctx->queue_family_decode_index, hwctx->nb_decode_queues, VK_QUEUE_VIDEO_DECODE_BIT_KHR);
+    }
+
+#undef SET_OLD_QF
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+    return 0;
+}
+
+/* Only resources created by vulkan_device_create should be released here,
+ * resources created by vulkan_device_init should be released by
+ * vulkan_device_uninit, to make sure we don't free user provided resources,
+ * and there is no leak.
+ */
+static void vulkan_device_free(AVHWDeviceContext *ctx)
+{
+    VulkanDevicePriv *p = ctx->hwctx;
+    AVVulkanDeviceContext *hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+
+    if (hwctx->act_dev)
+        vk->DestroyDevice(hwctx->act_dev, hwctx->alloc);
+
+    if (p->debug_ctx)
+        vk->DestroyDebugUtilsMessengerEXT(hwctx->inst, p->debug_ctx,
+                                          hwctx->alloc);
+
+    if (hwctx->inst)
+        vk->DestroyInstance(hwctx->inst, hwctx->alloc);
+
+    if (p->libvulkan)
+        dlclose(p->libvulkan);
+
+    RELEASE_PROPS(hwctx->enabled_inst_extensions, hwctx->nb_enabled_inst_extensions);
+    RELEASE_PROPS(hwctx->enabled_dev_extensions, hwctx->nb_enabled_dev_extensions);
+}
+
+static void vulkan_device_uninit(AVHWDeviceContext *ctx)
+{
+    VulkanDevicePriv *p = ctx->hwctx;
+
+    for (uint32_t i = 0; i < p->nb_tot_qfs; i++) {
+        pthread_mutex_destroy(p->qf_mutex[i]);
+        av_freep(&p->qf_mutex[i]);
+    }
+    av_freep(&p->qf_mutex);
+
+    ff_vk_uninit(&p->vkctx);
+}
+
+static int vulkan_device_has_rebar(AVHWDeviceContext *ctx)
+{
+    VulkanDevicePriv *p = ctx->hwctx;
+    VkDeviceSize max_vram = 0, max_visible_vram = 0;
+
+    /* Get device memory properties */
+    for (int i = 0; i < p->mprops.memoryTypeCount; i++) {
+        const VkMemoryType type = p->mprops.memoryTypes[i];
+        const VkMemoryHeap heap = p->mprops.memoryHeaps[type.heapIndex];
+        if (!(type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT))
+            continue;
+        max_vram = FFMAX(max_vram, heap.size);
+        if (type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
+            max_visible_vram = FFMAX(max_visible_vram, heap.size);
+    }
+
+    return max_vram - max_visible_vram < 1024; /* 1 kB tolerance */
+}
+
+static int vulkan_device_create_internal(AVHWDeviceContext *ctx,
+                                         VulkanDeviceSelection *dev_select,
+                                         int disable_multiplane,
+                                         AVDictionary *opts, int flags)
+{
+    int err = 0;
+    VkResult ret;
+    AVDictionaryEntry *opt_d;
+    VulkanDevicePriv *p = ctx->hwctx;
+    AVVulkanDeviceContext *hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+    enum FFVulkanDebugMode debug_mode = FF_VULKAN_DEBUG_NONE;
+    VulkanDeviceFeatures supported_feats = { 0 };
+    VkDeviceCreateInfo dev_info = {
+        .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+    };
+
+    /* Create an instance if not given one */
+    if ((err = create_instance(ctx, opts, &debug_mode)))
+        goto end;
+
+    /* Find a physical device (if not given one) */
+    if ((err = find_device(ctx, dev_select)))
+        goto end;
+
+    /* Find and enable extensions for the physical device */
+    if ((err = check_extensions(ctx, 1, opts, &dev_info.ppEnabledExtensionNames,
+                                &dev_info.enabledExtensionCount, debug_mode))) {
+        for (int i = 0; i < dev_info.queueCreateInfoCount; i++)
+            av_free((void *)dev_info.pQueueCreateInfos[i].pQueuePriorities);
+        av_free((void *)dev_info.pQueueCreateInfos);
+        goto end;
+    }
+
+    /* Get supported memory types */
+    vk->GetPhysicalDeviceMemoryProperties(hwctx->phys_dev, &p->mprops);
+
+    /* Get all supported features for the physical device */
+    device_features_init(ctx, &supported_feats);
+    vk->GetPhysicalDeviceFeatures2(hwctx->phys_dev, &supported_feats.device);
+
+    /* Copy all needed features from those supported and activate them */
+    device_features_init(ctx, &p->feats);
+    device_features_copy_needed(&p->feats, &supported_feats);
+    dev_info.pNext = p->feats.device.pNext;
+    dev_info.pEnabledFeatures = &p->feats.device.features;
+
+    /* Setup enabled queue families */
+    if ((err = setup_queue_families(ctx, &dev_info)))
+        goto end;
+
+    /* Finally create the device */
+    ret = vk->CreateDevice(hwctx->phys_dev, &dev_info, hwctx->alloc,
+                           &hwctx->act_dev);
+
+    for (int i = 0; i < dev_info.queueCreateInfoCount; i++)
+        av_free((void *)dev_info.pQueueCreateInfos[i].pQueuePriorities);
+    av_free((void *)dev_info.pQueueCreateInfos);
+
+    if (ret != VK_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Device creation failure: %s\n",
+               ff_vk_ret2str(ret));
+        for (int i = 0; i < dev_info.enabledExtensionCount; i++)
+            av_free((void *)dev_info.ppEnabledExtensionNames[i]);
+        av_free((void *)dev_info.ppEnabledExtensionNames);
+        err = AVERROR_EXTERNAL;
+        goto end;
+    }
+
+    /* Tiled images setting, use them by default */
+    opt_d = av_dict_get(opts, "linear_images", NULL, 0);
+    if (opt_d)
+        p->use_linear_images = strtol(opt_d->value, NULL, 10);
+
+    /* Limit queues to a given number if needed */
+    opt_d = av_dict_get(opts, "limit_queues", NULL, 0);
+    if (opt_d)
+        p->limit_queues = strtol(opt_d->value, NULL, 10);
+
+    /* The disable_multiplane argument takes precedent over the option */
+    p->disable_multiplane = disable_multiplane;
+    if (!p->disable_multiplane) {
+        opt_d = av_dict_get(opts, "disable_multiplane", NULL, 0);
+        if (opt_d)
+            p->disable_multiplane = strtol(opt_d->value, NULL, 10);
+    }
+
+    /* Disable host pointer imports (by default on nvidia) */
+    p->avoid_host_import = p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY;
+    opt_d = av_dict_get(opts, "avoid_host_import", NULL, 0);
+    if (opt_d)
+        p->avoid_host_import = strtol(opt_d->value, NULL, 10);
+
+    /* Set the public device feature struct and its pNext chain */
+    hwctx->device_features = p->feats.device;
+
+    /* Set the list of all active extensions */
+    hwctx->enabled_dev_extensions = dev_info.ppEnabledExtensionNames;
+    hwctx->nb_enabled_dev_extensions = dev_info.enabledExtensionCount;
+
+    /* The extension lists need to be freed */
+    ctx->free = vulkan_device_free;
+
+end:
+    return err;
+}
+
+static void lock_queue(AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index)
+{
+    VulkanDevicePriv *p = ctx->hwctx;
+    pthread_mutex_lock(&p->qf_mutex[queue_family][index]);
+}
+
+static void unlock_queue(AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index)
+{
+    VulkanDevicePriv *p = ctx->hwctx;
+    pthread_mutex_unlock(&p->qf_mutex[queue_family][index]);
+}
+
+static int vulkan_device_init(AVHWDeviceContext *ctx)
+{
+    int err = 0;
+    uint32_t qf_num;
+    VulkanDevicePriv *p = ctx->hwctx;
+    AVVulkanDeviceContext *hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+    VkQueueFamilyProperties2 *qf;
+    VkQueueFamilyVideoPropertiesKHR *qf_vid;
+    VkPhysicalDeviceExternalSemaphoreInfo ext_sem_props_info;
+    int graph_index, comp_index, tx_index, enc_index, dec_index;
+
+    /* Set device extension flags */
+    for (int i = 0; i < hwctx->nb_enabled_dev_extensions; i++) {
+        for (int j = 0; j < FF_ARRAY_ELEMS(optional_device_exts); j++) {
+            if (!strcmp(hwctx->enabled_dev_extensions[i],
+                        optional_device_exts[j].name)) {
+                p->vkctx.extensions |= optional_device_exts[j].flag;
+                break;
+            }
+        }
+    }
+
+    err = ff_vk_load_functions(ctx, vk, p->vkctx.extensions, 1, 1);
+    if (err < 0) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to load functions!\n");
+        return err;
+    }
+
+    p->props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+    p->props.pNext = &p->hprops;
+    p->hprops.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT;
+    p->hprops.pNext = &p->dprops;
+    p->dprops.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
+
+    vk->GetPhysicalDeviceProperties2(hwctx->phys_dev, &p->props);
+    av_log(ctx, AV_LOG_VERBOSE, "Using device: %s\n",
+           p->props.properties.deviceName);
+    av_log(ctx, AV_LOG_VERBOSE, "Alignments:\n");
+    av_log(ctx, AV_LOG_VERBOSE, "    optimalBufferCopyRowPitchAlignment: %"PRIu64"\n",
+           p->props.properties.limits.optimalBufferCopyRowPitchAlignment);
+    av_log(ctx, AV_LOG_VERBOSE, "    minMemoryMapAlignment:              %"SIZE_SPECIFIER"\n",
+           p->props.properties.limits.minMemoryMapAlignment);
+    av_log(ctx, AV_LOG_VERBOSE, "    nonCoherentAtomSize:                %"PRIu64"\n",
+           p->props.properties.limits.nonCoherentAtomSize);
+    if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY)
+        av_log(ctx, AV_LOG_VERBOSE, "    minImportedHostPointerAlignment:    %"PRIu64"\n",
+               p->hprops.minImportedHostPointerAlignment);
+
+    vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &qf_num, NULL);
+    if (!qf_num) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to get queues!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    ext_sem_props_info = (VkPhysicalDeviceExternalSemaphoreInfo) {
+        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
+    };
+
+    /* Opaque FD semaphore properties */
+    ext_sem_props_info.handleType =
+#ifdef _WIN32
+        IsWindows8OrGreater()
+            ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
+            : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT;
+#else
+        VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
+#endif
+    p->ext_sem_props_opaque.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES;
+    vk->GetPhysicalDeviceExternalSemaphoreProperties(hwctx->phys_dev,
+                                                     &ext_sem_props_info,
+                                                     &p->ext_sem_props_opaque);
+
+    qf = av_malloc_array(qf_num, sizeof(VkQueueFamilyProperties2));
+    if (!qf)
+        return AVERROR(ENOMEM);
+
+    qf_vid = av_malloc_array(qf_num, sizeof(VkQueueFamilyVideoPropertiesKHR));
+    if (!qf_vid) {
+        av_free(qf);
+        return AVERROR(ENOMEM);
+    }
+
+    for (uint32_t i = 0; i < qf_num; i++) {
+        qf_vid[i] = (VkQueueFamilyVideoPropertiesKHR) {
+            .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR,
+        };
+        qf[i] = (VkQueueFamilyProperties2) {
+            .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
+            .pNext = p->vkctx.extensions & FF_VK_EXT_VIDEO_QUEUE ? &qf_vid[i] : NULL,
+        };
+    }
+
+    vk->GetPhysicalDeviceQueueFamilyProperties2(hwctx->phys_dev, &qf_num, qf);
+
+    p->qf_mutex = av_calloc(qf_num, sizeof(*p->qf_mutex));
+    if (!p->qf_mutex) {
+        err = AVERROR(ENOMEM);
+        goto end;
+    }
+    p->nb_tot_qfs = qf_num;
+
+    for (uint32_t i = 0; i < qf_num; i++) {
+        p->qf_mutex[i] = av_calloc(qf[i].queueFamilyProperties.queueCount,
+                                   sizeof(**p->qf_mutex));
+        if (!p->qf_mutex[i]) {
+            err = AVERROR(ENOMEM);
+            goto end;
+        }
+        for (uint32_t j = 0; j < qf[i].queueFamilyProperties.queueCount; j++) {
+            err = pthread_mutex_init(&p->qf_mutex[i][j], NULL);
+            if (err != 0) {
+                av_log(ctx, AV_LOG_ERROR, "pthread_mutex_init failed : %s\n",
+                       av_err2str(err));
+                err = AVERROR(err);
+                goto end;
+            }
+        }
+    }
+
+#if FF_API_VULKAN_FIXED_QUEUES
+FF_DISABLE_DEPRECATION_WARNINGS
+    graph_index = hwctx->nb_graphics_queues ? hwctx->queue_family_index : -1;
+    comp_index  = hwctx->nb_comp_queues ? hwctx->queue_family_comp_index : -1;
+    tx_index    = hwctx->nb_tx_queues ? hwctx->queue_family_tx_index : -1;
+    dec_index   = hwctx->nb_decode_queues ? hwctx->queue_family_decode_index : -1;
+    enc_index   = hwctx->nb_encode_queues ? hwctx->queue_family_encode_index : -1;
+
+#define CHECK_QUEUE(type, required, fidx, ctx_qf, qc)                                           \
+    do {                                                                                        \
+        if (ctx_qf < 0 && required) {                                                           \
+            av_log(ctx, AV_LOG_ERROR, "%s queue family is required, but marked as missing"      \
+                   " in the context!\n", type);                                                 \
+            err = AVERROR(EINVAL);                                                              \
+            goto end;                                                                           \
+        } else if (fidx < 0 || ctx_qf < 0) {                                                    \
+            break;                                                                              \
+        } else if (ctx_qf >= qf_num) {                                                          \
+            av_log(ctx, AV_LOG_ERROR, "Invalid %s family index %i (device has %i families)!\n", \
+                   type, ctx_qf, qf_num);                                                       \
+            err = AVERROR(EINVAL);                                                              \
+            goto end;                                                                           \
+        }                                                                                       \
+                                                                                                \
+        av_log(ctx, AV_LOG_VERBOSE, "Using queue family %i (queues: %i)"                        \
+               " for%s%s%s%s%s\n",                                                              \
+               ctx_qf, qc,                                                                      \
+               ctx_qf == graph_index ? " graphics" : "",                                        \
+               ctx_qf == comp_index  ? " compute" : "",                                         \
+               ctx_qf == tx_index    ? " transfers" : "",                                       \
+               ctx_qf == enc_index   ? " encode" : "",                                          \
+               ctx_qf == dec_index   ? " decode" : "");                                         \
+        graph_index = (ctx_qf == graph_index) ? -1 : graph_index;                               \
+        comp_index  = (ctx_qf == comp_index)  ? -1 : comp_index;                                \
+        tx_index    = (ctx_qf == tx_index)    ? -1 : tx_index;                                  \
+        enc_index   = (ctx_qf == enc_index)   ? -1 : enc_index;                                 \
+        dec_index   = (ctx_qf == dec_index)   ? -1 : dec_index;                                 \
+    } while (0)
+
+    CHECK_QUEUE("graphics", 0, graph_index, hwctx->queue_family_index,        hwctx->nb_graphics_queues);
+    CHECK_QUEUE("compute",  1, comp_index,  hwctx->queue_family_comp_index,   hwctx->nb_comp_queues);
+    CHECK_QUEUE("upload",   1, tx_index,    hwctx->queue_family_tx_index,     hwctx->nb_tx_queues);
+    CHECK_QUEUE("decode",   0, dec_index,   hwctx->queue_family_decode_index, hwctx->nb_decode_queues);
+    CHECK_QUEUE("encode",   0, enc_index,   hwctx->queue_family_encode_index, hwctx->nb_encode_queues);
+
+#undef CHECK_QUEUE
+
+    /* Update the new queue family fields. If non-zero already,
+     * it means API users have set it. */
+    if (!hwctx->nb_qf) {
+#define ADD_QUEUE(ctx_qf, qc, flag)                                    \
+    do {                                                               \
+        if (ctx_qf != -1) {                                            \
+            hwctx->qf[hwctx->nb_qf++] = (AVVulkanDeviceQueueFamily) {  \
+                .idx = ctx_qf,                                         \
+                .num = qc,                                             \
+                .flags = flag,                                         \
+            };                                                         \
+        }                                                              \
+    } while (0)
+
+        ADD_QUEUE(hwctx->queue_family_index, hwctx->nb_graphics_queues, VK_QUEUE_GRAPHICS_BIT);
+        ADD_QUEUE(hwctx->queue_family_comp_index, hwctx->nb_comp_queues, VK_QUEUE_COMPUTE_BIT);
+        ADD_QUEUE(hwctx->queue_family_tx_index, hwctx->nb_tx_queues, VK_QUEUE_TRANSFER_BIT);
+        ADD_QUEUE(hwctx->queue_family_decode_index, hwctx->nb_decode_queues, VK_QUEUE_VIDEO_DECODE_BIT_KHR);
+        ADD_QUEUE(hwctx->queue_family_encode_index, hwctx->nb_encode_queues, VK_QUEUE_VIDEO_ENCODE_BIT_KHR);
+#undef ADD_QUEUE
+    }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+    for (int i = 0; i < hwctx->nb_qf; i++) {
+        if (!hwctx->qf[i].video_caps &&
+            hwctx->qf[i].flags & (VK_QUEUE_VIDEO_DECODE_BIT_KHR |
+                                  VK_QUEUE_VIDEO_ENCODE_BIT_KHR)) {
+            hwctx->qf[i].video_caps = qf_vid[hwctx->qf[i].idx].videoCodecOperations;
+        }
+    }
+
+    /* Setup array for pQueueFamilyIndices with used queue families */
+    p->nb_img_qfs = 0;
+    for (int i = 0; i < hwctx->nb_qf; i++) {
+        int seen = 0;
+        /* Make sure each entry is unique
+         * (VUID-VkBufferCreateInfo-sharingMode-01419) */
+        for (int j = (i - 1); j >= 0; j--) {
+            if (hwctx->qf[i].idx == hwctx->qf[j].idx) {
+                seen = 1;
+                break;
+            }
+        }
+        if (!seen)
+            p->img_qfs[p->nb_img_qfs++] = hwctx->qf[i].idx;
+    }
+
+    if (!hwctx->lock_queue)
+        hwctx->lock_queue = lock_queue;
+    if (!hwctx->unlock_queue)
+        hwctx->unlock_queue = unlock_queue;
+
+    /* Re-query device capabilities, in case the device was created externally */
+    vk->GetPhysicalDeviceMemoryProperties(hwctx->phys_dev, &p->mprops);
+
+    p->vkctx.device = ctx;
+    p->vkctx.hwctx = hwctx;
+
+    ff_vk_load_props(&p->vkctx);
+    p->compute_qf = ff_vk_qf_find(&p->vkctx, VK_QUEUE_COMPUTE_BIT, 0);
+    p->transfer_qf = ff_vk_qf_find(&p->vkctx, VK_QUEUE_TRANSFER_BIT, 0);
+
+    /* Re-query device capabilities, in case the device was created externally */
+    vk->GetPhysicalDeviceMemoryProperties(hwctx->phys_dev, &p->mprops);
+
+    /* Only use host image transfers if ReBAR is enabled */
+    p->disable_host_transfer = !vulkan_device_has_rebar(ctx);
+
+end:
+    av_free(qf_vid);
+    av_free(qf);
+    return err;
+}
+
+static int vulkan_device_create(AVHWDeviceContext *ctx, const char *device,
+                                AVDictionary *opts, int flags)
+{
+    VulkanDeviceSelection dev_select = { 0 };
+    if (device && device[0]) {
+        char *end = NULL;
+        dev_select.index = strtol(device, &end, 10);
+        if (end == device) {
+            dev_select.index = 0;
+            dev_select.name  = device;
+        }
+    }
+
+    return vulkan_device_create_internal(ctx, &dev_select, 0, opts, flags);
+}
+
+static int vulkan_device_derive(AVHWDeviceContext *ctx,
+                                AVHWDeviceContext *src_ctx,
+                                AVDictionary *opts, int flags)
+{
+    av_unused VulkanDeviceSelection dev_select = { 0 };
+
+    /* If there's only one device on the system, then even if its not covered
+     * by the following checks (e.g. non-PCIe ARM GPU), having an empty
+     * dev_select will mean it'll get picked. */
+    switch(src_ctx->type) {
+#if CONFIG_VAAPI
+    case AV_HWDEVICE_TYPE_VAAPI: {
+        AVVAAPIDeviceContext *src_hwctx = src_ctx->hwctx;
+        VADisplay dpy = src_hwctx->display;
+#if VA_CHECK_VERSION(1, 15, 0)
+        VAStatus vas;
+        VADisplayAttribute attr = {
+            .type = VADisplayPCIID,
+        };
+#endif
+        const char *vendor;
+
+#if VA_CHECK_VERSION(1, 15, 0)
+        vas = vaGetDisplayAttributes(dpy, &attr, 1);
+        if (vas == VA_STATUS_SUCCESS && attr.flags != VA_DISPLAY_ATTRIB_NOT_SUPPORTED)
+            dev_select.pci_device = (attr.value & 0xFFFF);
+#endif
+
+        if (!dev_select.pci_device) {
+            vendor = vaQueryVendorString(dpy);
+            if (!vendor) {
+                av_log(ctx, AV_LOG_ERROR, "Unable to get device info from VAAPI!\n");
+                return AVERROR_EXTERNAL;
+            }
+
+            if (strstr(vendor, "AMD"))
+                dev_select.vendor_id = 0x1002;
+        }
+
+        return vulkan_device_create_internal(ctx, &dev_select, 0, opts, flags);
+    }
+#endif
+#if CONFIG_LIBDRM
+    case AV_HWDEVICE_TYPE_DRM: {
+        int err;
+        struct stat drm_node_info;
+        drmDevice *drm_dev_info;
+        AVDRMDeviceContext *src_hwctx = src_ctx->hwctx;
+
+        err = fstat(src_hwctx->fd, &drm_node_info);
+        if (err) {
+            av_log(ctx, AV_LOG_ERROR, "Unable to get node info from DRM fd: %s!\n",
+                   av_err2str(AVERROR(errno)));
+            return AVERROR_EXTERNAL;
+        }
+
+        dev_select.drm_major = major(drm_node_info.st_dev);
+        dev_select.drm_minor = minor(drm_node_info.st_dev);
+        dev_select.has_drm   = 1;
+
+        err = drmGetDevice(src_hwctx->fd, &drm_dev_info);
+        if (err) {
+            av_log(ctx, AV_LOG_ERROR, "Unable to get device info from DRM fd: %s!\n",
+                   av_err2str(AVERROR(errno)));
+            return AVERROR_EXTERNAL;
+        }
+
+        if (drm_dev_info->bustype == DRM_BUS_PCI)
+            dev_select.pci_device = drm_dev_info->deviceinfo.pci->device_id;
+
+        drmFreeDevice(&drm_dev_info);
+
+        return vulkan_device_create_internal(ctx, &dev_select, 0, opts, flags);
+    }
+#endif
+#if CONFIG_CUDA
+    case AV_HWDEVICE_TYPE_CUDA: {
+        AVHWDeviceContext *cuda_cu = src_ctx;
+        AVCUDADeviceContext *src_hwctx = src_ctx->hwctx;
+        AVCUDADeviceContextInternal *cu_internal = src_hwctx->internal;
+        CudaFunctions *cu = cu_internal->cuda_dl;
+
+        int ret = CHECK_CU(cu->cuDeviceGetUuid((CUuuid *)&dev_select.uuid,
+                                               cu_internal->cuda_device));
+        if (ret < 0) {
+            av_log(ctx, AV_LOG_ERROR, "Unable to get UUID from CUDA!\n");
+            return AVERROR_EXTERNAL;
+        }
+
+        dev_select.has_uuid = 1;
+
+        /*
+         * CUDA is not able to import multiplane images, so always derive a
+         * Vulkan device with multiplane disabled.
+         */
+        return vulkan_device_create_internal(ctx, &dev_select, 1, opts, flags);
+    }
+#endif
+    default:
+        return AVERROR(ENOSYS);
+    }
+}
+
+static int vulkan_frames_get_constraints(AVHWDeviceContext *ctx,
+                                         const void *hwconfig,
+                                         AVHWFramesConstraints *constraints)
+{
+    int count = 0;
+    VulkanDevicePriv *p = ctx->hwctx;
+
+    for (enum AVPixelFormat i = 0; i < nb_vk_formats_list; i++) {
+        count += vkfmt_from_pixfmt2(ctx, vk_formats_list[i].pixfmt,
+                                    p->use_linear_images ? VK_IMAGE_TILING_LINEAR :
+                                                           VK_IMAGE_TILING_OPTIMAL,
+                                    NULL, NULL, NULL, NULL, p->disable_multiplane, 1) >= 0;
+    }
+
+    constraints->valid_sw_formats = av_malloc_array(count + 1,
+                                                    sizeof(enum AVPixelFormat));
+    if (!constraints->valid_sw_formats)
+        return AVERROR(ENOMEM);
+
+    count = 0;
+    for (enum AVPixelFormat i = 0; i < nb_vk_formats_list; i++) {
+        if (vkfmt_from_pixfmt2(ctx, vk_formats_list[i].pixfmt,
+                               p->use_linear_images ? VK_IMAGE_TILING_LINEAR :
+                                                      VK_IMAGE_TILING_OPTIMAL,
+                               NULL, NULL, NULL, NULL, p->disable_multiplane, 1) >= 0) {
+            constraints->valid_sw_formats[count++] = vk_formats_list[i].pixfmt;
+        }
+    }
+
+    constraints->valid_sw_formats[count++] = AV_PIX_FMT_NONE;
+
+    constraints->min_width  = 1;
+    constraints->min_height = 1;
+    constraints->max_width  = p->props.properties.limits.maxImageDimension2D;
+    constraints->max_height = p->props.properties.limits.maxImageDimension2D;
+
+    constraints->valid_hw_formats = av_malloc_array(2, sizeof(enum AVPixelFormat));
+    if (!constraints->valid_hw_formats)
+        return AVERROR(ENOMEM);
+
+    constraints->valid_hw_formats[0] = AV_PIX_FMT_VULKAN;
+    constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
+
+    return 0;
+}
+
+static int alloc_mem(AVHWDeviceContext *ctx, VkMemoryRequirements *req,
+                     VkMemoryPropertyFlagBits req_flags, const void *alloc_extension,
+                     VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
+{
+    VkResult ret;
+    int index = -1;
+    VulkanDevicePriv *p = ctx->hwctx;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+    AVVulkanDeviceContext *dev_hwctx = &p->p;
+    VkMemoryAllocateInfo alloc_info = {
+        .sType          = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+        .pNext          = alloc_extension,
+        .allocationSize = req->size,
+    };
+
+    /* The vulkan spec requires memory types to be sorted in the "optimal"
+     * order, so the first matching type we find will be the best/fastest one */
+    for (int i = 0; i < p->mprops.memoryTypeCount; i++) {
+        const VkMemoryType *type = &p->mprops.memoryTypes[i];
+
+        /* The memory type must be supported by the requirements (bitfield) */
+        if (!(req->memoryTypeBits & (1 << i)))
+            continue;
+
+        /* The memory type flags must include our properties */
+        if ((type->propertyFlags & req_flags) != req_flags)
+            continue;
+
+        /* The memory type must be large enough */
+        if (req->size > p->mprops.memoryHeaps[type->heapIndex].size)
+            continue;
+
+        /* Found a suitable memory type */
+        index = i;
+        break;
+    }
+
+    if (index < 0) {
+        av_log(ctx, AV_LOG_ERROR, "No memory type found for flags 0x%x\n",
+               req_flags);
+        return AVERROR(EINVAL);
+    }
+
+    alloc_info.memoryTypeIndex = index;
+
+    ret = vk->AllocateMemory(dev_hwctx->act_dev, &alloc_info,
+                             dev_hwctx->alloc, mem);
+    if (ret != VK_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory: %s\n",
+               ff_vk_ret2str(ret));
+        return AVERROR(ENOMEM);
+    }
+
+    *mem_flags |= p->mprops.memoryTypes[index].propertyFlags;
+
+    return 0;
+}
+
+static void vulkan_free_internal(AVVkFrame *f)
+{
+    av_unused AVVkFrameInternal *internal = f->internal;
+
+#if CONFIG_CUDA
+    if (internal->cuda_fc_ref) {
+        AVHWFramesContext *cuda_fc = (AVHWFramesContext *)internal->cuda_fc_ref->data;
+        int planes = av_pix_fmt_count_planes(cuda_fc->sw_format);
+        AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx;
+        AVCUDADeviceContext *cuda_dev = cuda_cu->hwctx;
+        AVCUDADeviceContextInternal *cu_internal = cuda_dev->internal;
+        CudaFunctions *cu = cu_internal->cuda_dl;
+
+        for (int i = 0; i < planes; i++) {
+            if (internal->cu_sem[i])
+                CHECK_CU(cu->cuDestroyExternalSemaphore(internal->cu_sem[i]));
+            if (internal->cu_mma[i])
+                CHECK_CU(cu->cuMipmappedArrayDestroy(internal->cu_mma[i]));
+            if (internal->ext_mem[i])
+                CHECK_CU(cu->cuDestroyExternalMemory(internal->ext_mem[i]));
+#ifdef _WIN32
+            if (internal->ext_sem_handle[i])
+                CloseHandle(internal->ext_sem_handle[i]);
+            if (internal->ext_mem_handle[i])
+                CloseHandle(internal->ext_mem_handle[i]);
+#endif
+        }
+
+        av_buffer_unref(&internal->cuda_fc_ref);
+    }
+#endif
+
+    pthread_mutex_destroy(&internal->update_mutex);
+    av_freep(&f->internal);
+}
+
+static void vulkan_frame_free(AVHWFramesContext *hwfc, AVVkFrame *f)
+{
+    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+    AVVulkanDeviceContext *hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+    int nb_images = ff_vk_count_images(f);
+    int nb_sems = 0;
+
+    while (nb_sems < FF_ARRAY_ELEMS(f->sem) && f->sem[nb_sems])
+        nb_sems++;
+
+    if (nb_sems) {
+        VkSemaphoreWaitInfo sem_wait = {
+            .sType          = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
+            .flags          = 0x0,
+            .pSemaphores    = f->sem,
+            .pValues        = f->sem_value,
+            .semaphoreCount = nb_sems,
+        };
+
+        vk->WaitSemaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
+    }
+
+    vulkan_free_internal(f);
+
+    for (int i = 0; i < nb_images; i++) {
+        vk->DestroyImage(hwctx->act_dev,     f->img[i], hwctx->alloc);
+        vk->FreeMemory(hwctx->act_dev,       f->mem[i], hwctx->alloc);
+        vk->DestroySemaphore(hwctx->act_dev, f->sem[i], hwctx->alloc);
+    }
+
+    av_free(f);
+}
+
+static void vulkan_frame_free_cb(void *opaque, uint8_t *data)
+{
+    vulkan_frame_free(opaque, (AVVkFrame*)data);
+}
+
+static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f,
+                          void *alloc_pnext, size_t alloc_pnext_stride)
+{
+    int img_cnt = 0, err;
+    VkResult ret;
+    AVHWDeviceContext *ctx = hwfc->device_ctx;
+    VulkanDevicePriv *p = ctx->hwctx;
+    AVVulkanDeviceContext *hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+    VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { { 0 } };
+
+    while (f->img[img_cnt]) {
+        int use_ded_mem;
+        VkImageMemoryRequirementsInfo2 req_desc = {
+            .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
+            .image = f->img[img_cnt],
+        };
+        VkMemoryDedicatedAllocateInfo ded_alloc = {
+            .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
+            .pNext = (void *)(((uint8_t *)alloc_pnext) + img_cnt*alloc_pnext_stride),
+        };
+        VkMemoryDedicatedRequirements ded_req = {
+            .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
+        };
+        VkMemoryRequirements2 req = {
+            .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
+            .pNext = &ded_req,
+        };
+
+        vk->GetImageMemoryRequirements2(hwctx->act_dev, &req_desc, &req);
+
+        if (f->tiling == VK_IMAGE_TILING_LINEAR)
+            req.memoryRequirements.size = FFALIGN(req.memoryRequirements.size,
+                                                  p->props.properties.limits.minMemoryMapAlignment);
+
+        /* In case the implementation prefers/requires dedicated allocation */
+        use_ded_mem = ded_req.prefersDedicatedAllocation |
+                      ded_req.requiresDedicatedAllocation;
+        if (use_ded_mem)
+            ded_alloc.image = f->img[img_cnt];
+
+        /* Allocate memory */
+        if ((err = alloc_mem(ctx, &req.memoryRequirements,
+                             f->tiling == VK_IMAGE_TILING_LINEAR ?
+                             VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
+                             VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
+                             use_ded_mem ? &ded_alloc : (void *)ded_alloc.pNext,
+                             &f->flags, &f->mem[img_cnt])))
+            return err;
+
+        f->size[img_cnt] = req.memoryRequirements.size;
+        bind_info[img_cnt].sType  = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
+        bind_info[img_cnt].image  = f->img[img_cnt];
+        bind_info[img_cnt].memory = f->mem[img_cnt];
+
+        img_cnt++;
+    }
+
+    /* Bind the allocated memory to the images */
+    ret = vk->BindImageMemory2(hwctx->act_dev, img_cnt, bind_info);
+    if (ret != VK_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to bind memory: %s\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+enum PrepMode {
+    PREP_MODE_GENERAL,
+    PREP_MODE_WRITE,
+    PREP_MODE_EXTERNAL_EXPORT,
+    PREP_MODE_EXTERNAL_IMPORT,
+    PREP_MODE_DECODING_DST,
+    PREP_MODE_DECODING_DPB,
+    PREP_MODE_ENCODING_DPB,
+};
+
+static int prepare_frame(AVHWFramesContext *hwfc, FFVkExecPool *ectx,
+                         AVVkFrame *frame, enum PrepMode pmode)
+{
+    int err;
+    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+    VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS];
+    int nb_img_bar = 0;
+
+    uint32_t dst_qf = p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0];
+    VkImageLayout new_layout;
+    VkAccessFlags2 new_access;
+    VkPipelineStageFlagBits2 src_stage = VK_PIPELINE_STAGE_2_NONE;
+
+    /* This is dirty - but it works. The vulkan.c dependency system doesn't
+     * free non-refcounted frames, and non-refcounted hardware frames cannot
+     * happen anywhere outside of here. */
+    AVBufferRef tmp_ref = {
+        .data = (uint8_t *)hwfc,
+    };
+    AVFrame tmp_frame = {
+        .data[0] = (uint8_t *)frame,
+        .hw_frames_ctx = &tmp_ref,
+    };
+
+    VkCommandBuffer cmd_buf;
+    FFVkExecContext *exec = ff_vk_exec_get(&p->vkctx, ectx);
+    cmd_buf = exec->buf;
+    ff_vk_exec_start(&p->vkctx, exec);
+
+    err = ff_vk_exec_add_dep_frame(&p->vkctx, exec, &tmp_frame,
+                                   VK_PIPELINE_STAGE_2_NONE,
+                                   VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
+    if (err < 0)
+        return err;
+
+    switch (pmode) {
+    case PREP_MODE_GENERAL:
+        new_layout = VK_IMAGE_LAYOUT_GENERAL;
+        new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
+        break;
+    case PREP_MODE_WRITE:
+        new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+        new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
+        break;
+    case PREP_MODE_EXTERNAL_IMPORT:
+        new_layout = VK_IMAGE_LAYOUT_GENERAL;
+        new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
+        break;
+    case PREP_MODE_EXTERNAL_EXPORT:
+        new_layout = VK_IMAGE_LAYOUT_GENERAL;
+        new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
+        dst_qf     = VK_QUEUE_FAMILY_EXTERNAL_KHR;
+        src_stage  = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
+        break;
+    case PREP_MODE_DECODING_DST:
+        new_layout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR;
+        new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
+        break;
+    case PREP_MODE_DECODING_DPB:
+        new_layout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR;
+        new_access = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
+        break;
+    case PREP_MODE_ENCODING_DPB:
+        new_layout = VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR;
+        new_access = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
+        break;
+    }
+
+    ff_vk_frame_barrier(&p->vkctx, exec, &tmp_frame, img_bar, &nb_img_bar,
+                        src_stage,
+                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                        new_access, new_layout, dst_qf);
+
+    vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+            .pImageMemoryBarriers = img_bar,
+            .imageMemoryBarrierCount = nb_img_bar,
+        });
+
+    err = ff_vk_exec_submit(&p->vkctx, exec);
+    if (err < 0)
+        return err;
+
+    /* We can do this because there are no real dependencies */
+    ff_vk_exec_discard_deps(&p->vkctx, exec);
+
+    return 0;
+}
+
+static inline void get_plane_wh(uint32_t *w, uint32_t *h, enum AVPixelFormat format,
+                                int frame_w, int frame_h, int plane)
+{
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format);
+
+    /* Currently always true unless gray + alpha support is added */
+    if (!plane || (plane == 3) || desc->flags & AV_PIX_FMT_FLAG_RGB ||
+        !(desc->flags & AV_PIX_FMT_FLAG_PLANAR)) {
+        *w = frame_w;
+        *h = frame_h;
+        return;
+    }
+
+    *w = AV_CEIL_RSHIFT(frame_w, desc->log2_chroma_w);
+    *h = AV_CEIL_RSHIFT(frame_h, desc->log2_chroma_h);
+}
+
+static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame,
+                        VkImageTiling tiling, VkImageUsageFlagBits usage,
+                        VkImageCreateFlags flags, int nb_layers,
+                        void *create_pnext)
+{
+    int err;
+    VkResult ret;
+    AVVulkanFramesContext *hwfc_vk = hwfc->hwctx;
+    AVHWDeviceContext *ctx = hwfc->device_ctx;
+    VulkanDevicePriv *p = ctx->hwctx;
+    AVVulkanDeviceContext *hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+    AVVkFrame *f;
+
+    VkSemaphoreTypeCreateInfo sem_type_info = {
+        .sType         = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
+        .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
+        .initialValue  = 0,
+    };
+    VkSemaphoreCreateInfo sem_spawn = {
+        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+        .pNext = &sem_type_info,
+    };
+
+    VkExportSemaphoreCreateInfo ext_sem_info_opaque = {
+        .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
+#ifdef _WIN32
+        .handleTypes = IsWindows8OrGreater()
+            ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
+            : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
+#else
+        .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
+#endif
+    };
+
+    /* Check if exporting is supported before chaining any structs */
+    if (p->ext_sem_props_opaque.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) {
+        if (p->vkctx.extensions & (FF_VK_EXT_EXTERNAL_WIN32_SEM | FF_VK_EXT_EXTERNAL_FD_SEM))
+            ff_vk_link_struct(&sem_type_info, &ext_sem_info_opaque);
+    }
+
+    f = av_vk_frame_alloc();
+    if (!f) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to allocate memory for AVVkFrame!\n");
+        return AVERROR(ENOMEM);
+    }
+
+    // TODO: check width and height for alignment in case of multiplanar (must be mod-2 if subsampled)
+
+    /* Create the images */
+    for (int i = 0; (hwfc_vk->format[i] != VK_FORMAT_UNDEFINED); i++) {
+        VkImageCreateInfo create_info = {
+            .sType                 = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+            .pNext                 = create_pnext,
+            .imageType             = VK_IMAGE_TYPE_2D,
+            .format                = hwfc_vk->format[i],
+            .extent.depth          = 1,
+            .mipLevels             = 1,
+            .arrayLayers           = nb_layers,
+            .flags                 = flags,
+            .tiling                = tiling,
+            .initialLayout         = VK_IMAGE_LAYOUT_UNDEFINED,
+            .usage                 = usage,
+            .samples               = VK_SAMPLE_COUNT_1_BIT,
+            .pQueueFamilyIndices   = p->img_qfs,
+            .queueFamilyIndexCount = p->nb_img_qfs,
+            .sharingMode           = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
+                                                         VK_SHARING_MODE_EXCLUSIVE,
+        };
+
+        get_plane_wh(&create_info.extent.width, &create_info.extent.height,
+                     hwfc->sw_format, hwfc->width, hwfc->height, i);
+
+        ret = vk->CreateImage(hwctx->act_dev, &create_info,
+                              hwctx->alloc, &f->img[i]);
+        if (ret != VK_SUCCESS) {
+            av_log(ctx, AV_LOG_ERROR, "Image creation failure: %s\n",
+                   ff_vk_ret2str(ret));
+            err = AVERROR(EINVAL);
+            goto fail;
+        }
+
+        /* Create semaphore */
+        ret = vk->CreateSemaphore(hwctx->act_dev, &sem_spawn,
+                                  hwctx->alloc, &f->sem[i]);
+        if (ret != VK_SUCCESS) {
+            av_log(hwctx, AV_LOG_ERROR, "Failed to create semaphore: %s\n",
+                   ff_vk_ret2str(ret));
+            err = AVERROR_EXTERNAL;
+            goto fail;
+        }
+
+        f->queue_family[i] = p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0];
+        f->layout[i] = create_info.initialLayout;
+        f->access[i] = 0x0;
+        f->sem_value[i] = 0;
+    }
+
+    f->flags     = 0x0;
+    f->tiling    = tiling;
+
+    *frame = f;
+    return 0;
+
+fail:
+    vulkan_frame_free(hwfc, f);
+    return err;
+}
+
+/* Checks if an export flag is enabled, and if it is ORs it with *iexp */
+static void try_export_flags(AVHWFramesContext *hwfc,
+                             VkExternalMemoryHandleTypeFlags *comp_handle_types,
+                             VkExternalMemoryHandleTypeFlagBits *iexp,
+                             VkExternalMemoryHandleTypeFlagBits exp)
+{
+    VkResult ret;
+    AVVulkanFramesContext *hwctx = hwfc->hwctx;
+    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+    AVVulkanDeviceContext *dev_hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+
+    const VkImageDrmFormatModifierListCreateInfoEXT *drm_mod_info =
+        ff_vk_find_struct(hwctx->create_pnext,
+                          VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
+    int has_mods = hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && drm_mod_info;
+    int nb_mods;
+
+    VkExternalImageFormatProperties eprops = {
+        .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
+    };
+    VkImageFormatProperties2 props = {
+        .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
+        .pNext = &eprops,
+    };
+    VkPhysicalDeviceImageDrmFormatModifierInfoEXT phy_dev_mod_info = {
+        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
+        .pNext = NULL,
+        .pQueueFamilyIndices   = p->img_qfs,
+        .queueFamilyIndexCount = p->nb_img_qfs,
+        .sharingMode           = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
+                                                     VK_SHARING_MODE_EXCLUSIVE,
+    };
+    VkPhysicalDeviceExternalImageFormatInfo enext = {
+        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
+        .handleType = exp,
+        .pNext = has_mods ? &phy_dev_mod_info : NULL,
+    };
+    VkPhysicalDeviceImageFormatInfo2 pinfo = {
+        .sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
+        .pNext  = !exp ? NULL : &enext,
+        .format = vk_find_format_entry(hwfc->sw_format)->vkf,
+        .type   = VK_IMAGE_TYPE_2D,
+        .tiling = hwctx->tiling,
+        .usage  = hwctx->usage,
+        .flags  = VK_IMAGE_CREATE_ALIAS_BIT,
+    };
+
+    nb_mods = has_mods ? drm_mod_info->drmFormatModifierCount : 1;
+    for (int i = 0; i < nb_mods; i++) {
+        if (has_mods)
+            phy_dev_mod_info.drmFormatModifier = drm_mod_info->pDrmFormatModifiers[i];
+
+        ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev,
+                                                        &pinfo, &props);
+
+        if (ret == VK_SUCCESS) {
+            *iexp |= exp;
+            *comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes;
+        }
+    }
+}
+
+static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size)
+{
+    int err;
+    AVVkFrame *f;
+    AVBufferRef *avbuf = NULL;
+    AVHWFramesContext *hwfc = opaque;
+    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+    VulkanFramesPriv *fp = hwfc->hwctx;
+    AVVulkanFramesContext *hwctx = &fp->p;
+    VkExternalMemoryHandleTypeFlags e = 0x0;
+    VkExportMemoryAllocateInfo eminfo[AV_NUM_DATA_POINTERS];
+
+    VkExternalMemoryImageCreateInfo eiinfo = {
+        .sType       = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
+        .pNext       = hwctx->create_pnext,
+    };
+
+#ifdef _WIN32
+    if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY)
+        try_export_flags(hwfc, &eiinfo.handleTypes, &e, IsWindows8OrGreater()
+                             ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
+                             : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT);
+#else
+    if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY)
+        try_export_flags(hwfc, &eiinfo.handleTypes, &e,
+                         VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT);
+
+    if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_DMABUF_MEMORY &&
+        hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
+        try_export_flags(hwfc, &eiinfo.handleTypes, &e,
+                         VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
+#endif
+
+    for (int i = 0; i < av_pix_fmt_count_planes(hwfc->sw_format); i++) {
+        eminfo[i].sType       = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO;
+        eminfo[i].pNext       = hwctx->alloc_pnext[i];
+        eminfo[i].handleTypes = e;
+    }
+
+    err = create_frame(hwfc, &f, hwctx->tiling, hwctx->usage, hwctx->img_flags,
+                       hwctx->nb_layers,
+                       eiinfo.handleTypes ? &eiinfo : hwctx->create_pnext);
+    if (err)
+        return NULL;
+
+    err = alloc_bind_mem(hwfc, f, eminfo, sizeof(*eminfo));
+    if (err)
+        goto fail;
+
+    if ( (hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR) &&
+        !(hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR))
+        err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_DECODING_DPB);
+    else if (hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)
+        err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_DECODING_DST);
+    else if (hwctx->usage & VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR)
+        err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_ENCODING_DPB);
+    else if (hwctx->usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)
+        err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_WRITE);
+    else
+        err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_GENERAL);
+    if (err)
+        goto fail;
+
+    avbuf = av_buffer_create((uint8_t *)f, sizeof(AVVkFrame),
+                             vulkan_frame_free_cb, hwfc, 0);
+    if (!avbuf)
+        goto fail;
+
+    return avbuf;
+
+fail:
+    vulkan_frame_free(hwfc, f);
+    return NULL;
+}
+
+static void lock_frame(AVHWFramesContext *fc, AVVkFrame *vkf)
+{
+    pthread_mutex_lock(&vkf->internal->update_mutex);
+}
+
+static void unlock_frame(AVHWFramesContext *fc, AVVkFrame *vkf)
+{
+    pthread_mutex_unlock(&vkf->internal->update_mutex);
+}
+
+static void vulkan_frames_uninit(AVHWFramesContext *hwfc)
+{
+    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+    VulkanFramesPriv *fp = hwfc->hwctx;
+
+    if (fp->modifier_info) {
+        if (fp->modifier_info->pDrmFormatModifiers)
+            av_freep(&fp->modifier_info->pDrmFormatModifiers);
+        av_freep(&fp->modifier_info);
+    }
+
+    ff_vk_exec_pool_free(&p->vkctx, &fp->compute_exec);
+    ff_vk_exec_pool_free(&p->vkctx, &fp->upload_exec);
+    ff_vk_exec_pool_free(&p->vkctx, &fp->download_exec);
+
+    av_buffer_pool_uninit(&fp->tmp);
+}
+
+static int vulkan_frames_init(AVHWFramesContext *hwfc)
+{
+    int err;
+    AVVkFrame *f;
+    VulkanFramesPriv *fp = hwfc->hwctx;
+    AVVulkanFramesContext *hwctx = &fp->p;
+    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+    AVVulkanDeviceContext *dev_hwctx = &p->p;
+    VkImageUsageFlagBits supported_usage;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+    const struct FFVkFormatEntry *fmt;
+    int disable_multiplane = p->disable_multiplane ||
+                             (hwctx->flags & AV_VK_FRAME_FLAG_DISABLE_MULTIPLANE);
+
+    /* Defaults */
+    if (!hwctx->nb_layers)
+        hwctx->nb_layers = 1;
+
+    /* VK_IMAGE_TILING_OPTIMAL == 0, can't check for it really */
+    if (p->use_linear_images &&
+        (hwctx->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT))
+        hwctx->tiling = VK_IMAGE_TILING_LINEAR;
+
+
+    fmt = vk_find_format_entry(hwfc->sw_format);
+    if (!fmt) {
+        av_log(hwfc, AV_LOG_ERROR, "Unsupported pixel format: %s!\n",
+               av_get_pix_fmt_name(hwfc->sw_format));
+        return AVERROR(EINVAL);
+    }
+
+    if (hwctx->format[0] != VK_FORMAT_UNDEFINED) {
+        if (hwctx->format[0] != fmt->vkf) {
+            for (int i = 0; i < fmt->nb_images_fallback; i++) {
+                if (hwctx->format[i] != fmt->fallback[i]) {
+                    av_log(hwfc, AV_LOG_ERROR, "Incompatible Vulkan format given "
+                           "for the current sw_format %s!\n",
+                           av_get_pix_fmt_name(hwfc->sw_format));
+                    return AVERROR(EINVAL);
+                }
+            }
+        }
+
+        /* Check if the sw_format itself is supported */
+        err = vkfmt_from_pixfmt2(hwfc->device_ctx, hwfc->sw_format,
+                                 hwctx->tiling, NULL,
+                                 NULL, NULL, &supported_usage, 0,
+                                 !hwctx->usage ||
+                                 (hwctx->usage & VK_IMAGE_USAGE_STORAGE_BIT));
+        if (err < 0) {
+            av_log(hwfc, AV_LOG_ERROR, "Unsupported sw format: %s!\n",
+                   av_get_pix_fmt_name(hwfc->sw_format));
+            return AVERROR(EINVAL);
+        }
+    } else {
+        err = vkfmt_from_pixfmt2(hwfc->device_ctx, hwfc->sw_format,
+                                 hwctx->tiling, hwctx->format, NULL,
+                                 NULL, &supported_usage,
+                                 disable_multiplane,
+                                 !hwctx->usage ||
+                                 (hwctx->usage & VK_IMAGE_USAGE_STORAGE_BIT));
+        if (err < 0)
+            return err;
+    }
+
+    /* Nvidia is violating the spec because they thought no one would use this. */
+    if (p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
+        (((fmt->nb_images == 1) && (fmt->vk_planes > 1)) ||
+         (av_pix_fmt_desc_get(hwfc->sw_format)->nb_components == 1)))
+        supported_usage &= ~VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
+
+    /* Image usage flags */
+    if (!hwctx->usage) {
+        hwctx->usage = supported_usage & (VK_IMAGE_USAGE_TRANSFER_DST_BIT |
+                                          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) && !p->disable_host_transfer)
+            hwctx->usage |= supported_usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
+
+        /* 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.
+     * Only fill them in automatically if the image is not going to be used as
+     * a DPB-only image, and we have SAMPLED/STORAGE bits set. */
+    if (!hwctx->img_flags) {
+        int is_lone_dpb = ((hwctx->usage & VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR) ||
+                           ((hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR) &&
+                            !(hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)));
+        int sampleable = hwctx->usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
+                                         VK_IMAGE_USAGE_STORAGE_BIT);
+        hwctx->img_flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
+        if (sampleable && !is_lone_dpb) {
+            hwctx->img_flags |= VK_IMAGE_CREATE_ALIAS_BIT;
+            if ((fmt->vk_planes > 1) && (hwctx->format[0] == fmt->vkf))
+                hwctx->img_flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
+        }
+    }
+
+    /* 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->vkctx.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE |
+                                FF_VK_EXT_VIDEO_MAINTENANCE_1))) {
+        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;
+
+    if (!hwctx->unlock_frame)
+        hwctx->unlock_frame = unlock_frame;
+
+    err = ff_vk_exec_pool_init(&p->vkctx, p->compute_qf, &fp->compute_exec,
+                               p->compute_qf->num, 0, 0, 0, NULL);
+    if (err)
+        return err;
+
+    err = ff_vk_exec_pool_init(&p->vkctx, p->transfer_qf, &fp->upload_exec,
+                               p->transfer_qf->num*2, 0, 0, 0, NULL);
+    if (err)
+        return err;
+
+    err = ff_vk_exec_pool_init(&p->vkctx, p->transfer_qf, &fp->download_exec,
+                               p->transfer_qf->num, 0, 0, 0, NULL);
+    if (err)
+        return err;
+
+    /* Test to see if allocation will fail */
+    err = create_frame(hwfc, &f, hwctx->tiling, hwctx->usage, hwctx->img_flags,
+                       hwctx->nb_layers, hwctx->create_pnext);
+    if (err)
+        return err;
+
+    /* Collect `VkDrmFormatModifierPropertiesEXT` for each plane. Required for DRM export. */
+    if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS && hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
+        VkImageDrmFormatModifierPropertiesEXT drm_mod = {
+            .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
+        };
+        err = vk->GetImageDrmFormatModifierPropertiesEXT(dev_hwctx->act_dev, f->img[0],
+                                                        &drm_mod);
+        if (err != VK_SUCCESS) {
+            av_log(hwfc, AV_LOG_ERROR, "Failed to get image DRM format modifier properties");
+            vulkan_frame_free(hwfc, f);
+            return AVERROR_EXTERNAL;
+        }
+        for (int i = 0; i < fmt->vk_planes; ++i) {
+            VkDrmFormatModifierPropertiesListEXT modp;
+            VkFormatProperties2 fmtp;
+            VkDrmFormatModifierPropertiesEXT *mod_props = NULL;
+
+            modp = (VkDrmFormatModifierPropertiesListEXT) {
+                .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
+            };
+            fmtp = (VkFormatProperties2) {
+                .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
+                .pNext = &modp,
+            };
+
+            /* query drmFormatModifierCount by keeping pDrmFormatModifierProperties NULL */
+            vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev, fmt->fallback[i], &fmtp);
+
+            modp.pDrmFormatModifierProperties =
+                av_calloc(modp.drmFormatModifierCount, sizeof(*modp.pDrmFormatModifierProperties));
+            if (!modp.pDrmFormatModifierProperties) {
+                vulkan_frame_free(hwfc, f);
+                return AVERROR(ENOMEM);
+            }
+            vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev, fmt->fallback[i], &fmtp);
+
+            for (uint32_t i = 0; i < modp.drmFormatModifierCount; ++i) {
+                VkDrmFormatModifierPropertiesEXT *m = &modp.pDrmFormatModifierProperties[i];
+                if (m->drmFormatModifier == drm_mod.drmFormatModifier) {
+                    mod_props = m;
+                    break;
+                }
+            }
+
+            if (mod_props == NULL) {
+                av_log(hwfc, AV_LOG_ERROR, "No DRM format modifier properties found for modifier 0x%016"PRIx64"\n",
+                          drm_mod.drmFormatModifier);
+                av_free(modp.pDrmFormatModifierProperties);
+                vulkan_frame_free(hwfc, f);
+                return AVERROR_EXTERNAL;
+            }
+
+            fp->drm_format_modifier_properties[i] = *mod_props;
+            av_free(modp.pDrmFormatModifierProperties);
+        }
+    }
+
+    vulkan_frame_free(hwfc, f);
+
+    /* If user did not specify a pool, hwfc->pool will be set to the internal one
+     * in hwcontext.c just after this gets called */
+    if (!hwfc->pool) {
+        ffhwframesctx(hwfc)->pool_internal = av_buffer_pool_init2(sizeof(AVVkFrame),
+                                                                  hwfc, vulkan_pool_alloc,
+                                                                  NULL);
+        if (!ffhwframesctx(hwfc)->pool_internal)
+            return AVERROR(ENOMEM);
+    }
+
+    return 0;
+}
+
+static int vulkan_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
+{
+    frame->buf[0] = av_buffer_pool_get(hwfc->pool);
+    if (!frame->buf[0])
+        return AVERROR(ENOMEM);
+
+    frame->data[0] = frame->buf[0]->data;
+    frame->format  = AV_PIX_FMT_VULKAN;
+    frame->width   = hwfc->width;
+    frame->height  = hwfc->height;
+
+    return 0;
+}
+
+static int vulkan_transfer_get_formats(AVHWFramesContext *hwfc,
+                                       enum AVHWFrameTransferDirection dir,
+                                       enum AVPixelFormat **formats)
+{
+    enum AVPixelFormat *fmts;
+    int n = 2;
+
+#if CONFIG_CUDA
+    n++;
+#endif
+    fmts = av_malloc_array(n, sizeof(*fmts));
+    if (!fmts)
+        return AVERROR(ENOMEM);
+
+    n = 0;
+    fmts[n++] = hwfc->sw_format;
+#if CONFIG_CUDA
+    fmts[n++] = AV_PIX_FMT_CUDA;
+#endif
+    fmts[n++] = AV_PIX_FMT_NONE;
+
+    *formats = fmts;
+    return 0;
+}
+
+#if CONFIG_LIBDRM
+static void vulkan_unmap_from_drm(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap)
+{
+    vulkan_frame_free(hwfc, hwmap->priv);
+}
+
+static const struct {
+    uint32_t drm_fourcc;
+    VkFormat vk_format;
+} vulkan_drm_format_map[] = {
+    { DRM_FORMAT_R8,       VK_FORMAT_R8_UNORM       },
+    { DRM_FORMAT_R16,      VK_FORMAT_R16_UNORM      },
+    { DRM_FORMAT_GR88,     VK_FORMAT_R8G8_UNORM     },
+    { DRM_FORMAT_RG88,     VK_FORMAT_R8G8_UNORM     },
+    { DRM_FORMAT_GR1616,   VK_FORMAT_R16G16_UNORM   },
+    { DRM_FORMAT_RG1616,   VK_FORMAT_R16G16_UNORM   },
+    { DRM_FORMAT_ARGB8888, VK_FORMAT_B8G8R8A8_UNORM },
+    { DRM_FORMAT_XRGB8888, VK_FORMAT_B8G8R8A8_UNORM },
+    { DRM_FORMAT_ABGR8888, VK_FORMAT_R8G8B8A8_UNORM },
+    { DRM_FORMAT_XBGR8888, VK_FORMAT_R8G8B8A8_UNORM },
+    { DRM_FORMAT_ARGB2101010, VK_FORMAT_A2B10G10R10_UNORM_PACK32 },
+    { DRM_FORMAT_ABGR2101010, VK_FORMAT_A2R10G10B10_UNORM_PACK32 },
+    { DRM_FORMAT_XRGB2101010, VK_FORMAT_A2B10G10R10_UNORM_PACK32 },
+    { DRM_FORMAT_XBGR2101010, VK_FORMAT_A2R10G10B10_UNORM_PACK32 },
+
+    // All these DRM_FORMATs were added in the same libdrm commit.
+#ifdef DRM_FORMAT_XYUV8888
+    { DRM_FORMAT_XYUV8888, VK_FORMAT_R8G8B8A8_UNORM     },
+    { DRM_FORMAT_XVYU2101010, VK_FORMAT_A2R10G10B10_UNORM_PACK32 } ,
+    { DRM_FORMAT_XVYU12_16161616, VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 } ,
+    { DRM_FORMAT_XVYU16161616, VK_FORMAT_R16G16B16A16_UNORM } ,
+#endif
+};
+
+static inline VkFormat drm_to_vulkan_fmt(uint32_t drm_fourcc)
+{
+    for (int i = 0; i < FF_ARRAY_ELEMS(vulkan_drm_format_map); i++)
+        if (vulkan_drm_format_map[i].drm_fourcc == drm_fourcc)
+            return vulkan_drm_format_map[i].vk_format;
+    return VK_FORMAT_UNDEFINED;
+}
+
+static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **frame,
+                                          const AVFrame *src, int flags)
+{
+    int err = 0;
+    VkResult ret;
+    AVVkFrame *f;
+    int bind_counts = 0;
+    AVHWDeviceContext *ctx = hwfc->device_ctx;
+    VulkanDevicePriv *p = ctx->hwctx;
+    AVVulkanDeviceContext *hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+    const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)src->data[0];
+    VkBindImageMemoryInfo bind_info[AV_DRM_MAX_PLANES];
+    VkBindImagePlaneMemoryInfo plane_info[AV_DRM_MAX_PLANES];
+
+    for (int i = 0; i < desc->nb_layers; i++) {
+        if (drm_to_vulkan_fmt(desc->layers[i].format) == VK_FORMAT_UNDEFINED) {
+            av_log(ctx, AV_LOG_ERROR, "Unsupported DMABUF layer format %#08x!\n",
+                   desc->layers[i].format);
+            return AVERROR(EINVAL);
+        }
+    }
+
+    if (!(f = av_vk_frame_alloc())) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to allocate memory for AVVkFrame!\n");
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    f->tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
+
+    for (int i = 0; i < desc->nb_layers; i++) {
+        const int planes = desc->layers[i].nb_planes;
+
+        /* Semaphore */
+        VkSemaphoreTypeCreateInfo sem_type_info = {
+            .sType         = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
+            .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
+            .initialValue  = 0,
+        };
+        VkSemaphoreCreateInfo sem_spawn = {
+            .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+            .pNext = &sem_type_info,
+        };
+
+        /* Image creation */
+        VkSubresourceLayout ext_img_layouts[AV_DRM_MAX_PLANES];
+        VkImageDrmFormatModifierExplicitCreateInfoEXT ext_img_mod_spec = {
+            .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
+            .drmFormatModifier = desc->objects[0].format_modifier,
+            .drmFormatModifierPlaneCount = planes,
+            .pPlaneLayouts = (const VkSubresourceLayout *)&ext_img_layouts,
+        };
+        VkExternalMemoryImageCreateInfo ext_img_spec = {
+            .sType       = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
+            .pNext       = &ext_img_mod_spec,
+            .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
+        };
+        VkImageCreateInfo create_info = {
+            .sType                 = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+            .pNext                 = &ext_img_spec,
+            .imageType             = VK_IMAGE_TYPE_2D,
+            .format                = drm_to_vulkan_fmt(desc->layers[i].format),
+            .extent.depth          = 1,
+            .mipLevels             = 1,
+            .arrayLayers           = 1,
+            .flags                 = 0x0,
+            .tiling                = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
+            .initialLayout         = VK_IMAGE_LAYOUT_UNDEFINED, /* specs say so */
+            .usage                 = 0x0, /* filled in below */
+            .samples               = VK_SAMPLE_COUNT_1_BIT,
+            .pQueueFamilyIndices   = p->img_qfs,
+            .queueFamilyIndexCount = p->nb_img_qfs,
+            .sharingMode           = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
+                                                         VK_SHARING_MODE_EXCLUSIVE,
+        };
+
+        /* Image format verification */
+        VkExternalImageFormatProperties ext_props = {
+            .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
+        };
+        VkImageFormatProperties2 props_ret = {
+            .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
+            .pNext = &ext_props,
+        };
+        VkPhysicalDeviceImageDrmFormatModifierInfoEXT props_drm_mod = {
+            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
+            .drmFormatModifier = ext_img_mod_spec.drmFormatModifier,
+            .pQueueFamilyIndices = create_info.pQueueFamilyIndices,
+            .queueFamilyIndexCount = create_info.queueFamilyIndexCount,
+            .sharingMode = create_info.sharingMode,
+        };
+        VkPhysicalDeviceExternalImageFormatInfo props_ext = {
+            .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
+            .pNext = &props_drm_mod,
+            .handleType = ext_img_spec.handleTypes,
+        };
+        VkPhysicalDeviceImageFormatInfo2 fmt_props;
+
+        if (flags & AV_HWFRAME_MAP_READ)
+            create_info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT |
+                                 VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+        if (flags & AV_HWFRAME_MAP_WRITE)
+            create_info.usage |= VK_IMAGE_USAGE_STORAGE_BIT |
+                                 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+
+        fmt_props = (VkPhysicalDeviceImageFormatInfo2) {
+            .sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
+            .pNext  = &props_ext,
+            .format = create_info.format,
+            .type   = create_info.imageType,
+            .tiling = create_info.tiling,
+            .usage  = create_info.usage,
+            .flags  = create_info.flags,
+        };
+
+        /* Check if importing is possible for this combination of parameters */
+        ret = vk->GetPhysicalDeviceImageFormatProperties2(hwctx->phys_dev,
+                                                          &fmt_props, &props_ret);
+        if (ret != VK_SUCCESS) {
+            av_log(ctx, AV_LOG_ERROR, "Cannot map DRM frame to Vulkan: %s\n",
+                   ff_vk_ret2str(ret));
+            err = AVERROR_EXTERNAL;
+            goto fail;
+        }
+
+        /* Set the image width/height */
+        get_plane_wh(&create_info.extent.width, &create_info.extent.height,
+                     hwfc->sw_format, src->width, src->height, i);
+
+        /* Set the subresource layout based on the layer properties */
+        for (int j = 0; j < planes; j++) {
+            ext_img_layouts[j].offset     = desc->layers[i].planes[j].offset;
+            ext_img_layouts[j].rowPitch   = desc->layers[i].planes[j].pitch;
+            ext_img_layouts[j].size       = 0; /* The specs say so for all 3 */
+            ext_img_layouts[j].arrayPitch = 0;
+            ext_img_layouts[j].depthPitch = 0;
+        }
+
+        /* Create image */
+        ret = vk->CreateImage(hwctx->act_dev, &create_info,
+                              hwctx->alloc, &f->img[i]);
+        if (ret != VK_SUCCESS) {
+            av_log(ctx, AV_LOG_ERROR, "Image creation failure: %s\n",
+                   ff_vk_ret2str(ret));
+            err = AVERROR(EINVAL);
+            goto fail;
+        }
+
+        ret = vk->CreateSemaphore(hwctx->act_dev, &sem_spawn,
+                                  hwctx->alloc, &f->sem[i]);
+        if (ret != VK_SUCCESS) {
+            av_log(hwctx, AV_LOG_ERROR, "Failed to create semaphore: %s\n",
+                   ff_vk_ret2str(ret));
+            err = AVERROR_EXTERNAL;
+            goto fail;
+        }
+
+        f->queue_family[i] = VK_QUEUE_FAMILY_EXTERNAL;
+        f->layout[i] = create_info.initialLayout;
+        f->access[i] = 0x0;
+        f->sem_value[i] = 0;
+    }
+
+    for (int i = 0; i < desc->nb_layers; i++) {
+        /* Memory requirements */
+        VkImageMemoryRequirementsInfo2 req_desc = {
+            .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
+            .image = f->img[i],
+        };
+        VkMemoryDedicatedRequirements ded_req = {
+            .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
+        };
+        VkMemoryRequirements2 req2 = {
+            .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
+            .pNext = &ded_req,
+        };
+
+        /* Allocation/importing */
+        VkMemoryFdPropertiesKHR fdmp = {
+            .sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR,
+        };
+        /* This assumes that a layer will never be constructed from multiple
+         * objects. If that was to happen in the real world, this code would
+         * need to import each plane separately.
+         */
+        VkImportMemoryFdInfoKHR idesc = {
+            .sType      = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
+            .fd         = dup(desc->objects[desc->layers[i].planes[0].object_index].fd),
+            .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
+        };
+        VkMemoryDedicatedAllocateInfo ded_alloc = {
+            .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
+            .pNext = &idesc,
+            .image = req_desc.image,
+        };
+
+        /* Get object properties */
+        ret = vk->GetMemoryFdPropertiesKHR(hwctx->act_dev,
+                                           VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
+                                           idesc.fd, &fdmp);
+        if (ret != VK_SUCCESS) {
+            av_log(hwfc, AV_LOG_ERROR, "Failed to get FD properties: %s\n",
+                   ff_vk_ret2str(ret));
+            err = AVERROR_EXTERNAL;
+            close(idesc.fd);
+            goto fail;
+        }
+
+        vk->GetImageMemoryRequirements2(hwctx->act_dev, &req_desc, &req2);
+
+        /* Only a single bit must be set, not a range, and it must match */
+        req2.memoryRequirements.memoryTypeBits = fdmp.memoryTypeBits;
+
+        err = alloc_mem(ctx, &req2.memoryRequirements,
+                        VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
+                        (ded_req.prefersDedicatedAllocation ||
+                         ded_req.requiresDedicatedAllocation) ?
+                            &ded_alloc : ded_alloc.pNext,
+                        &f->flags, &f->mem[i]);
+        if (err) {
+            close(idesc.fd);
+            return err;
+        }
+
+        f->size[i] = req2.memoryRequirements.size;
+    }
+
+    for (int i = 0; i < desc->nb_layers; i++) {
+        const int planes = desc->layers[i].nb_planes;
+        for (int j = 0; j < planes; j++) {
+            VkImageAspectFlagBits aspect = j == 0 ? VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT :
+                                           j == 1 ? VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT :
+                                                    VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT;
+
+            plane_info[bind_counts].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO;
+            plane_info[bind_counts].pNext = NULL;
+            plane_info[bind_counts].planeAspect = aspect;
+
+            bind_info[bind_counts].sType  = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
+            bind_info[bind_counts].pNext  = planes > 1 ? &plane_info[bind_counts] : NULL;
+            bind_info[bind_counts].image  = f->img[i];
+            bind_info[bind_counts].memory = f->mem[i];
+
+            /* Offset is already signalled via pPlaneLayouts above */
+            bind_info[bind_counts].memoryOffset = 0;
+
+            bind_counts++;
+        }
+    }
+
+    /* Bind the allocated memory to the images */
+    ret = vk->BindImageMemory2(hwctx->act_dev, bind_counts, bind_info);
+    if (ret != VK_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to bind memory: %s\n",
+               ff_vk_ret2str(ret));
+        err = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+    *frame = f;
+
+    return 0;
+
+fail:
+    vulkan_frame_free(hwfc, f);
+
+    return err;
+}
+
+static int vulkan_map_from_drm_frame_sync(AVHWFramesContext *hwfc, AVFrame *dst,
+                                          const AVFrame *src, int flags)
+{
+    int err;
+    VkResult ret;
+    AVHWDeviceContext *ctx = hwfc->device_ctx;
+    VulkanDevicePriv *p = ctx->hwctx;
+    VulkanFramesPriv *fp = hwfc->hwctx;
+    AVVulkanDeviceContext *hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+
+    const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)src->data[0];
+
+#ifdef DMA_BUF_IOCTL_EXPORT_SYNC_FILE
+    if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_SEM) {
+        VkCommandBuffer cmd_buf;
+        FFVkExecContext *exec;
+        VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS];
+        VkSemaphore drm_sync_sem[AV_DRM_MAX_PLANES] = { 0 };
+        int nb_img_bar = 0;
+
+        for (int i = 0; i < desc->nb_objects; i++) {
+            VkSemaphoreTypeCreateInfo sem_type_info = {
+                .sType         = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
+                .semaphoreType = VK_SEMAPHORE_TYPE_BINARY,
+            };
+            VkSemaphoreCreateInfo sem_spawn = {
+                .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+                .pNext = &sem_type_info,
+            };
+            VkImportSemaphoreFdInfoKHR import_info;
+            struct dma_buf_export_sync_file implicit_fd_info = {
+                .flags = DMA_BUF_SYNC_READ,
+                .fd = -1,
+            };
+
+            if (ioctl(desc->objects[i].fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE,
+                      &implicit_fd_info)) {
+                err = AVERROR(errno);
+                av_log(hwctx, AV_LOG_ERROR, "Failed to retrieve implicit DRM sync file: %s\n",
+                       av_err2str(err));
+                for (; i >= 0; i--)
+                    vk->DestroySemaphore(hwctx->act_dev, drm_sync_sem[i], hwctx->alloc);
+                return err;
+            }
+
+            ret = vk->CreateSemaphore(hwctx->act_dev, &sem_spawn,
+                                      hwctx->alloc, &drm_sync_sem[i]);
+            if (ret != VK_SUCCESS) {
+                av_log(hwctx, AV_LOG_ERROR, "Failed to create semaphore: %s\n",
+                       ff_vk_ret2str(ret));
+                err = AVERROR_EXTERNAL;
+                for (; i >= 0; i--)
+                    vk->DestroySemaphore(hwctx->act_dev, drm_sync_sem[i], hwctx->alloc);
+                return err;
+            }
+
+            import_info = (VkImportSemaphoreFdInfoKHR) {
+                .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
+                .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
+                .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
+                .semaphore = drm_sync_sem[i],
+                .fd = implicit_fd_info.fd,
+            };
+
+            ret = vk->ImportSemaphoreFdKHR(hwctx->act_dev, &import_info);
+            if (ret != VK_SUCCESS) {
+                av_log(hwctx, AV_LOG_ERROR, "Failed to import semaphore: %s\n",
+                       ff_vk_ret2str(ret));
+                err = AVERROR_EXTERNAL;
+                for (; i >= 0; i--)
+                    vk->DestroySemaphore(hwctx->act_dev, drm_sync_sem[i], hwctx->alloc);
+                return err;
+            }
+        }
+
+        exec = ff_vk_exec_get(&p->vkctx, &fp->compute_exec);
+        cmd_buf = exec->buf;
+
+        ff_vk_exec_start(&p->vkctx, exec);
+
+        /* Ownership of semaphores is passed */
+        err = ff_vk_exec_add_dep_bool_sem(&p->vkctx, exec,
+                                          drm_sync_sem, desc->nb_objects,
+                                          VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, 1);
+        if (err < 0)
+            return err;
+
+        err = ff_vk_exec_add_dep_frame(&p->vkctx, exec, dst,
+                                       VK_PIPELINE_STAGE_2_NONE,
+                                       VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
+        if (err < 0)
+            return err;
+
+        ff_vk_frame_barrier(&p->vkctx, exec, dst, img_bar, &nb_img_bar,
+                            VK_PIPELINE_STAGE_2_NONE,
+                            VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                            ((flags & AV_HWFRAME_MAP_READ) ?
+                             VK_ACCESS_2_SHADER_SAMPLED_READ_BIT : 0x0) |
+                            ((flags & AV_HWFRAME_MAP_WRITE) ?
+                             VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT : 0x0),
+                            VK_IMAGE_LAYOUT_GENERAL,
+                            p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0]);
+
+        vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
+                .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+                .pImageMemoryBarriers = img_bar,
+                .imageMemoryBarrierCount = nb_img_bar,
+            });
+
+        err = ff_vk_exec_submit(&p->vkctx, exec);
+        if (err < 0)
+            return err;
+    } else
+#endif
+    {
+        AVVkFrame *f = (AVVkFrame *)dst->data[0];
+        av_log(hwctx, AV_LOG_WARNING, "No support for synchronization when importing DMA-BUFs, "
+                                      "image may be corrupted.\n");
+        err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_EXTERNAL_IMPORT);
+        if (err)
+            return err;
+    }
+
+    return 0;
+}
+
+static int vulkan_map_from_drm(AVHWFramesContext *hwfc, AVFrame *dst,
+                               const AVFrame *src, int flags)
+{
+    int err = 0;
+    AVVkFrame *f;
+
+    if ((err = vulkan_map_from_drm_frame_desc(hwfc, &f, src, flags)))
+        return err;
+
+    /* The unmapping function will free this */
+    dst->data[0] = (uint8_t *)f;
+    dst->width   = src->width;
+    dst->height  = src->height;
+
+    err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
+                                &vulkan_unmap_from_drm, f);
+    if (err < 0)
+        goto fail;
+
+    err = vulkan_map_from_drm_frame_sync(hwfc, dst, src, flags);
+    if (err < 0)
+        return err;
+
+    av_log(hwfc, AV_LOG_DEBUG, "Mapped DRM object to Vulkan!\n");
+
+    return 0;
+
+fail:
+    vulkan_frame_free(hwfc->device_ctx->hwctx, f);
+    dst->data[0] = NULL;
+    return err;
+}
+
+#if CONFIG_VAAPI
+static int vulkan_map_from_vaapi(AVHWFramesContext *dst_fc,
+                                 AVFrame *dst, const AVFrame *src,
+                                 int flags)
+{
+    int err;
+    AVFrame *tmp = av_frame_alloc();
+    AVHWFramesContext *vaapi_fc = (AVHWFramesContext*)src->hw_frames_ctx->data;
+    AVVAAPIDeviceContext *vaapi_ctx = vaapi_fc->device_ctx->hwctx;
+    VASurfaceID surface_id = (VASurfaceID)(uintptr_t)src->data[3];
+
+    if (!tmp)
+        return AVERROR(ENOMEM);
+
+    /* We have to sync since like the previous comment said, no semaphores */
+    vaSyncSurface(vaapi_ctx->display, surface_id);
+
+    tmp->format = AV_PIX_FMT_DRM_PRIME;
+
+    err = av_hwframe_map(tmp, src, flags);
+    if (err < 0)
+        goto fail;
+
+    err = vulkan_map_from_drm(dst_fc, dst, tmp, flags);
+    if (err < 0)
+        goto fail;
+
+    err = ff_hwframe_map_replace(dst, src);
+
+fail:
+    av_frame_free(&tmp);
+    return err;
+}
+#endif
+#endif
+
+#if CONFIG_CUDA
+static int export_mem_to_cuda(AVHWDeviceContext *ctx,
+                              AVHWDeviceContext *cuda_cu, CudaFunctions *cu,
+                              AVVkFrameInternal *dst_int, int idx,
+                              VkDeviceMemory mem, size_t size)
+{
+    VkResult ret;
+    VulkanDevicePriv *p = ctx->hwctx;
+    AVVulkanDeviceContext *hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+
+#ifdef _WIN32
+    CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = {
+        .type = IsWindows8OrGreater()
+                ? CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32
+                : CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT,
+            .size = size,
+    };
+    VkMemoryGetWin32HandleInfoKHR export_info = {
+        .sType      = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR,
+        .memory     = mem,
+        .handleType = IsWindows8OrGreater()
+            ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
+            : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
+    };
+
+    ret = vk->GetMemoryWin32HandleKHR(hwctx->act_dev, &export_info,
+                                      &ext_desc.handle.win32.handle);
+    if (ret != VK_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to export the image as a Win32 Handle: %s!\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+    dst_int->ext_mem_handle[idx] = ext_desc.handle.win32.handle;
+#else
+    CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = {
+        .type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD,
+        .size = size,
+    };
+    VkMemoryGetFdInfoKHR export_info = {
+        .sType      = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
+        .memory     = mem,
+        .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
+    };
+
+    ret = vk->GetMemoryFdKHR(hwctx->act_dev, &export_info,
+                             &ext_desc.handle.fd);
+    if (ret != VK_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to export the image as a FD: %s!\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+#endif
+
+    ret = CHECK_CU(cu->cuImportExternalMemory(&dst_int->ext_mem[idx], &ext_desc));
+    if (ret < 0) {
+#ifndef _WIN32
+        close(ext_desc.handle.fd);
+#endif
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+static int export_sem_to_cuda(AVHWDeviceContext *ctx,
+                              AVHWDeviceContext *cuda_cu, CudaFunctions *cu,
+                              AVVkFrameInternal *dst_int, int idx,
+                              VkSemaphore sem)
+{
+    VkResult ret;
+    VulkanDevicePriv *p = ctx->hwctx;
+    AVVulkanDeviceContext *hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+
+#ifdef _WIN32
+    VkSemaphoreGetWin32HandleInfoKHR sem_export = {
+        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR,
+        .semaphore = sem,
+        .handleType = IsWindows8OrGreater()
+                      ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
+                      : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
+    };
+    CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = {
+        .type = 10 /* TODO: CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_WIN32 */,
+    };
+#else
+    VkSemaphoreGetFdInfoKHR sem_export = {
+        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
+        .semaphore = sem,
+        .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
+    };
+    CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = {
+        .type = 9 /* TODO: CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_FD */,
+    };
+#endif
+
+#ifdef _WIN32
+    ret = vk->GetSemaphoreWin32HandleKHR(hwctx->act_dev, &sem_export,
+                                         &ext_sem_desc.handle.win32.handle);
+#else
+    ret = vk->GetSemaphoreFdKHR(hwctx->act_dev, &sem_export,
+                                &ext_sem_desc.handle.fd);
+#endif
+    if (ret != VK_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to export semaphore: %s\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+#ifdef _WIN32
+    dst_int->ext_sem_handle[idx] = ext_sem_desc.handle.win32.handle;
+#endif
+
+    ret = CHECK_CU(cu->cuImportExternalSemaphore(&dst_int->cu_sem[idx],
+                                                 &ext_sem_desc));
+    if (ret < 0) {
+#ifndef _WIN32
+        close(ext_sem_desc.handle.fd);
+#endif
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+static int vulkan_export_to_cuda(AVHWFramesContext *hwfc,
+                                 AVBufferRef *cuda_hwfc,
+                                 const AVFrame *frame)
+{
+    int err;
+    VkResult ret;
+    AVVkFrame *dst_f;
+    AVVkFrameInternal *dst_int;
+    AVHWDeviceContext *ctx = hwfc->device_ctx;
+    const int planes = av_pix_fmt_count_planes(hwfc->sw_format);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format);
+    VulkanDevicePriv *p = ctx->hwctx;
+    AVVulkanDeviceContext *hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+    int nb_images;
+
+    AVHWFramesContext *cuda_fc = (AVHWFramesContext*)cuda_hwfc->data;
+    AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx;
+    AVCUDADeviceContext *cuda_dev = cuda_cu->hwctx;
+    AVCUDADeviceContextInternal *cu_internal = cuda_dev->internal;
+    CudaFunctions *cu = cu_internal->cuda_dl;
+    CUarray_format cufmt = desc->comp[0].depth > 8 ? CU_AD_FORMAT_UNSIGNED_INT16 :
+                                                     CU_AD_FORMAT_UNSIGNED_INT8;
+
+    dst_f = (AVVkFrame *)frame->data[0];
+    dst_int = dst_f->internal;
+
+    if (!dst_int->cuda_fc_ref) {
+        size_t offsets[3] = { 0 };
+
+        dst_int->cuda_fc_ref = av_buffer_ref(cuda_hwfc);
+        if (!dst_int->cuda_fc_ref)
+            return AVERROR(ENOMEM);
+
+        nb_images = ff_vk_count_images(dst_f);
+        for (int i = 0; i < nb_images; i++) {
+            err = export_mem_to_cuda(ctx, cuda_cu, cu, dst_int, i,
+                                     dst_f->mem[i], dst_f->size[i]);
+            if (err < 0)
+                goto fail;
+
+            err = export_sem_to_cuda(ctx, cuda_cu, cu, dst_int, i,
+                                     dst_f->sem[i]);
+            if (err < 0)
+                goto fail;
+        }
+
+        if (nb_images != planes) {
+            for (int i = 0; i < planes; i++) {
+                VkImageSubresource subres = {
+                    .aspectMask = i == 2 ? VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT :
+                                  i == 1 ? VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT :
+                                           VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT
+                };
+                VkSubresourceLayout layout = { 0 };
+                vk->GetImageSubresourceLayout(hwctx->act_dev, dst_f->img[FFMIN(i, nb_images - 1)],
+                                              &subres, &layout);
+                offsets[i] = layout.offset;
+            }
+        }
+
+        for (int i = 0; i < planes; i++) {
+            CUDA_EXTERNAL_MEMORY_MIPMAPPED_ARRAY_DESC tex_desc = {
+                .offset = offsets[i],
+                .arrayDesc = {
+                    .Depth = 0,
+                    .Format = cufmt,
+                    .NumChannels = 1 + ((planes == 2) && i),
+                    .Flags = 0,
+                },
+                .numLevels = 1,
+            };
+            int p_w, p_h;
+
+            get_plane_wh(&p_w, &p_h, hwfc->sw_format, hwfc->width, hwfc->height, i);
+            tex_desc.arrayDesc.Width = p_w;
+            tex_desc.arrayDesc.Height = p_h;
+
+            ret = CHECK_CU(cu->cuExternalMemoryGetMappedMipmappedArray(&dst_int->cu_mma[i],
+                                                                       dst_int->ext_mem[FFMIN(i, nb_images - 1)],
+                                                                       &tex_desc));
+            if (ret < 0) {
+                err = AVERROR_EXTERNAL;
+                goto fail;
+            }
+
+            ret = CHECK_CU(cu->cuMipmappedArrayGetLevel(&dst_int->cu_array[i],
+                                                        dst_int->cu_mma[i], 0));
+            if (ret < 0) {
+                err = AVERROR_EXTERNAL;
+                goto fail;
+            }
+
+        }
+    }
+
+    return 0;
+
+fail:
+    vulkan_free_internal(dst_f);
+    return err;
+}
+
+static int vulkan_transfer_data_from_cuda(AVHWFramesContext *hwfc,
+                                          AVFrame *dst, const AVFrame *src)
+{
+    int err;
+    CUcontext dummy;
+    AVVkFrame *dst_f;
+    AVVkFrameInternal *dst_int;
+    VulkanFramesPriv *fp = hwfc->hwctx;
+    const int planes = av_pix_fmt_count_planes(hwfc->sw_format);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format);
+
+    AVHWFramesContext *cuda_fc = (AVHWFramesContext*)src->hw_frames_ctx->data;
+    AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx;
+    AVCUDADeviceContext *cuda_dev = cuda_cu->hwctx;
+    AVCUDADeviceContextInternal *cu_internal = cuda_dev->internal;
+    CudaFunctions *cu = cu_internal->cuda_dl;
+    CUDA_EXTERNAL_SEMAPHORE_WAIT_PARAMS s_w_par[AV_NUM_DATA_POINTERS] = { 0 };
+    CUDA_EXTERNAL_SEMAPHORE_SIGNAL_PARAMS s_s_par[AV_NUM_DATA_POINTERS] = { 0 };
+
+    dst_f = (AVVkFrame *)dst->data[0];
+
+    err = prepare_frame(hwfc, &fp->upload_exec, dst_f, PREP_MODE_EXTERNAL_EXPORT);
+    if (err < 0)
+        return err;
+
+    err = CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx));
+    if (err < 0)
+        return err;
+
+    err = vulkan_export_to_cuda(hwfc, src->hw_frames_ctx, dst);
+    if (err < 0) {
+        CHECK_CU(cu->cuCtxPopCurrent(&dummy));
+        return err;
+    }
+
+    dst_int = dst_f->internal;
+
+    for (int i = 0; i < planes; i++) {
+        s_w_par[i].params.fence.value = dst_f->sem_value[i] + 0;
+        s_s_par[i].params.fence.value = dst_f->sem_value[i] + 1;
+    }
+
+    err = CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par,
+                                                     planes, cuda_dev->stream));
+    if (err < 0)
+        goto fail;
+
+    for (int i = 0; i < planes; i++) {
+        CUDA_MEMCPY2D cpy = {
+            .srcMemoryType = CU_MEMORYTYPE_DEVICE,
+            .srcDevice     = (CUdeviceptr)src->data[i],
+            .srcPitch      = src->linesize[i],
+            .srcY          = 0,
+
+            .dstMemoryType = CU_MEMORYTYPE_ARRAY,
+            .dstArray      = dst_int->cu_array[i],
+        };
+
+        int p_w, p_h;
+        get_plane_wh(&p_w, &p_h, hwfc->sw_format, hwfc->width, hwfc->height, i);
+
+        cpy.WidthInBytes = p_w * desc->comp[i].step;
+        cpy.Height = p_h;
+
+        err = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream));
+        if (err < 0)
+            goto fail;
+    }
+
+    err = CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par,
+                                                       planes, cuda_dev->stream));
+    if (err < 0)
+        goto fail;
+
+    for (int i = 0; i < planes; i++)
+        dst_f->sem_value[i]++;
+
+    CHECK_CU(cu->cuCtxPopCurrent(&dummy));
+
+    av_log(hwfc, AV_LOG_VERBOSE, "Transferred CUDA image to Vulkan!\n");
+
+    return err = prepare_frame(hwfc, &fp->upload_exec, dst_f, PREP_MODE_EXTERNAL_IMPORT);
+
+fail:
+    CHECK_CU(cu->cuCtxPopCurrent(&dummy));
+    vulkan_free_internal(dst_f);
+    av_buffer_unref(&dst->buf[0]);
+    return err;
+}
+#endif
+
+static int vulkan_map_to(AVHWFramesContext *hwfc, AVFrame *dst,
+                         const AVFrame *src, int flags)
+{
+    av_unused VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+
+    switch (src->format) {
+#if CONFIG_LIBDRM
+#if CONFIG_VAAPI
+    case AV_PIX_FMT_VAAPI:
+        if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS)
+            return vulkan_map_from_vaapi(hwfc, dst, src, flags);
+        else
+            return AVERROR(ENOSYS);
+#endif
+    case AV_PIX_FMT_DRM_PRIME:
+        if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS)
+            return vulkan_map_from_drm(hwfc, dst, src, flags);
+        else
+            return AVERROR(ENOSYS);
+#endif
+    default:
+        return AVERROR(ENOSYS);
+    }
+}
+
+#if CONFIG_LIBDRM
+typedef struct VulkanDRMMapping {
+    AVDRMFrameDescriptor drm_desc;
+    AVVkFrame *source;
+} VulkanDRMMapping;
+
+static void vulkan_unmap_to_drm(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap)
+{
+    AVDRMFrameDescriptor *drm_desc = hwmap->priv;
+
+    for (int i = 0; i < drm_desc->nb_objects; i++)
+        close(drm_desc->objects[i].fd);
+
+    av_free(drm_desc);
+}
+
+static inline uint32_t vulkan_fmt_to_drm(VkFormat vkfmt)
+{
+    for (int i = 0; i < FF_ARRAY_ELEMS(vulkan_drm_format_map); i++)
+        if (vulkan_drm_format_map[i].vk_format == vkfmt)
+            return vulkan_drm_format_map[i].drm_fourcc;
+    return DRM_FORMAT_INVALID;
+}
+
+#define MAX_MEMORY_PLANES 4
+static VkImageAspectFlags plane_index_to_aspect(int plane) {
+    if (plane == 0) return VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT;
+    if (plane == 1) return VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT;
+    if (plane == 2) return VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT;
+    if (plane == 3) return VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT;
+
+    av_assert2 (0 && "Invalid plane index");
+    return VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT;
+}
+
+static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst,
+                             const AVFrame *src, int flags)
+{
+    int err = 0;
+    VkResult ret;
+    AVVkFrame *f = (AVVkFrame *)src->data[0];
+    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+    AVVulkanDeviceContext *hwctx = &p->p;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+    VulkanFramesPriv *fp = hwfc->hwctx;
+    const int planes = av_pix_fmt_count_planes(hwfc->sw_format);
+    VkImageDrmFormatModifierPropertiesEXT drm_mod = {
+        .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
+    };
+    VkSemaphoreWaitInfo wait_info = {
+        .sType          = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
+        .flags          = 0x0,
+        .semaphoreCount = planes,
+    };
+
+    AVDRMFrameDescriptor *drm_desc = av_mallocz(sizeof(*drm_desc));
+    if (!drm_desc)
+        return AVERROR(ENOMEM);
+
+    err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_EXTERNAL_EXPORT);
+    if (err < 0)
+        goto end;
+
+    /* Wait for the operation to finish so we can cleanly export it. */
+    wait_info.pSemaphores = f->sem;
+    wait_info.pValues     = f->sem_value;
+
+    vk->WaitSemaphores(hwctx->act_dev, &wait_info, UINT64_MAX);
+
+    err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, &vulkan_unmap_to_drm, drm_desc);
+    if (err < 0)
+        goto end;
+
+    ret = vk->GetImageDrmFormatModifierPropertiesEXT(hwctx->act_dev, f->img[0],
+                                                     &drm_mod);
+    if (ret != VK_SUCCESS) {
+        av_log(hwfc, AV_LOG_ERROR, "Failed to retrieve DRM format modifier!\n");
+        err = AVERROR_EXTERNAL;
+        goto end;
+    }
+
+    for (int i = 0; (i < planes) && (f->mem[i]); i++) {
+        VkMemoryGetFdInfoKHR export_info = {
+            .sType      = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
+            .memory     = f->mem[i],
+            .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
+        };
+
+        ret = vk->GetMemoryFdKHR(hwctx->act_dev, &export_info,
+                                 &drm_desc->objects[i].fd);
+        if (ret != VK_SUCCESS) {
+            av_log(hwfc, AV_LOG_ERROR, "Unable to export the image as a FD!\n");
+            err = AVERROR_EXTERNAL;
+            goto end;
+        }
+
+        drm_desc->nb_objects++;
+        drm_desc->objects[i].size = f->size[i];
+        drm_desc->objects[i].format_modifier = drm_mod.drmFormatModifier;
+    }
+
+    drm_desc->nb_layers = planes;
+    for (int i = 0; i < drm_desc->nb_layers; i++) {
+        VkFormat plane_vkfmt = av_vkfmt_from_pixfmt(hwfc->sw_format)[i];
+
+        drm_desc->layers[i].format = vulkan_fmt_to_drm(plane_vkfmt);
+        drm_desc->layers[i].nb_planes = fp->drm_format_modifier_properties[i].drmFormatModifierPlaneCount;
+
+        if (drm_desc->layers[i].nb_planes > MAX_MEMORY_PLANES) {
+            av_log(hwfc, AV_LOG_ERROR, "Too many memory planes for DRM format!\n");
+            err = AVERROR_EXTERNAL;
+            goto end;
+        }
+
+        for (int j = 0; j < drm_desc->layers[i].nb_planes; j++) {
+            VkSubresourceLayout layout;
+            VkImageSubresource sub = {
+                .aspectMask = plane_index_to_aspect(j),
+            };
+
+            drm_desc->layers[i].planes[j].object_index = FFMIN(i, drm_desc->nb_objects - 1);
+
+            vk->GetImageSubresourceLayout(hwctx->act_dev, f->img[i], &sub, &layout);
+            drm_desc->layers[i].planes[j].offset = layout.offset;
+            drm_desc->layers[i].planes[j].pitch  = layout.rowPitch;
+        }
+
+        if (drm_desc->layers[i].format == DRM_FORMAT_INVALID) {
+            av_log(hwfc, AV_LOG_ERROR, "Cannot map to DRM layer, unsupported!\n");
+            err = AVERROR_PATCHWELCOME;
+            goto end;
+        }
+
+
+        if (f->tiling == VK_IMAGE_TILING_OPTIMAL)
+            continue;
+
+    }
+
+    dst->width   = src->width;
+    dst->height  = src->height;
+    dst->data[0] = (uint8_t *)drm_desc;
+
+    av_log(hwfc, AV_LOG_VERBOSE, "Mapped AVVkFrame to a DRM object!\n");
+
+    return 0;
+
+end:
+    av_free(drm_desc);
+    return err;
+}
+
+#if CONFIG_VAAPI
+static int vulkan_map_to_vaapi(AVHWFramesContext *hwfc, AVFrame *dst,
+                               const AVFrame *src, int flags)
+{
+    int err;
+    AVFrame *tmp = av_frame_alloc();
+    if (!tmp)
+        return AVERROR(ENOMEM);
+
+    tmp->format = AV_PIX_FMT_DRM_PRIME;
+
+    err = vulkan_map_to_drm(hwfc, tmp, src, flags);
+    if (err < 0)
+        goto fail;
+
+    err = av_hwframe_map(dst, tmp, flags);
+    if (err < 0)
+        goto fail;
+
+    err = ff_hwframe_map_replace(dst, src);
+
+fail:
+    av_frame_free(&tmp);
+    return err;
+}
+#endif
+#endif
+
+static int vulkan_map_from(AVHWFramesContext *hwfc, AVFrame *dst,
+                           const AVFrame *src, int flags)
+{
+    av_unused VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+
+    switch (dst->format) {
+#if CONFIG_LIBDRM
+    case AV_PIX_FMT_DRM_PRIME:
+        if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS)
+            return vulkan_map_to_drm(hwfc, dst, src, flags);
+        else
+            return AVERROR(ENOSYS);
+#if CONFIG_VAAPI
+    case AV_PIX_FMT_VAAPI:
+        if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS)
+            return vulkan_map_to_vaapi(hwfc, dst, src, flags);
+        else
+            return AVERROR(ENOSYS);
+#endif
+#endif
+    default:
+        break;
+    }
+    return AVERROR(ENOSYS);
+}
+
+static int copy_buffer_data(AVHWFramesContext *hwfc, AVBufferRef *buf,
+                            AVFrame *swf, VkBufferImageCopy *region,
+                            int planes, int upload)
+{
+    VkResult ret;
+    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+    AVVulkanDeviceContext *hwctx = &p->p;
+
+    FFVkBuffer *vkbuf = (FFVkBuffer *)buf->data;
+
+    const VkMappedMemoryRange flush_info = {
+        .sType  = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+        .memory = vkbuf->mem,
+        .size   = VK_WHOLE_SIZE,
+    };
+
+    if (!upload && !(vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
+        ret = vk->InvalidateMappedMemoryRanges(hwctx->act_dev, 1,
+                                               &flush_info);
+        if (ret != VK_SUCCESS) {
+            av_log(hwfc, AV_LOG_ERROR, "Failed to invalidate buffer data: %s\n",
+                   ff_vk_ret2str(ret));
+            return AVERROR_EXTERNAL;
+        }
+    }
+
+    if (upload) {
+        for (int i = 0; i < planes; i++)
+            av_image_copy_plane(vkbuf->mapped_mem + region[i].bufferOffset,
+                                region[i].bufferRowLength,
+                                swf->data[i],
+                                swf->linesize[i],
+                                swf->linesize[i],
+                                region[i].imageExtent.height);
+    } else {
+        for (int i = 0; i < planes; i++)
+            av_image_copy_plane(swf->data[i],
+                                swf->linesize[i],
+                                vkbuf->mapped_mem + region[i].bufferOffset,
+                                region[i].bufferRowLength,
+                                swf->linesize[i],
+                                region[i].imageExtent.height);
+    }
+
+    if (upload && !(vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
+        ret = vk->FlushMappedMemoryRanges(hwctx->act_dev, 1,
+                                          &flush_info);
+        if (ret != VK_SUCCESS) {
+            av_log(hwfc, AV_LOG_ERROR, "Failed to flush buffer data: %s\n",
+                   ff_vk_ret2str(ret));
+            return AVERROR_EXTERNAL;
+        }
+    }
+
+    return 0;
+}
+
+static int get_plane_buf(AVHWFramesContext *hwfc, AVBufferRef **dst,
+                         AVFrame *swf, VkBufferImageCopy *region, int upload)
+{
+    int err;
+    uint32_t p_w, p_h;
+    VulkanFramesPriv *fp = hwfc->hwctx;
+    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+    const int planes = av_pix_fmt_count_planes(swf->format);
+    VkBufferUsageFlags buf_usage = upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
+                                            VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+    size_t buf_offset = 0;
+    for (int i = 0; i < planes; i++) {
+        get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
+
+        region[i] = (VkBufferImageCopy) {
+            .bufferOffset = buf_offset,
+            .bufferRowLength = FFALIGN(swf->linesize[i],
+                                       p->props.properties.limits.optimalBufferCopyRowPitchAlignment),
+            .bufferImageHeight = p_h,
+            .imageSubresource.layerCount = 1,
+            .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
+            /* Rest of the fields adjusted/filled in later */
+        };
+
+        buf_offset += FFALIGN(p_h*region[i].bufferRowLength,
+                              p->props.properties.limits.optimalBufferCopyOffsetAlignment);
+    }
+
+    err = ff_vk_get_pooled_buffer(&p->vkctx, &fp->tmp, dst, buf_usage,
+                                  NULL, buf_offset,
+                                  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+                                  VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
+    if (err < 0)
+        return err;
+
+    return 0;
+}
+
+static int host_map_frame(AVHWFramesContext *hwfc, AVBufferRef **dst, int *nb_bufs,
+                          AVFrame *swf, VkBufferImageCopy *region, int upload)
+{
+    int err;
+    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+
+    int nb_src_bufs;
+    const int planes = av_pix_fmt_count_planes(swf->format);
+    VkBufferUsageFlags buf_usage = upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
+                                            VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+    /* We can't host map images with negative strides */
+    for (int i = 0; i < planes; i++)
+        if (swf->linesize[i] < 0)
+            return AVERROR(EINVAL);
+
+    /* Count the number of buffers in the software frame */
+    nb_src_bufs = 0;
+    while (swf->buf[nb_src_bufs])
+        nb_src_bufs++;
+
+    /* Single buffer contains all planes */
+    if (nb_src_bufs == 1) {
+        err = ff_vk_host_map_buffer(&p->vkctx, &dst[0],
+                                    swf->data[0], swf->buf[0],
+                                    buf_usage);
+        if (err < 0)
+            return err;
+        (*nb_bufs)++;
+
+        for (int i = 0; i < planes; i++)
+            region[i].bufferOffset = ((FFVkBuffer *)dst[0]->data)->virtual_offset +
+                                     swf->data[i] - swf->data[0];
+    } else if (nb_src_bufs == planes) { /* One buffer per plane */
+        for (int i = 0; i < planes; i++) {
+            err = ff_vk_host_map_buffer(&p->vkctx, &dst[i],
+                                        swf->data[i], swf->buf[i],
+                                        buf_usage);
+            if (err < 0)
+                goto fail;
+            (*nb_bufs)++;
+
+            region[i].bufferOffset = ((FFVkBuffer *)dst[i]->data)->virtual_offset;
+        }
+    } else {
+        /* Weird layout (3 planes, 2 buffers), patch welcome, fallback to copy */
+        return AVERROR_PATCHWELCOME;
+    }
+
+    return 0;
+
+fail:
+    for (int i = 0; i < (*nb_bufs); i++)
+        av_buffer_unref(&dst[i]);
+    return err;
+}
+
+static int vulkan_transfer_host(AVHWFramesContext *hwfc, AVFrame *hwf,
+                                AVFrame *swf, int upload)
+{
+    VulkanFramesPriv *fp = hwfc->hwctx;
+    AVVulkanFramesContext *hwfc_vk = &fp->p;
+    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);
+
+    VkSemaphoreWaitInfo sem_wait;
+    VkHostImageLayoutTransitionInfoEXT layout_ch_info[AV_NUM_DATA_POINTERS];
+    int nb_layout_ch = 0;
+
+    hwfc_vk->lock_frame(hwfc, hwf_vk);
+
+    for (int i = 0; i < nb_images; i++) {
+        int compat = 0;
+        for (int j = 0; j < p->vkctx.host_image_props.copySrcLayoutCount; j++) {
+            if (hwf_vk->layout[i] == p->vkctx.host_image_props.pCopySrcLayouts[j]) {
+                compat = 1;
+                break;
+            }
+        }
+        if (compat)
+            continue;
+
+        layout_ch_info[nb_layout_ch] = (VkHostImageLayoutTransitionInfoEXT) {
+            .sType = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,
+            .image = hwf_vk->img[i],
+            .oldLayout = hwf_vk->layout[i],
+            .newLayout = VK_IMAGE_LAYOUT_GENERAL,
+            .subresourceRange = {
+                .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+                .levelCount = 1,
+                .layerCount = 1,
+            },
+        };
+
+        hwf_vk->layout[i] = layout_ch_info[nb_layout_ch].newLayout;
+        nb_layout_ch++;
+    }
+
+    sem_wait = (VkSemaphoreWaitInfo) {
+        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
+        .pSemaphores = hwf_vk->sem,
+        .pValues = hwf_vk->sem_value,
+        .semaphoreCount = nb_images,
+    };
+
+    vk->WaitSemaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
+
+    if (nb_layout_ch)
+        vk->TransitionImageLayoutEXT(hwctx->act_dev,
+                                     nb_layout_ch, layout_ch_info);
+
+    if (upload) {
+        VkMemoryToImageCopyEXT region_info = {
+            .sType = VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT,
+            .imageSubresource = {
+                .layerCount = 1,
+            },
+        };
+        VkCopyMemoryToImageInfoEXT copy_info = {
+            .sType = VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO_EXT,
+            .flags = VK_HOST_IMAGE_COPY_MEMCPY_EXT,
+            .regionCount = 1,
+            .pRegions = &region_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, &copy_info);
+        }
+    } else {
+        VkImageToMemoryCopyEXT region_info = {
+            .sType = VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT,
+            .imageSubresource = {
+                .layerCount = 1,
+            },
+        };
+        VkCopyImageToMemoryInfoEXT copy_info = {
+            .sType = VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO_EXT,
+            .flags = VK_HOST_IMAGE_COPY_MEMCPY_EXT,
+            .regionCount = 1,
+            .pRegions = &region_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, &copy_info);
+        }
+    }
+
+    hwfc_vk->unlock_frame(hwfc, hwf_vk);
+
+    return 0;
+}
+
+static int vulkan_transfer_frame(AVHWFramesContext *hwfc,
+                                 AVFrame *swf, AVFrame *hwf,
+                                 int upload)
+{
+    int err;
+    VulkanFramesPriv *fp = hwfc->hwctx;
+    AVVulkanFramesContext *hwctx = &fp->p;
+    VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+    FFVulkanFunctions *vk = &p->vkctx.vkfn;
+
+    int host_mapped = 0;
+
+    AVVkFrame *hwf_vk = (AVVkFrame *)hwf->data[0];
+    VkBufferImageCopy region[AV_NUM_DATA_POINTERS]; // always one per plane
+
+    const int planes = av_pix_fmt_count_planes(swf->format);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(swf->format);
+    const int nb_images = ff_vk_count_images(hwf_vk);
+
+    VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS];
+    int nb_img_bar = 0;
+
+    AVBufferRef *bufs[AV_NUM_DATA_POINTERS];
+    int nb_bufs = 0;
+
+    VkCommandBuffer cmd_buf;
+    FFVkExecContext *exec;
+
+    /* Sanity checking */
+    if ((swf->format != AV_PIX_FMT_NONE && !av_vkfmt_from_pixfmt(swf->format))) {
+        av_log(hwfc, AV_LOG_ERROR, "Unsupported software frame pixel format!\n");
+        return AVERROR(EINVAL);
+    }
+
+    if (swf->width > hwfc->width || swf->height > hwfc->height)
+        return AVERROR(EINVAL);
+
+    if (hwctx->usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT)
+        return vulkan_transfer_host(hwfc, hwf, swf, upload);
+
+    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);
+
+        /* Buffer region for this plane */
+        region[i] = (VkBufferImageCopy) {
+            .bufferOffset = 0,
+            .bufferRowLength = swf->linesize[i],
+            .bufferImageHeight = p_h,
+            .imageSubresource.layerCount = 1,
+            .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
+            /* Rest of the fields adjusted/filled in later */
+        };
+    }
+
+    /* Setup buffers first */
+    if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY && !p->avoid_host_import) {
+        err = host_map_frame(hwfc, bufs, &nb_bufs, swf, region, upload);
+        if (err >= 0)
+            host_mapped = 1;
+    }
+
+    if (!host_mapped) {
+        err = get_plane_buf(hwfc, &bufs[0], swf, region, upload);
+        if (err < 0)
+            goto end;
+        nb_bufs = 1;
+
+        if (upload) {
+            err = copy_buffer_data(hwfc, bufs[0], swf, region, planes, 1);
+            if (err < 0)
+                goto end;
+        }
+    }
+
+    exec = ff_vk_exec_get(&p->vkctx, &fp->upload_exec);
+    cmd_buf = exec->buf;
+
+    ff_vk_exec_start(&p->vkctx, exec);
+
+    /* Prep destination Vulkan frame */
+    err = ff_vk_exec_add_dep_frame(&p->vkctx, exec, hwf,
+                                   VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                   VK_PIPELINE_STAGE_2_TRANSFER_BIT);
+    if (err < 0)
+        goto end;
+
+    /* No need to declare buf deps for synchronous transfers (downloads) */
+    if (upload) {
+        /* Add the software frame backing the buffers if we're host mapping */
+        if (host_mapped) {
+            err = ff_vk_exec_add_dep_sw_frame(&p->vkctx, exec, swf);
+            if (err < 0) {
+                ff_vk_exec_discard_deps(&p->vkctx, exec);
+                goto end;
+            }
+        }
+
+        /* Add the buffers as a dependency */
+        err = ff_vk_exec_add_dep_buf(&p->vkctx, exec, bufs, nb_bufs, 1);
+        if (err < 0) {
+            ff_vk_exec_discard_deps(&p->vkctx, exec);
+            goto end;
+        }
+    }
+
+    ff_vk_frame_barrier(&p->vkctx, exec, hwf, img_bar, &nb_img_bar,
+                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                        VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,
+                        upload ? VK_ACCESS_TRANSFER_WRITE_BIT :
+                                 VK_ACCESS_TRANSFER_READ_BIT,
+                        upload ? VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL :
+                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                        p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0]);
+
+    vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+            .pImageMemoryBarriers = img_bar,
+            .imageMemoryBarrierCount = nb_img_bar,
+    });
+
+    for (int i = 0; i < planes; i++) {
+        int buf_idx = FFMIN(i, (nb_bufs - 1));
+        int img_idx = FFMIN(i, (nb_images - 1));
+        FFVkBuffer *vkbuf = (FFVkBuffer *)bufs[buf_idx]->data;
+
+        uint32_t orig_stride = region[i].bufferRowLength;
+        region[i].bufferRowLength /= desc->comp[i].step;
+        region[i].imageSubresource.aspectMask = ff_vk_aspect_flag(hwf, i);
+
+        if (upload)
+            vk->CmdCopyBufferToImage(cmd_buf, vkbuf->buf,
+                                     hwf_vk->img[img_idx],
+                                     img_bar[img_idx].newLayout,
+                                     1, &region[i]);
+        else
+            vk->CmdCopyImageToBuffer(cmd_buf, hwf_vk->img[img_idx],
+                                     img_bar[img_idx].newLayout,
+                                     vkbuf->buf,
+                                     1, &region[i]);
+
+        region[i].bufferRowLength = orig_stride;
+    }
+
+    err = ff_vk_exec_submit(&p->vkctx, exec);
+    if (err < 0) {
+        ff_vk_exec_discard_deps(&p->vkctx, exec);
+    } else if (!upload) {
+        ff_vk_exec_wait(&p->vkctx, exec);
+        if (!host_mapped)
+            err = copy_buffer_data(hwfc, bufs[0], swf, region, planes, 0);
+    }
+
+end:
+    for (int i = 0; i < nb_bufs; i++)
+        av_buffer_unref(&bufs[i]);
+
+    return err;
+}
+
+static int vulkan_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst,
+                                   const AVFrame *src)
+{
+    av_unused VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+
+    switch (src->format) {
+#if CONFIG_CUDA
+    case AV_PIX_FMT_CUDA:
+#ifdef _WIN32
+        if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) &&
+            (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM))
+#else
+        if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) &&
+            (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_SEM))
+#endif
+            return vulkan_transfer_data_from_cuda(hwfc, dst, src);
+#endif
+    default:
+        if (src->hw_frames_ctx)
+            return AVERROR(ENOSYS);
+        else
+            return vulkan_transfer_frame(hwfc, (AVFrame *)src, dst, 1);
+    }
+}
+
+#if CONFIG_CUDA
+static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst,
+                                        const AVFrame *src)
+{
+    int err;
+    CUcontext dummy;
+    AVVkFrame *dst_f;
+    AVVkFrameInternal *dst_int;
+    VulkanFramesPriv *fp = hwfc->hwctx;
+    const int planes = av_pix_fmt_count_planes(hwfc->sw_format);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format);
+    int nb_images;
+
+    AVHWFramesContext *cuda_fc = (AVHWFramesContext*)dst->hw_frames_ctx->data;
+    AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx;
+    AVCUDADeviceContext *cuda_dev = cuda_cu->hwctx;
+    AVCUDADeviceContextInternal *cu_internal = cuda_dev->internal;
+    CudaFunctions *cu = cu_internal->cuda_dl;
+    CUDA_EXTERNAL_SEMAPHORE_WAIT_PARAMS s_w_par[AV_NUM_DATA_POINTERS] = { 0 };
+    CUDA_EXTERNAL_SEMAPHORE_SIGNAL_PARAMS s_s_par[AV_NUM_DATA_POINTERS] = { 0 };
+
+    dst_f = (AVVkFrame *)src->data[0];
+    nb_images = ff_vk_count_images(dst_f);
+
+    err = prepare_frame(hwfc, &fp->upload_exec, dst_f, PREP_MODE_EXTERNAL_EXPORT);
+    if (err < 0)
+        return err;
+
+    err = CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx));
+    if (err < 0)
+        return err;
+
+    err = vulkan_export_to_cuda(hwfc, dst->hw_frames_ctx, src);
+    if (err < 0) {
+        CHECK_CU(cu->cuCtxPopCurrent(&dummy));
+        return err;
+    }
+
+    dst_int = dst_f->internal;
+
+    for (int i = 0; i < planes; i++) {
+        s_w_par[i].params.fence.value = dst_f->sem_value[i] + 0;
+        s_s_par[i].params.fence.value = dst_f->sem_value[i] + 1;
+    }
+
+    err = CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par,
+                                                     nb_images, cuda_dev->stream));
+    if (err < 0)
+        goto fail;
+
+    for (int i = 0; i < planes; i++) {
+        CUDA_MEMCPY2D cpy = {
+            .dstMemoryType = CU_MEMORYTYPE_DEVICE,
+            .dstDevice     = (CUdeviceptr)dst->data[i],
+            .dstPitch      = dst->linesize[i],
+            .dstY          = 0,
+
+            .srcMemoryType = CU_MEMORYTYPE_ARRAY,
+            .srcArray      = dst_int->cu_array[i],
+        };
+
+        int w, h;
+        get_plane_wh(&w, &h, hwfc->sw_format, hwfc->width, hwfc->height, i);
+
+        cpy.WidthInBytes = w * desc->comp[i].step;
+        cpy.Height = h;
+
+        err = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream));
+        if (err < 0)
+            goto fail;
+    }
+
+    err = CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par,
+                                                       nb_images, cuda_dev->stream));
+    if (err < 0)
+        goto fail;
+
+    for (int i = 0; i < planes; i++)
+        dst_f->sem_value[i]++;
+
+    CHECK_CU(cu->cuCtxPopCurrent(&dummy));
+
+    av_log(hwfc, AV_LOG_VERBOSE, "Transferred Vulkan image to CUDA!\n");
+
+    return prepare_frame(hwfc, &fp->upload_exec, dst_f, PREP_MODE_EXTERNAL_IMPORT);
+
+fail:
+    CHECK_CU(cu->cuCtxPopCurrent(&dummy));
+    vulkan_free_internal(dst_f);
+    av_buffer_unref(&dst->buf[0]);
+    return err;
+}
+#endif
+
+static int vulkan_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst,
+                                     const AVFrame *src)
+{
+    av_unused VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
+
+    switch (dst->format) {
+#if CONFIG_CUDA
+    case AV_PIX_FMT_CUDA:
+#ifdef _WIN32
+        if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) &&
+            (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM))
+#else
+        if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) &&
+            (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_SEM))
+#endif
+            return vulkan_transfer_data_to_cuda(hwfc, dst, src);
+#endif
+    default:
+        if (dst->hw_frames_ctx)
+            return AVERROR(ENOSYS);
+        else
+            return vulkan_transfer_frame(hwfc, dst, (AVFrame *)src, 0);
+    }
+}
+
+static int vulkan_frames_derive_to(AVHWFramesContext *dst_fc,
+                                   AVHWFramesContext *src_fc, int flags)
+{
+    return vulkan_frames_init(dst_fc);
+}
+
+AVVkFrame *av_vk_frame_alloc(void)
+{
+    int err;
+    AVVkFrame *f = av_mallocz(sizeof(AVVkFrame));
+    if (!f)
+        return NULL;
+
+    f->internal = av_mallocz(sizeof(*f->internal));
+    if (!f->internal) {
+        av_free(f);
+        return NULL;
+    }
+
+    err = pthread_mutex_init(&f->internal->update_mutex, NULL);
+    if (err != 0) {
+        av_free(f->internal);
+        av_free(f);
+        return NULL;
+    }
+
+    return f;
+}
+
+const HWContextType ff_hwcontext_type_vulkan = {
+    .type                   = AV_HWDEVICE_TYPE_VULKAN,
+    .name                   = "Vulkan",
+
+    .device_hwctx_size      = sizeof(VulkanDevicePriv),
+    .frames_hwctx_size      = sizeof(VulkanFramesPriv),
+
+    .device_init            = &vulkan_device_init,
+    .device_uninit          = &vulkan_device_uninit,
+    .device_create          = &vulkan_device_create,
+    .device_derive          = &vulkan_device_derive,
+
+    .frames_get_constraints = &vulkan_frames_get_constraints,
+    .frames_init            = vulkan_frames_init,
+    .frames_get_buffer      = vulkan_get_buffer,
+    .frames_uninit          = vulkan_frames_uninit,
+
+    .transfer_get_formats   = vulkan_transfer_get_formats,
+    .transfer_data_to       = vulkan_transfer_data_to,
+    .transfer_data_from     = vulkan_transfer_data_from,
+
+    .map_to                 = vulkan_map_to,
+    .map_from               = vulkan_map_from,
+    .frames_derive_to       = &vulkan_frames_derive_to,
+
+    .pix_fmts = (const enum AVPixelFormat []) {
+        AV_PIX_FMT_VULKAN,
+        AV_PIX_FMT_NONE
+    },
+};
-- 
2.49.1


From ac1c988371e59a65551c506829bcb8107dd0ef8a Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:15:54 +0000
Subject: [PATCH 041/118] Changing vulkan file directory

---
 libavutil/hwcontext_vulkan.h | 377 -----------------------------------
 1 file changed, 377 deletions(-)
 delete mode 100644 libavutil/hwcontext_vulkan.h

diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
deleted file mode 100644
index 15cf515668..0000000000
--- a/libavutil/hwcontext_vulkan.h
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVUTIL_HWCONTEXT_VULKAN_H
-#define AVUTIL_HWCONTEXT_VULKAN_H
-
-#if defined(_WIN32) && !defined(VK_USE_PLATFORM_WIN32_KHR)
-#define VK_USE_PLATFORM_WIN32_KHR
-#endif
-#include <vulkan/vulkan.h>
-
-#include "pixfmt.h"
-#include "frame.h"
-#include "hwcontext.h"
-
-typedef struct AVVkFrame AVVkFrame;
-
-typedef struct AVVulkanDeviceQueueFamily {
-    /* Queue family index */
-    int idx;
-    /* Number of queues in the queue family in use */
-    int num;
-    /* Queue family capabilities. Must be non-zero.
-     * Flags may be removed to indicate the queue family may not be used
-     * for a given purpose. */
-    VkQueueFlagBits flags;
-    /* Vulkan implementations are allowed to list multiple video queues
-     * which differ in what they can encode or decode. */
-    VkVideoCodecOperationFlagBitsKHR video_caps;
-} AVVulkanDeviceQueueFamily;
-
-/**
- * @file
- * API-specific header for AV_HWDEVICE_TYPE_VULKAN.
- *
- * For user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs
- * with the data pointer set to an AVVkFrame.
- */
-
-/**
- * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
- * All of these can be set before init to change what the context uses
- */
-typedef struct AVVulkanDeviceContext {
-    /**
-     * Custom memory allocator, else NULL
-     */
-    const VkAllocationCallbacks *alloc;
-
-    /**
-     * Pointer to a vkGetInstanceProcAddr loading function.
-     * If unset, will dynamically load and use libvulkan.
-     */
-    PFN_vkGetInstanceProcAddr get_proc_addr;
-
-    /**
-     * Vulkan instance. Must be at least version 1.3.
-     */
-    VkInstance inst;
-
-    /**
-     * Physical device
-     */
-    VkPhysicalDevice phys_dev;
-
-    /**
-     * Active device
-     */
-    VkDevice act_dev;
-
-    /**
-     * This structure should be set to the set of features that present and enabled
-     * during device creation. When a device is created by FFmpeg, it will default to
-     * enabling all that are present of the shaderImageGatherExtended,
-     * fragmentStoresAndAtomics, shaderInt64 and vertexPipelineStoresAndAtomics features.
-     */
-    VkPhysicalDeviceFeatures2 device_features;
-
-    /**
-     * Enabled instance extensions.
-     * If supplying your own device context, set this to an array of strings, with
-     * each entry containing the specified Vulkan extension string to enable.
-     * Duplicates are possible and accepted.
-     * If no extensions are enabled, set these fields to NULL, and 0 respectively.
-     */
-    const char * const *enabled_inst_extensions;
-    int nb_enabled_inst_extensions;
-
-    /**
-     * Enabled device extensions. By default, VK_KHR_external_memory_fd,
-     * VK_EXT_external_memory_dma_buf, VK_EXT_image_drm_format_modifier,
-     * VK_KHR_external_semaphore_fd and VK_EXT_external_memory_host are enabled if found.
-     * If supplying your own device context, these fields takes the same format as
-     * the above fields, with the same conditions that duplicates are possible
-     * and accepted, and that NULL and 0 respectively means no extensions are enabled.
-     */
-    const char * const *enabled_dev_extensions;
-    int nb_enabled_dev_extensions;
-
-#if FF_API_VULKAN_FIXED_QUEUES
-    /**
-     * Queue family index for graphics operations, and the number of queues
-     * enabled for it. If unavailable, will be set to -1. Not required.
-     * av_hwdevice_create() will attempt to find a dedicated queue for each
-     * queue family, or pick the one with the least unrelated flags set.
-     * Queue indices here may overlap if a queue has to share capabilities.
-     */
-    attribute_deprecated
-    int queue_family_index;
-    attribute_deprecated
-    int nb_graphics_queues;
-
-    /**
-     * Queue family index for transfer operations and the number of queues
-     * enabled. Required.
-     */
-    attribute_deprecated
-    int queue_family_tx_index;
-    attribute_deprecated
-    int nb_tx_queues;
-
-    /**
-     * Queue family index for compute operations and the number of queues
-     * enabled. Required.
-     */
-    attribute_deprecated
-    int queue_family_comp_index;
-    attribute_deprecated
-    int nb_comp_queues;
-
-    /**
-     * Queue family index for video encode ops, and the amount of queues enabled.
-     * If the device doesn't support such, queue_family_encode_index will be -1.
-     * Not required.
-     */
-    attribute_deprecated
-    int queue_family_encode_index;
-    attribute_deprecated
-    int nb_encode_queues;
-
-    /**
-     * Queue family index for video decode ops, and the amount of queues enabled.
-     * If the device doesn't support such, queue_family_decode_index will be -1.
-     * Not required.
-     */
-    attribute_deprecated
-    int queue_family_decode_index;
-    attribute_deprecated
-    int nb_decode_queues;
-#endif
-
-    /**
-     * Locks a queue, preventing other threads from submitting any command
-     * buffers to this queue.
-     * If set to NULL, will be set to lavu-internal functions that utilize a
-     * mutex.
-     */
-    void (*lock_queue)(struct AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index);
-
-    /**
-     * Similar to lock_queue(), unlocks a queue. Must only be called after locking.
-     */
-    void (*unlock_queue)(struct AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index);
-
-    /**
-     * Queue families used. Must be preferentially ordered. List may contain
-     * duplicates.
-     *
-     * For compatibility reasons, all the enabled queue families listed above
-     * (queue_family_(tx/comp/encode/decode)_index) must also be included in
-     * this list until they're removed after deprecation.
-     */
-    AVVulkanDeviceQueueFamily qf[64];
-    int nb_qf;
-} AVVulkanDeviceContext;
-
-/**
- * Defines the behaviour of frame allocation.
- */
-typedef enum AVVkFrameFlags {
-    /* Unless this flag is set, autodetected flags will be OR'd based on the
-     * device and tiling during av_hwframe_ctx_init(). */
-    AV_VK_FRAME_FLAG_NONE              = (1ULL << 0),
-
-    /* Disables multiplane images.
-     * This is required to export/import images from CUDA. */
-    AV_VK_FRAME_FLAG_DISABLE_MULTIPLANE = (1ULL << 2),
-} AVVkFrameFlags;
-
-/**
- * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options
- */
-typedef struct AVVulkanFramesContext {
-    /**
-     * Controls the tiling of allocated frames.
-     * If left as VK_IMAGE_TILING_OPTIMAL (0), will use optimal tiling.
-     * Can be set to VK_IMAGE_TILING_LINEAR to force linear images,
-     * or VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT to force DMABUF-backed
-     * images.
-     * @note Imported frames from other APIs ignore this.
-     */
-    VkImageTiling tiling;
-
-    /**
-     * Defines extra usage of output frames. If non-zero, all flags MUST be
-     * supported by the VkFormat. Otherwise, will use supported flags amongst:
-     * - VK_IMAGE_USAGE_SAMPLED_BIT
-     * - VK_IMAGE_USAGE_STORAGE_BIT
-     * - VK_IMAGE_USAGE_TRANSFER_SRC_BIT
-     * - VK_IMAGE_USAGE_TRANSFER_DST_BIT
-     */
-    VkImageUsageFlagBits usage;
-
-    /**
-     * Extension data for image creation.
-     * If DRM tiling is used, a VkImageDrmFormatModifierListCreateInfoEXT structure
-     * can be added to specify the exact modifier to use.
-     *
-     * Additional structures may be added at av_hwframe_ctx_init() time,
-     * which will be freed automatically on uninit(), so users must only free
-     * any structures they've allocated themselves.
-     */
-    void *create_pnext;
-
-    /**
-     * Extension data for memory allocation. Must have as many entries as
-     * the number of planes of the sw_format.
-     * This will be chained to VkExportMemoryAllocateInfo, which is used
-     * to make all pool images exportable to other APIs if the necessary
-     * extensions are present in enabled_dev_extensions.
-     */
-    void *alloc_pnext[AV_NUM_DATA_POINTERS];
-
-    /**
-     * A combination of AVVkFrameFlags. Unless AV_VK_FRAME_FLAG_NONE is set,
-     * autodetected flags will be OR'd based on the device and tiling during
-     * av_hwframe_ctx_init().
-     */
-    AVVkFrameFlags flags;
-
-    /**
-     * Flags to set during image creation. If unset, defaults to
-     * VK_IMAGE_CREATE_ALIAS_BIT.
-     */
-    VkImageCreateFlags img_flags;
-
-    /**
-     * Vulkan format for each image. MUST be compatible with the pixel format.
-     * If unset, will be automatically set.
-     * There are at most two compatible formats for a frame - a multiplane
-     * format, and a single-plane multi-image format.
-     */
-    VkFormat format[AV_NUM_DATA_POINTERS];
-
-    /**
-     * Number of layers each image will have.
-     */
-    int nb_layers;
-
-    /**
-     * Locks a frame, preventing other threads from changing frame properties.
-     * Users SHOULD only ever lock just before command submission in order
-     * to get accurate frame properties, and unlock immediately after command
-     * submission without waiting for it to finish.
-     *
-     * If unset, will be set to lavu-internal functions that utilize a mutex.
-     */
-    void (*lock_frame)(struct AVHWFramesContext *fc, AVVkFrame *vkf);
-
-    /**
-     * Similar to lock_frame(), unlocks a frame. Must only be called after locking.
-     */
-    void (*unlock_frame)(struct AVHWFramesContext *fc, AVVkFrame *vkf);
-} AVVulkanFramesContext;
-
-/*
- * Frame structure.
- *
- * @note the size of this structure is not part of the ABI, to allocate
- * you must use @av_vk_frame_alloc().
- */
-struct AVVkFrame {
-    /**
-     * Vulkan images to which the memory is bound to.
-     * May be one for multiplane formats, or multiple.
-     */
-    VkImage img[AV_NUM_DATA_POINTERS];
-
-    /**
-     * Tiling for the frame.
-     */
-    VkImageTiling tiling;
-
-    /**
-     * Memory backing the images. Either one, or as many as there are planes
-     * in the sw_format.
-     * In case of having multiple VkImages, but one memory, the offset field
-     * will indicate the bound offset for each image.
-     */
-    VkDeviceMemory mem[AV_NUM_DATA_POINTERS];
-    size_t size[AV_NUM_DATA_POINTERS];
-
-    /**
-     * OR'd flags for all memory allocated
-     */
-    VkMemoryPropertyFlagBits flags;
-
-    /**
-     * Updated after every barrier. One per VkImage.
-     */
-    VkAccessFlagBits access[AV_NUM_DATA_POINTERS];
-    VkImageLayout layout[AV_NUM_DATA_POINTERS];
-
-    /**
-     * Synchronization timeline semaphores, one for each VkImage.
-     * Must not be freed manually. Must be waited on at every submission using
-     * the value in sem_value, and must be signalled at every submission,
-     * using an incremented value.
-     */
-    VkSemaphore sem[AV_NUM_DATA_POINTERS];
-
-    /**
-     * Up to date semaphore value at which each image becomes accessible.
-     * One per VkImage.
-     * Clients must wait on this value when submitting a command queue,
-     * and increment it when signalling.
-     */
-    uint64_t sem_value[AV_NUM_DATA_POINTERS];
-
-    /**
-     * Internal data.
-     */
-    struct AVVkFrameInternal *internal;
-
-    /**
-     * Describes the binding offset of each image to the VkDeviceMemory.
-     * One per VkImage.
-     */
-    ptrdiff_t offset[AV_NUM_DATA_POINTERS];
-
-    /**
-     * Queue family of the images. Must be VK_QUEUE_FAMILY_IGNORED if
-     * the image was allocated with the CONCURRENT concurrency option.
-     * One per VkImage.
-     */
-    uint32_t queue_family[AV_NUM_DATA_POINTERS];
-};
-
-/**
- * Allocates a single AVVkFrame and initializes everything as 0.
- * @note Must be freed via av_free()
- */
-AVVkFrame *av_vk_frame_alloc(void);
-
-/**
- * Returns the optimal per-plane Vulkan format for a given sw_format,
- * one for each plane.
- * Returns NULL on unsupported formats.
- */
-const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p);
-
-#endif /* AVUTIL_HWCONTEXT_VULKAN_H */
-- 
2.49.1


From 120ebdcf6a643d4dbc3fa597c7c48e52aa6f1194 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:16:23 +0000
Subject: [PATCH 042/118] Changing vulkan file directory

---
 libavutil/vulkan/hwcontext_vulkan.h | 377 ++++++++++++++++++++++++++++
 1 file changed, 377 insertions(+)
 create mode 100644 libavutil/vulkan/hwcontext_vulkan.h

diff --git a/libavutil/vulkan/hwcontext_vulkan.h b/libavutil/vulkan/hwcontext_vulkan.h
new file mode 100644
index 0000000000..11a01b9565
--- /dev/null
+++ b/libavutil/vulkan/hwcontext_vulkan.h
@@ -0,0 +1,377 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_HWCONTEXT_VULKAN_H
+#define AVUTIL_HWCONTEXT_VULKAN_H
+
+#if defined(_WIN32) && !defined(VK_USE_PLATFORM_WIN32_KHR)
+#define VK_USE_PLATFORM_WIN32_KHR
+#endif
+#include <vulkan/vulkan.h>
+
+#include "libavutil/pixfmt.h"
+#include "libavutil/frame.h"
+#include "libavutil/hwcontext.h"
+
+typedef struct AVVkFrame AVVkFrame;
+
+typedef struct AVVulkanDeviceQueueFamily {
+    /* Queue family index */
+    int idx;
+    /* Number of queues in the queue family in use */
+    int num;
+    /* Queue family capabilities. Must be non-zero.
+     * Flags may be removed to indicate the queue family may not be used
+     * for a given purpose. */
+    VkQueueFlagBits flags;
+    /* Vulkan implementations are allowed to list multiple video queues
+     * which differ in what they can encode or decode. */
+    VkVideoCodecOperationFlagBitsKHR video_caps;
+} AVVulkanDeviceQueueFamily;
+
+/**
+ * @file
+ * API-specific header for AV_HWDEVICE_TYPE_VULKAN.
+ *
+ * For user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs
+ * with the data pointer set to an AVVkFrame.
+ */
+
+/**
+ * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
+ * All of these can be set before init to change what the context uses
+ */
+typedef struct AVVulkanDeviceContext {
+    /**
+     * Custom memory allocator, else NULL
+     */
+    const VkAllocationCallbacks *alloc;
+
+    /**
+     * Pointer to a vkGetInstanceProcAddr loading function.
+     * If unset, will dynamically load and use libvulkan.
+     */
+    PFN_vkGetInstanceProcAddr get_proc_addr;
+
+    /**
+     * Vulkan instance. Must be at least version 1.3.
+     */
+    VkInstance inst;
+
+    /**
+     * Physical device
+     */
+    VkPhysicalDevice phys_dev;
+
+    /**
+     * Active device
+     */
+    VkDevice act_dev;
+
+    /**
+     * This structure should be set to the set of features that present and enabled
+     * during device creation. When a device is created by FFmpeg, it will default to
+     * enabling all that are present of the shaderImageGatherExtended,
+     * fragmentStoresAndAtomics, shaderInt64 and vertexPipelineStoresAndAtomics features.
+     */
+    VkPhysicalDeviceFeatures2 device_features;
+
+    /**
+     * Enabled instance extensions.
+     * If supplying your own device context, set this to an array of strings, with
+     * each entry containing the specified Vulkan extension string to enable.
+     * Duplicates are possible and accepted.
+     * If no extensions are enabled, set these fields to NULL, and 0 respectively.
+     */
+    const char * const *enabled_inst_extensions;
+    int nb_enabled_inst_extensions;
+
+    /**
+     * Enabled device extensions. By default, VK_KHR_external_memory_fd,
+     * VK_EXT_external_memory_dma_buf, VK_EXT_image_drm_format_modifier,
+     * VK_KHR_external_semaphore_fd and VK_EXT_external_memory_host are enabled if found.
+     * If supplying your own device context, these fields takes the same format as
+     * the above fields, with the same conditions that duplicates are possible
+     * and accepted, and that NULL and 0 respectively means no extensions are enabled.
+     */
+    const char * const *enabled_dev_extensions;
+    int nb_enabled_dev_extensions;
+
+#if FF_API_VULKAN_FIXED_QUEUES
+    /**
+     * Queue family index for graphics operations, and the number of queues
+     * enabled for it. If unavaiable, will be set to -1. Not required.
+     * av_hwdevice_create() will attempt to find a dedicated queue for each
+     * queue family, or pick the one with the least unrelated flags set.
+     * Queue indices here may overlap if a queue has to share capabilities.
+     */
+    attribute_deprecated
+    int queue_family_index;
+    attribute_deprecated
+    int nb_graphics_queues;
+
+    /**
+     * Queue family index for transfer operations and the number of queues
+     * enabled. Required.
+     */
+    attribute_deprecated
+    int queue_family_tx_index;
+    attribute_deprecated
+    int nb_tx_queues;
+
+    /**
+     * Queue family index for compute operations and the number of queues
+     * enabled. Required.
+     */
+    attribute_deprecated
+    int queue_family_comp_index;
+    attribute_deprecated
+    int nb_comp_queues;
+
+    /**
+     * Queue family index for video encode ops, and the amount of queues enabled.
+     * If the device doesn't support such, queue_family_encode_index will be -1.
+     * Not required.
+     */
+    attribute_deprecated
+    int queue_family_encode_index;
+    attribute_deprecated
+    int nb_encode_queues;
+
+    /**
+     * Queue family index for video decode ops, and the amount of queues enabled.
+     * If the device doesn't support such, queue_family_decode_index will be -1.
+     * Not required.
+     */
+    attribute_deprecated
+    int queue_family_decode_index;
+    attribute_deprecated
+    int nb_decode_queues;
+#endif
+
+    /**
+     * Locks a queue, preventing other threads from submitting any command
+     * buffers to this queue.
+     * If set to NULL, will be set to lavu-internal functions that utilize a
+     * mutex.
+     */
+    void (*lock_queue)(struct AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index);
+
+    /**
+     * Similar to lock_queue(), unlocks a queue. Must only be called after locking.
+     */
+    void (*unlock_queue)(struct AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index);
+
+    /**
+     * Queue families used. Must be preferentially ordered. List may contain
+     * duplicates.
+     *
+     * For compatibility reasons, all the enabled queue families listed above
+     * (queue_family_(tx/comp/encode/decode)_index) must also be included in
+     * this list until they're removed after deprecation.
+     */
+    AVVulkanDeviceQueueFamily qf[64];
+    int nb_qf;
+} AVVulkanDeviceContext;
+
+/**
+ * Defines the behaviour of frame allocation.
+ */
+typedef enum AVVkFrameFlags {
+    /* Unless this flag is set, autodetected flags will be OR'd based on the
+     * device and tiling during av_hwframe_ctx_init(). */
+    AV_VK_FRAME_FLAG_NONE              = (1ULL << 0),
+
+    /* Disables multiplane images.
+     * This is required to export/import images from CUDA. */
+    AV_VK_FRAME_FLAG_DISABLE_MULTIPLANE = (1ULL << 2),
+} AVVkFrameFlags;
+
+/**
+ * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options
+ */
+typedef struct AVVulkanFramesContext {
+    /**
+     * Controls the tiling of allocated frames.
+     * If left as VK_IMAGE_TILING_OPTIMAL (0), will use optimal tiling.
+     * Can be set to VK_IMAGE_TILING_LINEAR to force linear images,
+     * or VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT to force DMABUF-backed
+     * images.
+     * @note Imported frames from other APIs ignore this.
+     */
+    VkImageTiling tiling;
+
+    /**
+     * Defines extra usage of output frames. If non-zero, all flags MUST be
+     * supported by the VkFormat. Otherwise, will use supported flags amongst:
+     * - VK_IMAGE_USAGE_SAMPLED_BIT
+     * - VK_IMAGE_USAGE_STORAGE_BIT
+     * - VK_IMAGE_USAGE_TRANSFER_SRC_BIT
+     * - VK_IMAGE_USAGE_TRANSFER_DST_BIT
+     */
+    VkImageUsageFlagBits usage;
+
+    /**
+     * Extension data for image creation.
+     * If DRM tiling is used, a VkImageDrmFormatModifierListCreateInfoEXT structure
+     * can be added to specify the exact modifier to use.
+     *
+     * Additional structures may be added at av_hwframe_ctx_init() time,
+     * which will be freed automatically on uninit(), so users must only free
+     * any structures they've allocated themselves.
+     */
+    void *create_pnext;
+
+    /**
+     * Extension data for memory allocation. Must have as many entries as
+     * the number of planes of the sw_format.
+     * This will be chained to VkExportMemoryAllocateInfo, which is used
+     * to make all pool images exportable to other APIs if the necessary
+     * extensions are present in enabled_dev_extensions.
+     */
+    void *alloc_pnext[AV_NUM_DATA_POINTERS];
+
+    /**
+     * A combination of AVVkFrameFlags. Unless AV_VK_FRAME_FLAG_NONE is set,
+     * autodetected flags will be OR'd based on the device and tiling during
+     * av_hwframe_ctx_init().
+     */
+    AVVkFrameFlags flags;
+
+    /**
+     * Flags to set during image creation. If unset, defaults to
+     * VK_IMAGE_CREATE_ALIAS_BIT.
+     */
+    VkImageCreateFlags img_flags;
+
+    /**
+     * Vulkan format for each image. MUST be compatible with the pixel format.
+     * If unset, will be automatically set.
+     * There are at most two compatible formats for a frame - a multiplane
+     * format, and a single-plane multi-image format.
+     */
+    VkFormat format[AV_NUM_DATA_POINTERS];
+
+    /**
+     * Number of layers each image will have.
+     */
+    int nb_layers;
+
+    /**
+     * Locks a frame, preventing other threads from changing frame properties.
+     * Users SHOULD only ever lock just before command submission in order
+     * to get accurate frame properties, and unlock immediately after command
+     * submission without waiting for it to finish.
+     *
+     * If unset, will be set to lavu-internal functions that utilize a mutex.
+     */
+    void (*lock_frame)(struct AVHWFramesContext *fc, AVVkFrame *vkf);
+
+    /**
+     * Similar to lock_frame(), unlocks a frame. Must only be called after locking.
+     */
+    void (*unlock_frame)(struct AVHWFramesContext *fc, AVVkFrame *vkf);
+} AVVulkanFramesContext;
+
+/*
+ * Frame structure.
+ *
+ * @note the size of this structure is not part of the ABI, to allocate
+ * you must use @av_vk_frame_alloc().
+ */
+struct AVVkFrame {
+    /**
+     * Vulkan images to which the memory is bound to.
+     * May be one for multiplane formats, or multiple.
+     */
+    VkImage img[AV_NUM_DATA_POINTERS];
+
+    /**
+     * Tiling for the frame.
+     */
+    VkImageTiling tiling;
+
+    /**
+     * Memory backing the images. Either one, or as many as there are planes
+     * in the sw_format.
+     * In case of having multiple VkImages, but one memory, the offset field
+     * will indicate the bound offset for each image.
+     */
+    VkDeviceMemory mem[AV_NUM_DATA_POINTERS];
+    size_t size[AV_NUM_DATA_POINTERS];
+
+    /**
+     * OR'd flags for all memory allocated
+     */
+    VkMemoryPropertyFlagBits flags;
+
+    /**
+     * Updated after every barrier. One per VkImage.
+     */
+    VkAccessFlagBits access[AV_NUM_DATA_POINTERS];
+    VkImageLayout layout[AV_NUM_DATA_POINTERS];
+
+    /**
+     * Synchronization timeline semaphores, one for each VkImage.
+     * Must not be freed manually. Must be waited on at every submission using
+     * the value in sem_value, and must be signalled at every submission,
+     * using an incremented value.
+     */
+    VkSemaphore sem[AV_NUM_DATA_POINTERS];
+
+    /**
+     * Up to date semaphore value at which each image becomes accessible.
+     * One per VkImage.
+     * Clients must wait on this value when submitting a command queue,
+     * and increment it when signalling.
+     */
+    uint64_t sem_value[AV_NUM_DATA_POINTERS];
+
+    /**
+     * Internal data.
+     */
+    struct AVVkFrameInternal *internal;
+
+    /**
+     * Describes the binding offset of each image to the VkDeviceMemory.
+     * One per VkImage.
+     */
+    ptrdiff_t offset[AV_NUM_DATA_POINTERS];
+
+    /**
+     * Queue family of the images. Must be VK_QUEUE_FAMILY_IGNORED if
+     * the image was allocated with the CONCURRENT concurrency option.
+     * One per VkImage.
+     */
+    uint32_t queue_family[AV_NUM_DATA_POINTERS];
+};
+
+/**
+ * Allocates a single AVVkFrame and initializes everything as 0.
+ * @note Must be freed via av_free()
+ */
+AVVkFrame *av_vk_frame_alloc(void);
+
+/**
+ * Returns the optimal per-plane Vulkan format for a given sw_format,
+ * one for each plane.
+ * Returns NULL on unsupported formats.
+ */
+const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p);
+
+#endif /* AVUTIL_HWCONTEXT_VULKAN_H */
-- 
2.49.1


From c56d89f5dae247d832327c68cf301251c0f2dbef Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:16:52 +0000
Subject: [PATCH 043/118] Changing vulkan file directory

---
 libavutil/vulkan.c | 3029 --------------------------------------------
 1 file changed, 3029 deletions(-)
 delete mode 100644 libavutil/vulkan.c

diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c
deleted file mode 100644
index ef755ad6f7..0000000000
--- a/libavutil/vulkan.c
+++ /dev/null
@@ -1,3029 +0,0 @@
-/*
- * Copyright (c) Lynne
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "avassert.h"
-#include "mem.h"
-
-#include "vulkan.h"
-#include "libavutil/vulkan_loader.h"
-
-const VkComponentMapping ff_comp_identity_map = {
-    .r = VK_COMPONENT_SWIZZLE_IDENTITY,
-    .g = VK_COMPONENT_SWIZZLE_IDENTITY,
-    .b = VK_COMPONENT_SWIZZLE_IDENTITY,
-    .a = VK_COMPONENT_SWIZZLE_IDENTITY,
-};
-
-/* Converts return values to strings */
-const char *ff_vk_ret2str(VkResult res)
-{
-#define CASE(VAL) case VAL: return #VAL
-    switch (res) {
-    CASE(VK_SUCCESS);
-    CASE(VK_NOT_READY);
-    CASE(VK_TIMEOUT);
-    CASE(VK_EVENT_SET);
-    CASE(VK_EVENT_RESET);
-    CASE(VK_INCOMPLETE);
-    CASE(VK_ERROR_OUT_OF_HOST_MEMORY);
-    CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY);
-    CASE(VK_ERROR_INITIALIZATION_FAILED);
-    CASE(VK_ERROR_DEVICE_LOST);
-    CASE(VK_ERROR_MEMORY_MAP_FAILED);
-    CASE(VK_ERROR_LAYER_NOT_PRESENT);
-    CASE(VK_ERROR_EXTENSION_NOT_PRESENT);
-    CASE(VK_ERROR_FEATURE_NOT_PRESENT);
-    CASE(VK_ERROR_INCOMPATIBLE_DRIVER);
-    CASE(VK_ERROR_TOO_MANY_OBJECTS);
-    CASE(VK_ERROR_FORMAT_NOT_SUPPORTED);
-    CASE(VK_ERROR_FRAGMENTED_POOL);
-    CASE(VK_ERROR_UNKNOWN);
-    CASE(VK_ERROR_OUT_OF_POOL_MEMORY);
-    CASE(VK_ERROR_INVALID_EXTERNAL_HANDLE);
-    CASE(VK_ERROR_FRAGMENTATION);
-    CASE(VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS);
-    CASE(VK_PIPELINE_COMPILE_REQUIRED);
-    CASE(VK_ERROR_SURFACE_LOST_KHR);
-    CASE(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR);
-    CASE(VK_SUBOPTIMAL_KHR);
-    CASE(VK_ERROR_OUT_OF_DATE_KHR);
-    CASE(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR);
-    CASE(VK_ERROR_VALIDATION_FAILED_EXT);
-    CASE(VK_ERROR_INVALID_SHADER_NV);
-    CASE(VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR);
-    CASE(VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR);
-    CASE(VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR);
-    CASE(VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR);
-    CASE(VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR);
-    CASE(VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT);
-    CASE(VK_ERROR_NOT_PERMITTED_KHR);
-    CASE(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT);
-    CASE(VK_THREAD_IDLE_KHR);
-    CASE(VK_THREAD_DONE_KHR);
-    CASE(VK_OPERATION_DEFERRED_KHR);
-    CASE(VK_OPERATION_NOT_DEFERRED_KHR);
-    default: return "Unknown error";
-    }
-#undef CASE
-}
-
-/* Malitia pura, Khronos */
-#define FN_MAP_TO(dst_t, dst_name, src_t, src_name)                                 \
-    dst_t ff_vk_map_ ##src_name## _to_ ##dst_name(src_t src) \
-    {                                                                   \
-        dst_t dst = 0x0;                                                \
-        MAP_TO(VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT,                   \
-               VK_IMAGE_USAGE_SAMPLED_BIT);                             \
-        MAP_TO(VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT,                    \
-               VK_IMAGE_USAGE_TRANSFER_SRC_BIT);                        \
-        MAP_TO(VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT,                    \
-               VK_IMAGE_USAGE_TRANSFER_DST_BIT);                        \
-        MAP_TO(VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT,                   \
-               VK_IMAGE_USAGE_STORAGE_BIT);                             \
-        MAP_TO(VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT,                \
-               VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);                    \
-        MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR,         \
-               VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR);                \
-        MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR,            \
-               VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR);                \
-        MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR,            \
-               VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR);                \
-        MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR,          \
-               VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR);                \
-        MAP_TO(VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT,         \
-               VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT);                   \
-        return dst;                                                     \
-    }
-
-#define MAP_TO(flag1, flag2) if (src & flag2) dst |= flag1;
-FN_MAP_TO(VkFormatFeatureFlagBits2, feats, VkImageUsageFlags, usage)
-#undef MAP_TO
-#define MAP_TO(flag1, flag2) if (src & flag1) dst |= flag2;
-FN_MAP_TO(VkImageUsageFlags, usage, VkFormatFeatureFlagBits2, feats)
-#undef MAP_TO
-#undef FN_MAP_TO
-
-static void load_enabled_qfs(FFVulkanContext *s)
-{
-    s->nb_qfs = 0;
-    for (int i = 0; i < s->hwctx->nb_qf; i++) {
-        /* Skip duplicates */
-        int skip = 0;
-        for (int j = 0; j < s->nb_qfs; j++) {
-            if (s->qfs[j] == s->hwctx->qf[i].idx) {
-                skip = 1;
-                break;
-            }
-        }
-        if (skip)
-            continue;
-
-        s->qfs[s->nb_qfs++] = s->hwctx->qf[i].idx;
-    }
-}
-
-int ff_vk_load_props(FFVulkanContext *s)
-{
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    s->props = (VkPhysicalDeviceProperties2) {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
-    };
-
-    FF_VK_STRUCT_EXT(s, &s->props, &s->props_11, FF_VK_EXT_NO_FLAG,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES);
-    FF_VK_STRUCT_EXT(s, &s->props, &s->driver_props, FF_VK_EXT_NO_FLAG,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES);
-    FF_VK_STRUCT_EXT(s, &s->props, &s->subgroup_props, FF_VK_EXT_NO_FLAG,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES);
-
-    FF_VK_STRUCT_EXT(s, &s->props, &s->push_desc_props, FF_VK_EXT_PUSH_DESCRIPTOR,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR);
-    FF_VK_STRUCT_EXT(s, &s->props, &s->hprops, FF_VK_EXT_EXTERNAL_HOST_MEMORY,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT);
-    FF_VK_STRUCT_EXT(s, &s->props, &s->coop_matrix_props, FF_VK_EXT_COOP_MATRIX,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR);
-    FF_VK_STRUCT_EXT(s, &s->props, &s->desc_buf_props, FF_VK_EXT_DESCRIPTOR_BUFFER,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT);
-    FF_VK_STRUCT_EXT(s, &s->props, &s->optical_flow_props, FF_VK_EXT_OPTICAL_FLOW,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV);
-    FF_VK_STRUCT_EXT(s, &s->props, &s->host_image_props, FF_VK_EXT_HOST_IMAGE_COPY,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT);
-
-    s->feats = (VkPhysicalDeviceFeatures2) {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
-    };
-
-    FF_VK_STRUCT_EXT(s, &s->feats, &s->feats_12, FF_VK_EXT_NO_FLAG,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES);
-    FF_VK_STRUCT_EXT(s, &s->feats, &s->atomic_float_feats, FF_VK_EXT_ATOMIC_FLOAT,
-                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT);
-
-    /* Try allocating 1024 layouts */
-    s->host_image_copy_layouts = av_malloc(sizeof(*s->host_image_copy_layouts)*1024);
-    s->host_image_props.pCopySrcLayouts = s->host_image_copy_layouts;
-    s->host_image_props.copySrcLayoutCount = 512;
-    s->host_image_props.pCopyDstLayouts = s->host_image_copy_layouts + 512;
-    s->host_image_props.copyDstLayoutCount = 512;
-
-    vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props);
-
-    /* Check if we had enough memory for all layouts */
-    if (s->host_image_props.copySrcLayoutCount == 512 ||
-        s->host_image_props.copyDstLayoutCount == 512) {
-        VkImageLayout *new_array;
-        size_t new_size;
-        s->host_image_props.pCopySrcLayouts =
-        s->host_image_props.pCopyDstLayouts = NULL;
-        s->host_image_props.copySrcLayoutCount =
-        s->host_image_props.copyDstLayoutCount = 0;
-        vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props);
-
-        new_size = s->host_image_props.copySrcLayoutCount +
-                   s->host_image_props.copyDstLayoutCount;
-        new_size *= sizeof(*s->host_image_copy_layouts);
-        new_array = av_realloc(s->host_image_copy_layouts, new_size);
-        if (!new_array)
-            return AVERROR(ENOMEM);
-
-        s->host_image_copy_layouts = new_array;
-        s->host_image_props.pCopySrcLayouts = new_array;
-        s->host_image_props.pCopyDstLayouts = new_array + s->host_image_props.copySrcLayoutCount;
-        vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props);
-    }
-
-    vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops);
-    vk->GetPhysicalDeviceFeatures2(s->hwctx->phys_dev, &s->feats);
-
-    load_enabled_qfs(s);
-
-    if (s->qf_props)
-        return 0;
-
-    vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &s->tot_nb_qfs, NULL);
-
-    s->qf_props = av_calloc(s->tot_nb_qfs, sizeof(*s->qf_props));
-    if (!s->qf_props)
-        return AVERROR(ENOMEM);
-
-    s->query_props = av_calloc(s->tot_nb_qfs, sizeof(*s->query_props));
-    if (!s->qf_props) {
-        av_freep(&s->qf_props);
-        return AVERROR(ENOMEM);
-    }
-
-    s->video_props = av_calloc(s->tot_nb_qfs, sizeof(*s->video_props));
-    if (!s->video_props) {
-        av_freep(&s->qf_props);
-        av_freep(&s->query_props);
-        return AVERROR(ENOMEM);
-    }
-
-    for (uint32_t i = 0; i < s->tot_nb_qfs; i++) {
-        s->qf_props[i] = (VkQueueFamilyProperties2) {
-            .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
-        };
-
-        FF_VK_STRUCT_EXT(s, &s->qf_props[i], &s->query_props[i], FF_VK_EXT_NO_FLAG,
-                         VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR);
-        FF_VK_STRUCT_EXT(s, &s->qf_props[i], &s->video_props[i], FF_VK_EXT_VIDEO_QUEUE,
-                         VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR);
-    }
-
-    vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &s->tot_nb_qfs, s->qf_props);
-
-    if (s->extensions & FF_VK_EXT_COOP_MATRIX) {
-        vk->GetPhysicalDeviceCooperativeMatrixPropertiesKHR(s->hwctx->phys_dev,
-                                                            &s->coop_mat_props_nb, NULL);
-
-        if (s->coop_mat_props_nb) {
-            s->coop_mat_props = av_malloc_array(s->coop_mat_props_nb,
-                                                sizeof(VkCooperativeMatrixPropertiesKHR));
-            for (int i = 0; i < s->coop_mat_props_nb; i++) {
-                s->coop_mat_props[i] = (VkCooperativeMatrixPropertiesKHR) {
-                    .sType = VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_KHR,
-                };
-            }
-
-            vk->GetPhysicalDeviceCooperativeMatrixPropertiesKHR(s->hwctx->phys_dev,
-                                                                &s->coop_mat_props_nb,
-                                                                s->coop_mat_props);
-        }
-    }
-
-    return 0;
-}
-
-AVVulkanDeviceQueueFamily *ff_vk_qf_find(FFVulkanContext *s,
-                                         VkQueueFlagBits dev_family,
-                                         VkVideoCodecOperationFlagBitsKHR vid_ops)
-{
-    for (int i = 0; i < s->hwctx->nb_qf; i++) {
-        if ((s->hwctx->qf[i].flags & dev_family) &&
-            (s->hwctx->qf[i].video_caps & vid_ops) == vid_ops) {
-            return &s->hwctx->qf[i];
-        }
-    }
-    return NULL;
-}
-
-void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
-{
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    for (int i = 0; i < pool->pool_size; i++) {
-        FFVkExecContext *e = &pool->contexts[i];
-
-        if (e->fence) {
-            if (e->had_submission)
-                vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
-            vk->DestroyFence(s->hwctx->act_dev, e->fence, s->hwctx->alloc);
-        }
-
-        ff_vk_exec_discard_deps(s, e);
-
-        av_free(e->frame_deps);
-        av_free(e->sw_frame_deps);
-        av_free(e->buf_deps);
-        av_free(e->queue_family_dst);
-        av_free(e->layout_dst);
-        av_free(e->access_dst);
-        av_free(e->frame_update);
-        av_free(e->frame_locked);
-        av_free(e->sem_sig);
-        av_free(e->sem_sig_val_dst);
-        av_free(e->sem_wait);
-    }
-
-    /* Free shader-specific data */
-    for (int i = 0; i < pool->nb_reg_shd; i++) {
-        FFVulkanShaderData *sd = &pool->reg_shd[i];
-
-        if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
-            for (int j = 0; j < sd->nb_descriptor_sets; j++) {
-                FFVulkanDescriptorSetData *set_data = &sd->desc_set_buf[j];
-                if (set_data->buf.mem)
-                    ff_vk_unmap_buffer(s, &set_data->buf, 0);
-                ff_vk_free_buf(s, &set_data->buf);
-            }
-        }
-
-        if (sd->desc_pool)
-            vk->DestroyDescriptorPool(s->hwctx->act_dev, sd->desc_pool,
-                                      s->hwctx->alloc);
-
-        av_freep(&sd->desc_set_buf);
-        av_freep(&sd->desc_bind);
-        av_freep(&sd->desc_sets);
-    }
-
-    av_freep(&pool->reg_shd);
-
-    for (int i = 0; i < pool->pool_size; i++) {
-        if (pool->cmd_buf_pools[i])
-            vk->FreeCommandBuffers(s->hwctx->act_dev, pool->cmd_buf_pools[i],
-                                   1, &pool->cmd_bufs[i]);
-
-        if (pool->cmd_buf_pools[i])
-            vk->DestroyCommandPool(s->hwctx->act_dev, pool->cmd_buf_pools[i], s->hwctx->alloc);
-    }
-    if (pool->query_pool)
-        vk->DestroyQueryPool(s->hwctx->act_dev, pool->query_pool, s->hwctx->alloc);
-
-    av_free(pool->query_data);
-    av_free(pool->cmd_buf_pools);
-    av_free(pool->cmd_bufs);
-    av_free(pool->contexts);
-}
-
-int ff_vk_exec_pool_init(FFVulkanContext *s, AVVulkanDeviceQueueFamily *qf,
-                         FFVkExecPool *pool, int nb_contexts,
-                         int nb_queries, VkQueryType query_type, int query_64bit,
-                         const void *query_create_pnext)
-{
-    int err;
-    VkResult ret;
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    VkCommandPoolCreateInfo cqueue_create;
-    VkCommandBufferAllocateInfo cbuf_create;
-
-    const VkQueryPoolVideoEncodeFeedbackCreateInfoKHR *ef = NULL;
-
-    atomic_init(&pool->idx, 0);
-
-    if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) {
-        ef = ff_vk_find_struct(query_create_pnext,
-                               VK_STRUCTURE_TYPE_QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR);
-        if (!ef)
-            return AVERROR(EINVAL);
-    }
-
-    /* Allocate space for command buffer pools */
-    pool->cmd_buf_pools = av_malloc(nb_contexts*sizeof(*pool->cmd_buf_pools));
-    if (!pool->cmd_buf_pools) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    /* Allocate space for command buffers */
-    pool->cmd_bufs = av_malloc(nb_contexts*sizeof(*pool->cmd_bufs));
-    if (!pool->cmd_bufs) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    for (int i = 0; i < nb_contexts; i++) {
-        /* Create command pool */
-        cqueue_create = (VkCommandPoolCreateInfo) {
-            .sType              = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
-            .flags              = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
-                                  VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
-            .queueFamilyIndex   = qf->idx,
-        };
-
-        ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create,
-                                    s->hwctx->alloc, &pool->cmd_buf_pools[i]);
-        if (ret != VK_SUCCESS) {
-            av_log(s, AV_LOG_ERROR, "Command pool creation failure: %s\n",
-                   ff_vk_ret2str(ret));
-            err = AVERROR_EXTERNAL;
-            goto fail;
-        }
-
-        /* Allocate command buffer */
-        cbuf_create = (VkCommandBufferAllocateInfo) {
-            .sType              = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
-            .level              = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
-            .commandPool        = pool->cmd_buf_pools[i],
-            .commandBufferCount = 1,
-        };
-        ret = vk->AllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create,
-                                         &pool->cmd_bufs[i]);
-        if (ret != VK_SUCCESS) {
-            av_log(s, AV_LOG_ERROR, "Command buffer alloc failure: %s\n",
-                   ff_vk_ret2str(ret));
-            err = AVERROR_EXTERNAL;
-            goto fail;
-        }
-    }
-
-    /* Query pool */
-    if (nb_queries) {
-        VkQueryPoolCreateInfo query_pool_info = {
-            .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
-            .pNext = query_create_pnext,
-            .queryType = query_type,
-            .queryCount = nb_queries*nb_contexts,
-        };
-        ret = vk->CreateQueryPool(s->hwctx->act_dev, &query_pool_info,
-                                  s->hwctx->alloc, &pool->query_pool);
-        if (ret != VK_SUCCESS) {
-            av_log(s, AV_LOG_ERROR, "Query pool alloc failure: %s\n",
-                   ff_vk_ret2str(ret));
-            err = AVERROR_EXTERNAL;
-            goto fail;
-        }
-
-        pool->nb_queries = nb_queries;
-        pool->query_status_stride = 1 + 1; /* One result, one status by default */
-        pool->query_results = nb_queries;
-        pool->query_statuses = nb_queries;
-
-        /* Video encode queries produce two results per query */
-        if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) {
-            int nb_results = av_popcount(ef->encodeFeedbackFlags);
-            pool->query_status_stride = nb_results + 1;
-            pool->query_results *= nb_results;
-        } else if (query_type == VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR) {
-            pool->query_status_stride = 1;
-            pool->query_results = 0;
-        }
-
-        pool->qd_size = (pool->query_results + pool->query_statuses)*(query_64bit ? 8 : 4);
-
-        /* Allocate space for the query data */
-        pool->query_data = av_calloc(nb_contexts, pool->qd_size);
-        if (!pool->query_data) {
-            err = AVERROR(ENOMEM);
-            goto fail;
-        }
-    }
-
-    /* Allocate space for the contexts */
-    pool->contexts = av_calloc(nb_contexts, sizeof(*pool->contexts));
-    if (!pool->contexts) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    pool->pool_size = nb_contexts;
-
-    /* Init contexts */
-    for (int i = 0; i < pool->pool_size; i++) {
-        FFVkExecContext *e = &pool->contexts[i];
-        VkFenceCreateInfo fence_create = {
-            .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
-            .flags = VK_FENCE_CREATE_SIGNALED_BIT,
-        };
-
-        /* Fence */
-        ret = vk->CreateFence(s->hwctx->act_dev, &fence_create, s->hwctx->alloc,
-                              &e->fence);
-        if (ret != VK_SUCCESS) {
-            av_log(s, AV_LOG_ERROR, "Failed to create submission fence: %s\n",
-                   ff_vk_ret2str(ret));
-            return AVERROR_EXTERNAL;
-        }
-
-        e->idx = i;
-        e->parent = pool;
-
-        /* Query data */
-        e->query_data = ((uint8_t *)pool->query_data) + pool->qd_size*i;
-        e->query_idx = nb_queries*i;
-
-        /* Command buffer */
-        e->buf = pool->cmd_bufs[i];
-
-        /* Queue index distribution */
-        e->qi = i % qf->num;
-        e->qf = qf->idx;
-        vk->GetDeviceQueue(s->hwctx->act_dev, qf->idx, e->qi, &e->queue);
-    }
-
-    return 0;
-
-fail:
-    ff_vk_exec_pool_free(s, pool);
-    return err;
-}
-
-VkResult ff_vk_exec_get_query(FFVulkanContext *s, FFVkExecContext *e,
-                              void **data, VkQueryResultFlagBits flags)
-{
-    FFVulkanFunctions *vk = &s->vkfn;
-    const FFVkExecPool *pool = e->parent;
-    VkQueryResultFlags qf = flags & ~(VK_QUERY_RESULT_64_BIT |
-                                      VK_QUERY_RESULT_WITH_STATUS_BIT_KHR);
-
-    if (!e->query_data) {
-        av_log(s, AV_LOG_ERROR, "Requested a query with a NULL query_data pointer!\n");
-        return VK_INCOMPLETE;
-    }
-
-    qf |= pool->query_64bit ?
-          VK_QUERY_RESULT_64_BIT : 0x0;
-    qf |= pool->query_statuses ?
-          VK_QUERY_RESULT_WITH_STATUS_BIT_KHR : 0x0;
-
-    if (data)
-        *data = e->query_data;
-
-    return vk->GetQueryPoolResults(s->hwctx->act_dev, pool->query_pool,
-                                   e->query_idx,
-                                   pool->nb_queries,
-                                   pool->qd_size, e->query_data,
-                                   pool->qd_size, qf);
-}
-
-FFVkExecContext *ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
-{
-    return &pool->contexts[atomic_fetch_add(&pool->idx, 1) % pool->pool_size];
-}
-
-void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
-{
-    FFVulkanFunctions *vk = &s->vkfn;
-    vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
-    ff_vk_exec_discard_deps(s, e);
-}
-
-int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
-{
-    VkResult ret;
-    FFVulkanFunctions *vk = &s->vkfn;
-    const FFVkExecPool *pool = e->parent;
-
-    VkCommandBufferBeginInfo cmd_start = {
-        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
-        .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
-    };
-
-    /* Wait for the fence to be signalled */
-    vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
-    vk->ResetFences(s->hwctx->act_dev, 1, &e->fence);
-
-    /* Discard queue dependencies */
-    ff_vk_exec_discard_deps(s, e);
-
-    ret = vk->BeginCommandBuffer(e->buf, &cmd_start);
-    if (ret != VK_SUCCESS) {
-        av_log(s, AV_LOG_ERROR, "Failed to start command recoding: %s\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-
-    if (pool->nb_queries)
-        vk->CmdResetQueryPool(e->buf, pool->query_pool,
-                              e->query_idx, pool->nb_queries);
-
-    return 0;
-}
-
-void ff_vk_exec_discard_deps(FFVulkanContext *s, FFVkExecContext *e)
-{
-    for (int j = 0; j < e->nb_buf_deps; j++)
-        av_buffer_unref(&e->buf_deps[j]);
-    e->nb_buf_deps = 0;
-
-    for (int j = 0; j < e->nb_sw_frame_deps; j++)
-        av_frame_free(&e->sw_frame_deps[j]);
-    e->nb_sw_frame_deps = 0;
-
-    for (int j = 0; j < e->nb_frame_deps; j++) {
-        AVFrame *f = e->frame_deps[j];
-        if (e->frame_locked[j]) {
-            AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
-            AVVulkanFramesContext *vkfc = hwfc->hwctx;
-            AVVkFrame *vkf = (AVVkFrame *)f->data[0];
-            vkfc->unlock_frame(hwfc, vkf);
-            e->frame_locked[j] = 0;
-        }
-        e->frame_update[j] = 0;
-    }
-    e->nb_frame_deps = 0;
-
-    e->sem_wait_cnt = 0;
-    e->sem_sig_cnt = 0;
-    e->sem_sig_val_dst_cnt = 0;
-}
-
-int ff_vk_exec_add_dep_buf(FFVulkanContext *s, FFVkExecContext *e,
-                           AVBufferRef **deps, int nb_deps, int ref)
-{
-    AVBufferRef **dst = av_fast_realloc(e->buf_deps, &e->buf_deps_alloc_size,
-                                        (e->nb_buf_deps + nb_deps) * sizeof(*dst));
-    if (!dst) {
-        ff_vk_exec_discard_deps(s, e);
-        return AVERROR(ENOMEM);
-    }
-
-    e->buf_deps = dst;
-
-    for (int i = 0; i < nb_deps; i++) {
-        if (!deps[i])
-            continue;
-
-        e->buf_deps[e->nb_buf_deps] = ref ? av_buffer_ref(deps[i]) : deps[i];
-        if (!e->buf_deps[e->nb_buf_deps]) {
-            ff_vk_exec_discard_deps(s, e);
-            return AVERROR(ENOMEM);
-        }
-        e->nb_buf_deps++;
-    }
-
-    return 0;
-}
-
-int ff_vk_exec_add_dep_sw_frame(FFVulkanContext *s, FFVkExecContext *e,
-                                AVFrame *f)
-{
-    AVFrame **dst = av_fast_realloc(e->sw_frame_deps, &e->sw_frame_deps_alloc_size,
-                                    (e->nb_sw_frame_deps + 1) * sizeof(*dst));
-    if (!dst) {
-        ff_vk_exec_discard_deps(s, e);
-        return AVERROR(ENOMEM);
-    }
-
-    e->sw_frame_deps = dst;
-
-    e->sw_frame_deps[e->nb_sw_frame_deps] = av_frame_clone(f);
-    if (!e->sw_frame_deps[e->nb_sw_frame_deps]) {
-        ff_vk_exec_discard_deps(s, e);
-        return AVERROR(ENOMEM);
-    }
-
-    e->nb_sw_frame_deps++;
-
-    return 0;
-}
-
-#define ARR_REALLOC(str, arr, alloc_s, cnt)                               \
-    do {                                                                  \
-        arr = av_fast_realloc(str->arr, alloc_s, (cnt + 1)*sizeof(*arr)); \
-        if (!arr) {                                                       \
-            ff_vk_exec_discard_deps(s, e);                                \
-            return AVERROR(ENOMEM);                                       \
-        }                                                                 \
-        str->arr = arr;                                                   \
-    } while (0)
-
-typedef struct TempSyncCtx {
-    int nb_sem;
-    VkSemaphore sem[];
-} TempSyncCtx;
-
-static void destroy_tmp_semaphores(void *opaque, uint8_t *data)
-{
-    FFVulkanContext *s = opaque;
-    FFVulkanFunctions *vk = &s->vkfn;
-    TempSyncCtx *ts = (TempSyncCtx *)data;
-
-    for (int i = 0; i < ts->nb_sem; i++)
-        vk->DestroySemaphore(s->hwctx->act_dev, ts->sem[i], s->hwctx->alloc);
-
-    av_free(ts);
-}
-
-int ff_vk_exec_add_dep_wait_sem(FFVulkanContext *s, FFVkExecContext *e,
-                                VkSemaphore sem, uint64_t val,
-                                VkPipelineStageFlagBits2 stage)
-{
-    VkSemaphoreSubmitInfo *sem_wait;
-    ARR_REALLOC(e, sem_wait, &e->sem_wait_alloc, e->sem_wait_cnt);
-
-    e->sem_wait[e->sem_wait_cnt++] = (VkSemaphoreSubmitInfo) {
-        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
-        .semaphore = sem,
-        .value = val,
-        .stageMask = stage,
-    };
-
-    return 0;
-}
-
-int ff_vk_exec_add_dep_bool_sem(FFVulkanContext *s, FFVkExecContext *e,
-                                VkSemaphore *sem, int nb,
-                                VkPipelineStageFlagBits2 stage,
-                                int wait)
-{
-    int err;
-    size_t buf_size;
-    AVBufferRef *buf;
-    TempSyncCtx *ts;
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    /* Do not transfer ownership if we're signalling a binary semaphore,
-     * since we're probably exporting it. */
-    if (!wait) {
-        for (int i = 0; i < nb; i++) {
-            VkSemaphoreSubmitInfo *sem_sig;
-            ARR_REALLOC(e, sem_sig, &e->sem_sig_alloc, e->sem_sig_cnt);
-
-            e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
-                .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
-                .semaphore = sem[i],
-                .stageMask = stage,
-            };
-        }
-
-        return 0;
-    }
-
-    buf_size = sizeof(*ts) + sizeof(VkSemaphore)*nb;
-    ts = av_mallocz(buf_size);
-    if (!ts) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    memcpy(ts->sem, sem, nb*sizeof(*sem));
-    ts->nb_sem = nb;
-
-    buf = av_buffer_create((uint8_t *)ts, buf_size, destroy_tmp_semaphores, s, 0);
-    if (!buf) {
-        av_free(ts);
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    err = ff_vk_exec_add_dep_buf(s, e, &buf, 1, 0);
-    if (err < 0) {
-        av_buffer_unref(&buf);
-        return err;
-    }
-
-    for (int i = 0; i < nb; i++) {
-        err = ff_vk_exec_add_dep_wait_sem(s, e, sem[i], 0, stage);
-        if (err < 0)
-            return err;
-    }
-
-    return 0;
-
-fail:
-    for (int i = 0; i < nb; i++)
-        vk->DestroySemaphore(s->hwctx->act_dev, sem[i], s->hwctx->alloc);
-
-    return err;
-}
-
-int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f,
-                             VkPipelineStageFlagBits2 wait_stage,
-                             VkPipelineStageFlagBits2 signal_stage)
-{
-    uint8_t *frame_locked;
-    uint8_t *frame_update;
-    AVFrame **frame_deps;
-    AVBufferRef **buf_deps;
-    VkImageLayout *layout_dst;
-    uint32_t *queue_family_dst;
-    VkAccessFlagBits *access_dst;
-
-    AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
-    AVVulkanFramesContext *vkfc = hwfc->hwctx;
-    AVVkFrame *vkf = (AVVkFrame *)f->data[0];
-    int nb_images = ff_vk_count_images(vkf);
-
-    /* Don't add duplicates */
-    for (int i = 0; i < e->nb_frame_deps; i++)
-        if (e->frame_deps[i]->data[0] == f->data[0])
-            return 1;
-
-    ARR_REALLOC(e, layout_dst,       &e->layout_dst_alloc,       e->nb_frame_deps);
-    ARR_REALLOC(e, queue_family_dst, &e->queue_family_dst_alloc, e->nb_frame_deps);
-    ARR_REALLOC(e, access_dst,       &e->access_dst_alloc,       e->nb_frame_deps);
-
-    ARR_REALLOC(e, frame_locked, &e->frame_locked_alloc_size, e->nb_frame_deps);
-    ARR_REALLOC(e, frame_update, &e->frame_update_alloc_size, e->nb_frame_deps);
-    ARR_REALLOC(e, frame_deps,   &e->frame_deps_alloc_size,   e->nb_frame_deps);
-
-    /* prepare_frame in hwcontext_vulkan.c uses the regular frame management
-     * code but has no frame yet, and it doesn't need to actually store a ref
-     * to the frame. */
-    if (f->buf[0]) {
-        ARR_REALLOC(e, buf_deps, &e->buf_deps_alloc_size, e->nb_buf_deps);
-        e->buf_deps[e->nb_buf_deps] = av_buffer_ref(f->buf[0]);
-        if (!e->buf_deps[e->nb_buf_deps]) {
-            ff_vk_exec_discard_deps(s, e);
-            return AVERROR(ENOMEM);
-        }
-        e->nb_buf_deps++;
-    }
-
-    e->frame_deps[e->nb_frame_deps] = f;
-
-    vkfc->lock_frame(hwfc, vkf);
-    e->frame_locked[e->nb_frame_deps] = 1;
-    e->frame_update[e->nb_frame_deps] = 0;
-    e->nb_frame_deps++;
-
-    for (int i = 0; i < nb_images; i++) {
-        VkSemaphoreSubmitInfo *sem_wait;
-        VkSemaphoreSubmitInfo *sem_sig;
-        uint64_t **sem_sig_val_dst;
-
-        ARR_REALLOC(e, sem_wait, &e->sem_wait_alloc, e->sem_wait_cnt);
-        ARR_REALLOC(e, sem_sig, &e->sem_sig_alloc, e->sem_sig_cnt);
-        ARR_REALLOC(e, sem_sig_val_dst, &e->sem_sig_val_dst_alloc, e->sem_sig_val_dst_cnt);
-
-        e->sem_wait[e->sem_wait_cnt++] = (VkSemaphoreSubmitInfo) {
-            .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
-            .semaphore = vkf->sem[i],
-            .value = vkf->sem_value[i],
-            .stageMask = wait_stage,
-        };
-
-        e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
-            .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
-            .semaphore = vkf->sem[i],
-            .value = vkf->sem_value[i] + 1,
-            .stageMask = signal_stage,
-        };
-
-        e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = &vkf->sem_value[i];
-        e->sem_sig_val_dst_cnt++;
-    }
-
-    return 0;
-}
-
-void ff_vk_exec_update_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f,
-                             VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar)
-{
-    int i;
-    for (i = 0; i < e->nb_frame_deps; i++)
-        if (e->frame_deps[i]->data[0] == f->data[0])
-            break;
-    av_assert0(i < e->nb_frame_deps);
-
-    /* Don't update duplicates */
-    if (nb_img_bar && !e->frame_update[i])
-        (*nb_img_bar)++;
-
-    e->queue_family_dst[i] = bar->dstQueueFamilyIndex;
-    e->access_dst[i] = bar->dstAccessMask;
-    e->layout_dst[i] = bar->newLayout;
-    e->frame_update[i] = 1;
-}
-
-int ff_vk_exec_mirror_sem_value(FFVulkanContext *s, FFVkExecContext *e,
-                                VkSemaphore *dst, uint64_t *dst_val,
-                                AVFrame *f)
-{
-    uint64_t **sem_sig_val_dst;
-    AVVkFrame *vkf = (AVVkFrame *)f->data[0];
-
-    /* Reject unknown frames */
-    int i;
-    for (i = 0; i < e->nb_frame_deps; i++)
-        if (e->frame_deps[i]->data[0] == f->data[0])
-            break;
-    if (i == e->nb_frame_deps)
-        return AVERROR(EINVAL);
-
-    ARR_REALLOC(e, sem_sig_val_dst, &e->sem_sig_val_dst_alloc, e->sem_sig_val_dst_cnt);
-
-    *dst     = vkf->sem[0];
-    *dst_val = vkf->sem_value[0];
-
-    e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = dst_val;
-    e->sem_sig_val_dst_cnt++;
-
-    return 0;
-}
-
-int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
-{
-    VkResult ret;
-    FFVulkanFunctions *vk = &s->vkfn;
-    VkCommandBufferSubmitInfo cmd_buf_info = (VkCommandBufferSubmitInfo) {
-        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
-        .commandBuffer = e->buf,
-    };
-    VkSubmitInfo2 submit_info = (VkSubmitInfo2) {
-        .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
-        .pCommandBufferInfos = &cmd_buf_info,
-        .commandBufferInfoCount = 1,
-        .pWaitSemaphoreInfos = e->sem_wait,
-        .waitSemaphoreInfoCount = e->sem_wait_cnt,
-        .pSignalSemaphoreInfos = e->sem_sig,
-        .signalSemaphoreInfoCount = e->sem_sig_cnt,
-    };
-
-    ret = vk->EndCommandBuffer(e->buf);
-    if (ret != VK_SUCCESS) {
-        av_log(s, AV_LOG_ERROR, "Unable to finish command buffer: %s\n",
-               ff_vk_ret2str(ret));
-        ff_vk_exec_discard_deps(s, e);
-        return AVERROR_EXTERNAL;
-    }
-
-    s->hwctx->lock_queue(s->device, e->qf, e->qi);
-    ret = vk->QueueSubmit2(e->queue, 1, &submit_info, e->fence);
-    s->hwctx->unlock_queue(s->device, e->qf, e->qi);
-
-    if (ret != VK_SUCCESS) {
-        av_log(s, AV_LOG_ERROR, "Unable to submit command buffer: %s\n",
-               ff_vk_ret2str(ret));
-        ff_vk_exec_discard_deps(s, e);
-        return AVERROR_EXTERNAL;
-    }
-
-    for (int i = 0; i < e->sem_sig_val_dst_cnt; i++)
-        *e->sem_sig_val_dst[i] += 1;
-
-    /* Unlock all frames */
-    for (int j = 0; j < e->nb_frame_deps; j++) {
-        if (e->frame_locked[j]) {
-            AVFrame *f = e->frame_deps[j];
-            AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
-            AVVulkanFramesContext *vkfc = hwfc->hwctx;
-            AVVkFrame *vkf = (AVVkFrame *)f->data[0];
-
-            if (e->frame_update[j]) {
-                int nb_images = ff_vk_count_images(vkf);
-                for (int i = 0; i < nb_images; i++) {
-                    vkf->layout[i] = e->layout_dst[j];
-                    vkf->access[i] = e->access_dst[j];
-                    vkf->queue_family[i] = e->queue_family_dst[j];
-                }
-            }
-            vkfc->unlock_frame(hwfc, vkf);
-            e->frame_locked[j] = 0;
-        }
-    }
-
-    e->had_submission = 1;
-
-    return 0;
-}
-
-int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req,
-                    VkMemoryPropertyFlagBits req_flags, void *alloc_extension,
-                    VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
-{
-    VkResult ret;
-    int index = -1;
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    VkMemoryAllocateInfo alloc_info = {
-        .sType           = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
-        .pNext           = alloc_extension,
-    };
-
-    alloc_info.allocationSize = req->size;
-
-    /* The vulkan spec requires memory types to be sorted in the "optimal"
-     * order, so the first matching type we find will be the best/fastest one */
-    for (int i = 0; i < s->mprops.memoryTypeCount; i++) {
-        /* The memory type must be supported by the requirements (bitfield) */
-        if (!(req->memoryTypeBits & (1 << i)))
-            continue;
-
-        /* The memory type flags must include our properties */
-        if ((req_flags != UINT32_MAX) &&
-            ((s->mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags))
-            continue;
-
-        /* Found a suitable memory type */
-        index = i;
-        break;
-    }
-
-    if (index < 0) {
-        av_log(s, AV_LOG_ERROR, "No memory type found for flags 0x%x\n",
-               req_flags);
-        return AVERROR(EINVAL);
-    }
-
-    alloc_info.memoryTypeIndex = index;
-
-    ret = vk->AllocateMemory(s->hwctx->act_dev, &alloc_info,
-                             s->hwctx->alloc, mem);
-    if (ret != VK_SUCCESS)
-        return AVERROR(ENOMEM);
-
-    if (mem_flags)
-        *mem_flags |= s->mprops.memoryTypes[index].propertyFlags;
-
-    return 0;
-}
-
-int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size,
-                     void *pNext, void *alloc_pNext,
-                     VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
-{
-    int err;
-    VkResult ret;
-    int use_ded_mem;
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    /* Buffer usage flags corresponding to buffer descriptor types */
-    const VkBufferUsageFlags desc_usage =
-        VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
-        VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
-        VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
-        VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
-
-    if ((s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) && (usage & desc_usage))
-        usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
-
-    VkBufferCreateInfo buf_spawn = {
-        .sType       = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
-        .pNext       = pNext,
-        .usage       = usage,
-        .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
-        .size        = flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT ?
-                       FFALIGN(size, s->props.properties.limits.minMemoryMapAlignment) :
-                       size,
-    };
-
-    VkMemoryAllocateFlagsInfo alloc_flags = {
-        .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
-        .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
-    };
-    VkBufferMemoryRequirementsInfo2 req_desc = {
-        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
-    };
-    VkMemoryDedicatedAllocateInfo ded_alloc = {
-        .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
-        .pNext = alloc_pNext,
-    };
-    VkMemoryDedicatedRequirements ded_req = {
-        .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
-    };
-    VkMemoryRequirements2 req = {
-        .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
-        .pNext = &ded_req,
-    };
-
-    av_log(s, AV_LOG_DEBUG, "Creating a buffer of %"SIZE_SPECIFIER" bytes, "
-                            "usage: 0x%x, flags: 0x%x\n",
-           size, usage, flags);
-
-    ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, s->hwctx->alloc, &buf->buf);
-    if (ret != VK_SUCCESS) {
-        av_log(s, AV_LOG_ERROR, "Failed to create buffer: %s\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-
-    req_desc.buffer = buf->buf;
-
-    vk->GetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req);
-
-    /* In case the implementation prefers/requires dedicated allocation */
-    use_ded_mem = ded_req.prefersDedicatedAllocation |
-                  ded_req.requiresDedicatedAllocation;
-    if (use_ded_mem) {
-        ded_alloc.buffer = buf->buf;
-        ded_alloc.pNext = alloc_pNext;
-        alloc_pNext = &ded_alloc;
-    }
-
-    if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
-        alloc_flags.pNext = alloc_pNext;
-        alloc_pNext = &alloc_flags;
-    }
-
-    err = ff_vk_alloc_mem(s, &req.memoryRequirements, flags, alloc_pNext,
-                          &buf->flags, &buf->mem);
-    if (err)
-        return err;
-
-    ret = vk->BindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0);
-    if (ret != VK_SUCCESS) {
-        av_log(s, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-
-    if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
-        VkBufferDeviceAddressInfo address_info = {
-            .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
-            .buffer = buf->buf,
-        };
-        buf->address = vk->GetBufferDeviceAddress(s->hwctx->act_dev, &address_info);
-    }
-
-    buf->size = size;
-
-    return 0;
-}
-
-int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer **buf, uint8_t *mem[],
-                      int nb_buffers, int invalidate)
-{
-    VkResult ret;
-    FFVulkanFunctions *vk = &s->vkfn;
-    VkMappedMemoryRange inval_list[64];
-    int inval_count = 0;
-
-    for (int i = 0; i < nb_buffers; i++) {
-        void *dst;
-        ret = vk->MapMemory(s->hwctx->act_dev, buf[i]->mem, 0,
-                            VK_WHOLE_SIZE, 0, &dst);
-        if (ret != VK_SUCCESS) {
-            av_log(s, AV_LOG_ERROR, "Failed to map buffer memory: %s\n",
-                   ff_vk_ret2str(ret));
-            return AVERROR_EXTERNAL;
-        }
-        mem[i] = buf[i]->mapped_mem = dst;
-    }
-
-    if (!invalidate)
-        return 0;
-
-    for (int i = 0; i < nb_buffers; i++) {
-        const VkMappedMemoryRange ival_buf = {
-            .sType  = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
-            .memory = buf[i]->mem,
-            .size   = VK_WHOLE_SIZE,
-        };
-        if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
-            continue;
-        inval_list[inval_count++] = ival_buf;
-    }
-
-    if (inval_count) {
-        ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count,
-                                               inval_list);
-        if (ret != VK_SUCCESS) {
-            av_log(s, AV_LOG_ERROR, "Failed to invalidate memory: %s\n",
-                   ff_vk_ret2str(ret));
-            return AVERROR_EXTERNAL;
-        }
-    }
-
-    return 0;
-}
-
-int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers,
-                        int flush)
-{
-    int err = 0;
-    VkResult ret;
-    FFVulkanFunctions *vk = &s->vkfn;
-    VkMappedMemoryRange flush_list[64];
-    int flush_count = 0;
-
-    if (flush) {
-        for (int i = 0; i < nb_buffers; i++) {
-            const VkMappedMemoryRange flush_buf = {
-                .sType  = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
-                .memory = buf[i]->mem,
-                .size   = VK_WHOLE_SIZE,
-            };
-
-            av_assert0(!buf[i]->host_ref);
-            if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
-                continue;
-            flush_list[flush_count++] = flush_buf;
-        }
-    }
-
-    if (flush_count) {
-        ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, flush_count,
-                                          flush_list);
-        if (ret != VK_SUCCESS) {
-            av_log(s, AV_LOG_ERROR, "Failed to flush memory: %s\n",
-                   ff_vk_ret2str(ret));
-            err = AVERROR_EXTERNAL; /* We still want to try to unmap them */
-        }
-    }
-
-    for (int i = 0; i < nb_buffers; i++) {
-        vk->UnmapMemory(s->hwctx->act_dev, buf[i]->mem);
-        buf[i]->mapped_mem = NULL;
-    }
-
-    return err;
-}
-
-void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf)
-{
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    if (!buf || !s->hwctx)
-        return;
-
-    if (buf->mapped_mem && !buf->host_ref)
-        ff_vk_unmap_buffer(s, buf, 0);
-    if (buf->buf != VK_NULL_HANDLE)
-        vk->DestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc);
-    if (buf->mem != VK_NULL_HANDLE)
-        vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc);
-    if (buf->host_ref)
-        av_buffer_unref(&buf->host_ref);
-
-    buf->buf = VK_NULL_HANDLE;
-    buf->mem = VK_NULL_HANDLE;
-    buf->mapped_mem = NULL;
-}
-
-static void free_data_buf(void *opaque, uint8_t *data)
-{
-    FFVulkanContext *ctx = opaque;
-    FFVkBuffer *buf = (FFVkBuffer *)data;
-    ff_vk_free_buf(ctx, buf);
-    av_free(data);
-}
-
-static AVBufferRef *alloc_data_buf(void *opaque, size_t size)
-{
-    AVBufferRef *ref;
-    uint8_t *buf = av_mallocz(size);
-    if (!buf)
-        return NULL;
-
-    ref = av_buffer_create(buf, size, free_data_buf, opaque, 0);
-    if (!ref)
-        av_free(buf);
-    return ref;
-}
-
-int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVBufferPool **buf_pool,
-                            AVBufferRef **buf, VkBufferUsageFlags usage,
-                            void *create_pNext, size_t size,
-                            VkMemoryPropertyFlagBits mem_props)
-{
-    int err;
-    AVBufferRef *ref;
-    FFVkBuffer *data;
-
-    *buf = NULL;
-
-    if (!(*buf_pool)) {
-        *buf_pool = av_buffer_pool_init2(sizeof(FFVkBuffer), ctx,
-                                         alloc_data_buf, NULL);
-        if (!(*buf_pool))
-            return AVERROR(ENOMEM);
-    }
-
-    *buf = ref = av_buffer_pool_get(*buf_pool);
-    if (!ref)
-        return AVERROR(ENOMEM);
-
-    data = (FFVkBuffer *)ref->data;
-    data->stage = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
-    data->access = VK_ACCESS_2_NONE;
-
-    if (data->size >= size)
-        return 0;
-
-    ff_vk_free_buf(ctx, data);
-    memset(data, 0, sizeof(*data));
-
-    err = ff_vk_create_buf(ctx, data, size,
-                           create_pNext, NULL, usage,
-                           mem_props);
-    if (err < 0) {
-        av_buffer_unref(&ref);
-        *buf = NULL;
-        return err;
-    }
-
-    if (mem_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
-        err = ff_vk_map_buffer(ctx, data, &data->mapped_mem, 0);
-        if (err < 0) {
-            av_buffer_unref(&ref);
-            *buf = NULL;
-            return err;
-        }
-    }
-
-    return 0;
-}
-
-static int create_mapped_buffer(FFVulkanContext *s,
-                                FFVkBuffer *vkb, VkBufferUsageFlags usage,
-                                size_t size,
-                                VkExternalMemoryBufferCreateInfo *create_desc,
-                                VkImportMemoryHostPointerInfoEXT *import_desc,
-                                VkMemoryHostPointerPropertiesEXT props)
-{
-    int err;
-    VkResult ret;
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    VkBufferCreateInfo buf_spawn = {
-        .sType       = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
-        .pNext       = create_desc,
-        .usage       = usage,
-        .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
-        .size        = size,
-    };
-    VkMemoryRequirements req = {
-        .size           = size,
-        .alignment      = s->hprops.minImportedHostPointerAlignment,
-        .memoryTypeBits = props.memoryTypeBits,
-    };
-
-    err = ff_vk_alloc_mem(s, &req,
-                          VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
-                          import_desc, &vkb->flags, &vkb->mem);
-    if (err < 0)
-        return err;
-
-    ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, s->hwctx->alloc, &vkb->buf);
-    if (ret != VK_SUCCESS) {
-        vk->FreeMemory(s->hwctx->act_dev, vkb->mem, s->hwctx->alloc);
-        return AVERROR_EXTERNAL;
-    }
-
-    ret = vk->BindBufferMemory(s->hwctx->act_dev, vkb->buf, vkb->mem, 0);
-    if (ret != VK_SUCCESS) {
-        vk->FreeMemory(s->hwctx->act_dev, vkb->mem, s->hwctx->alloc);
-        vk->DestroyBuffer(s->hwctx->act_dev, vkb->buf, s->hwctx->alloc);
-        return AVERROR_EXTERNAL;
-    }
-
-    return 0;
-}
-
-static void destroy_avvkbuf(void *opaque, uint8_t *data)
-{
-    FFVulkanContext *s = opaque;
-    FFVkBuffer *buf = (FFVkBuffer *)data;
-    ff_vk_free_buf(s, buf);
-    av_free(buf);
-}
-
-int ff_vk_host_map_buffer(FFVulkanContext *s, AVBufferRef **dst,
-                          uint8_t *src_data, const AVBufferRef *src_buf,
-                          VkBufferUsageFlags usage)
-{
-    int err;
-    VkResult ret;
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    VkExternalMemoryBufferCreateInfo create_desc = {
-        .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
-        .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
-    };
-    VkMemoryAllocateFlagsInfo alloc_flags = {
-        .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
-        .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
-    };
-    VkImportMemoryHostPointerInfoEXT import_desc = {
-        .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT,
-        .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
-        .pNext = usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT ? &alloc_flags : NULL,
-    };
-    VkMemoryHostPointerPropertiesEXT props;
-
-    AVBufferRef *ref;
-    FFVkBuffer *vkb;
-    size_t offs;
-    size_t buffer_size;
-
-    *dst = NULL;
-
-    /* Get the previous point at which mapping was possible and use it */
-    offs = (uintptr_t)src_data % s->hprops.minImportedHostPointerAlignment;
-    import_desc.pHostPointer = src_data - offs;
-
-    props = (VkMemoryHostPointerPropertiesEXT) {
-        VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT,
-    };
-    ret = vk->GetMemoryHostPointerPropertiesEXT(s->hwctx->act_dev,
-                                                import_desc.handleType,
-                                                import_desc.pHostPointer,
-                                                &props);
-    if (!(ret == VK_SUCCESS && props.memoryTypeBits))
-        return AVERROR(EINVAL);
-
-    /* Ref the source buffer */
-    ref = av_buffer_ref(src_buf);
-    if (!ref)
-        return AVERROR(ENOMEM);
-
-    /* Add the offset at the start, which gets ignored */
-    const ptrdiff_t src_offset = src_data - src_buf->data;
-    buffer_size = offs + (src_buf->size - src_offset);
-    buffer_size = FFALIGN(buffer_size, s->props.properties.limits.minMemoryMapAlignment);
-    buffer_size = FFALIGN(buffer_size, s->hprops.minImportedHostPointerAlignment);
-
-    /* Create a buffer struct */
-    vkb = av_mallocz(sizeof(*vkb));
-    if (!vkb) {
-        av_buffer_unref(&ref);
-        return AVERROR(ENOMEM);
-    }
-
-    err = create_mapped_buffer(s, vkb, usage,
-                               buffer_size, &create_desc, &import_desc,
-                               props);
-    if (err < 0) {
-        av_buffer_unref(&ref);
-        av_free(vkb);
-        return err;
-    }
-
-    if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
-        VkBufferDeviceAddressInfo address_info = {
-            .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
-            .buffer = vkb->buf,
-        };
-        vkb->address = vk->GetBufferDeviceAddress(s->hwctx->act_dev, &address_info);
-    }
-
-    vkb->host_ref       = ref;
-    vkb->virtual_offset = offs;
-    vkb->address       += offs;
-    vkb->mapped_mem     = src_data;
-    vkb->size           = buffer_size - offs;
-    vkb->flags         |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
-
-    /* Create a ref */
-    *dst = av_buffer_create((uint8_t *)vkb, sizeof(*vkb),
-                            destroy_avvkbuf, s, 0);
-    if (!(*dst)) {
-        destroy_avvkbuf(s, (uint8_t *)vkb);
-        *dst = NULL;
-        return AVERROR(ENOMEM);
-    }
-
-    return 0;
-}
-
-int ff_vk_shader_add_push_const(FFVulkanShader *shd, int offset, int size,
-                                VkShaderStageFlagBits stage)
-{
-    VkPushConstantRange *pc;
-
-    shd->push_consts = av_realloc_array(shd->push_consts,
-                                        sizeof(*shd->push_consts),
-                                        shd->push_consts_num + 1);
-    if (!shd->push_consts)
-        return AVERROR(ENOMEM);
-
-    pc = &shd->push_consts[shd->push_consts_num++];
-    memset(pc, 0, sizeof(*pc));
-
-    pc->stageFlags = stage;
-    pc->offset = offset;
-    pc->size = size;
-
-    return 0;
-}
-
-int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler,
-                       int unnorm_coords, VkFilter filt)
-{
-    VkResult ret;
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    VkSamplerCreateInfo sampler_info = {
-        .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
-        .magFilter = filt,
-        .minFilter = sampler_info.magFilter,
-        .mipmapMode = unnorm_coords ? VK_SAMPLER_MIPMAP_MODE_NEAREST :
-                                      VK_SAMPLER_MIPMAP_MODE_LINEAR,
-        .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
-        .addressModeV = sampler_info.addressModeU,
-        .addressModeW = sampler_info.addressModeU,
-        .anisotropyEnable = VK_FALSE,
-        .compareOp = VK_COMPARE_OP_NEVER,
-        .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
-        .unnormalizedCoordinates = unnorm_coords,
-    };
-
-    ret = vk->CreateSampler(s->hwctx->act_dev, &sampler_info,
-                            s->hwctx->alloc, sampler);
-    if (ret != VK_SUCCESS) {
-        av_log(s, AV_LOG_ERROR, "Unable to init sampler: %s\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-
-    return 0;
-}
-
-VkImageAspectFlags ff_vk_aspect_flag(AVFrame *f, int p)
-{
-    AVVkFrame *vkf = (AVVkFrame *)f->data[0];
-    AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
-    int nb_images = ff_vk_count_images(vkf);
-    int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
-
-    static const VkImageAspectFlags plane_aspect[] = { VK_IMAGE_ASPECT_PLANE_0_BIT,
-                                                       VK_IMAGE_ASPECT_PLANE_1_BIT,
-                                                       VK_IMAGE_ASPECT_PLANE_2_BIT, };
-
-    if (ff_vk_mt_is_np_rgb(hwfc->sw_format) || (nb_planes == nb_images))
-        return VK_IMAGE_ASPECT_COLOR_BIT;
-
-    return plane_aspect[p];
-}
-
-int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt)
-{
-    if (pix_fmt == AV_PIX_FMT_ABGR   || pix_fmt == AV_PIX_FMT_BGRA   ||
-        pix_fmt == AV_PIX_FMT_RGBA   || pix_fmt == AV_PIX_FMT_RGB24  ||
-        pix_fmt == AV_PIX_FMT_BGR24  || pix_fmt == AV_PIX_FMT_RGB48  ||
-        pix_fmt == AV_PIX_FMT_RGBA64 || pix_fmt == AV_PIX_FMT_RGB565 ||
-        pix_fmt == AV_PIX_FMT_BGR565 || pix_fmt == AV_PIX_FMT_BGR0   ||
-        pix_fmt == AV_PIX_FMT_0BGR   || pix_fmt == AV_PIX_FMT_RGB0   ||
-        pix_fmt == AV_PIX_FMT_GBRP10  || pix_fmt == AV_PIX_FMT_GBRP12 ||
-        pix_fmt == AV_PIX_FMT_GBRP14  || pix_fmt == AV_PIX_FMT_GBRP16 ||
-        pix_fmt == AV_PIX_FMT_GBRAP   || pix_fmt == AV_PIX_FMT_GBRAP10 ||
-        pix_fmt == AV_PIX_FMT_GBRAP12 || pix_fmt == AV_PIX_FMT_GBRAP14 ||
-        pix_fmt == AV_PIX_FMT_GBRAP16 || pix_fmt == AV_PIX_FMT_GBRAP32 ||
-        pix_fmt == AV_PIX_FMT_GBRPF32 || pix_fmt == AV_PIX_FMT_GBRAPF32 ||
-        pix_fmt == AV_PIX_FMT_X2RGB10 || pix_fmt == AV_PIX_FMT_X2BGR10 ||
-        pix_fmt == AV_PIX_FMT_RGBAF32 || pix_fmt == AV_PIX_FMT_RGBF32 ||
-        pix_fmt == AV_PIX_FMT_RGBA128 || pix_fmt == AV_PIX_FMT_RGB96 ||
-        pix_fmt == AV_PIX_FMT_GBRP || pix_fmt == AV_PIX_FMT_BAYER_RGGB16)
-        return 1;
-    return 0;
-}
-
-void ff_vk_set_perm(enum AVPixelFormat pix_fmt, int lut[4], int inv)
-{
-    switch (pix_fmt) {
-    case AV_PIX_FMT_GBRP:
-    case AV_PIX_FMT_GBRAP:
-    case AV_PIX_FMT_GBRAP10:
-    case AV_PIX_FMT_GBRAP12:
-    case AV_PIX_FMT_GBRAP14:
-    case AV_PIX_FMT_GBRAP16:
-    case AV_PIX_FMT_GBRP10:
-    case AV_PIX_FMT_GBRP12:
-    case AV_PIX_FMT_GBRP14:
-    case AV_PIX_FMT_GBRP16:
-    case AV_PIX_FMT_GBRPF32:
-    case AV_PIX_FMT_GBRAP32:
-    case AV_PIX_FMT_GBRAPF32:
-        lut[0] = 1;
-        lut[1] = 2;
-        lut[2] = 0;
-        lut[3] = 3;
-        break;
-    default:
-        lut[0] = 0;
-        lut[1] = 1;
-        lut[2] = 2;
-        lut[3] = 3;
-        break;
-    }
-
-    if (inv) {
-        int lut_tmp[4] = { lut[0], lut[1], lut[2], lut[3] };
-        for (int i = 0; i < 4; i++)
-            lut[lut_tmp[i]] = i;
-    }
-
-    return;
-}
-
-const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pix_fmt,
-                                 enum FFVkShaderRepFormat rep_fmt)
-{
-    switch (pix_fmt) {
-    case AV_PIX_FMT_RGBA:
-    case AV_PIX_FMT_BGRA:
-    case AV_PIX_FMT_RGB24:
-    case AV_PIX_FMT_BGR24:
-    case AV_PIX_FMT_BGR0:
-    case AV_PIX_FMT_RGB0:
-    case AV_PIX_FMT_RGB565:
-    case AV_PIX_FMT_BGR565:
-    case AV_PIX_FMT_UYVA:
-    case AV_PIX_FMT_YUYV422:
-    case AV_PIX_FMT_UYVY422: {
-        const char *rep_tab[] = {
-            [FF_VK_REP_NATIVE] = "rgba8ui",
-            [FF_VK_REP_FLOAT] = "rgba8",
-            [FF_VK_REP_INT] = "rgba8i",
-            [FF_VK_REP_UINT] = "rgba8ui",
-        };
-        return rep_tab[rep_fmt];
-    }
-    case AV_PIX_FMT_X2RGB10:
-    case AV_PIX_FMT_X2BGR10:
-    case AV_PIX_FMT_Y210:
-    case AV_PIX_FMT_XV30: {
-        const char *rep_tab[] = {
-            [FF_VK_REP_NATIVE] = "rgb10_a2ui",
-            [FF_VK_REP_FLOAT] = "rgb10_a2",
-            [FF_VK_REP_INT] = NULL,
-            [FF_VK_REP_UINT] = "rgb10_a2ui",
-        };
-        return rep_tab[rep_fmt];
-    }
-    case AV_PIX_FMT_RGB48:
-    case AV_PIX_FMT_RGBA64:
-    case AV_PIX_FMT_Y212:
-    case AV_PIX_FMT_Y216:
-    case AV_PIX_FMT_XV36:
-    case AV_PIX_FMT_XV48: {
-        const char *rep_tab[] = {
-            [FF_VK_REP_NATIVE] = "rgba16ui",
-            [FF_VK_REP_FLOAT] = "rgba16",
-            [FF_VK_REP_INT] = "rgba16i",
-            [FF_VK_REP_UINT] = "rgba16ui",
-        };
-        return rep_tab[rep_fmt];
-    }
-    case AV_PIX_FMT_RGBF32:
-    case AV_PIX_FMT_RGBAF32: {
-        const char *rep_tab[] = {
-            [FF_VK_REP_NATIVE] = "rgba32f",
-            [FF_VK_REP_FLOAT] = "rgba32f",
-            [FF_VK_REP_INT] = "rgba32i",
-            [FF_VK_REP_UINT] = "rgba32ui",
-        };
-        return rep_tab[rep_fmt];
-    }
-    case AV_PIX_FMT_RGB96:
-    case AV_PIX_FMT_RGBA128: {
-        const char *rep_tab[] = {
-            [FF_VK_REP_NATIVE] = "rgba32ui",
-            [FF_VK_REP_FLOAT] = NULL,
-            [FF_VK_REP_INT] = "rgba32i",
-            [FF_VK_REP_UINT] = "rgba32ui",
-        };
-        return rep_tab[rep_fmt];
-    }
-    case AV_PIX_FMT_GBRP:
-    case AV_PIX_FMT_GRAY8:
-    case AV_PIX_FMT_GBRAP:
-    case AV_PIX_FMT_YUV420P:
-    case AV_PIX_FMT_YUV422P:
-    case AV_PIX_FMT_YUV444P:
-    case AV_PIX_FMT_YUVA420P:
-    case AV_PIX_FMT_YUVA422P:
-    case AV_PIX_FMT_YUVA444P: {
-        const char *rep_tab[] = {
-            [FF_VK_REP_NATIVE] = "r8ui",
-            [FF_VK_REP_FLOAT] = "r8",
-            [FF_VK_REP_INT] = "r8i",
-            [FF_VK_REP_UINT] = "r8ui",
-        };
-        return rep_tab[rep_fmt];
-    };
-    case AV_PIX_FMT_GRAY10:
-    case AV_PIX_FMT_GRAY12:
-    case AV_PIX_FMT_GRAY14:
-    case AV_PIX_FMT_GRAY16:
-    case AV_PIX_FMT_GBRAP10:
-    case AV_PIX_FMT_GBRAP12:
-    case AV_PIX_FMT_GBRAP14:
-    case AV_PIX_FMT_GBRAP16:
-    case AV_PIX_FMT_GBRP10:
-    case AV_PIX_FMT_GBRP12:
-    case AV_PIX_FMT_GBRP14:
-    case AV_PIX_FMT_GBRP16:
-    case AV_PIX_FMT_YUV420P10:
-    case AV_PIX_FMT_YUV420P12:
-    case AV_PIX_FMT_YUV420P16:
-    case AV_PIX_FMT_YUV422P10:
-    case AV_PIX_FMT_YUV422P12:
-    case AV_PIX_FMT_YUV422P16:
-    case AV_PIX_FMT_YUV444P10:
-    case AV_PIX_FMT_YUV444P12:
-    case AV_PIX_FMT_YUV444P16:
-    case AV_PIX_FMT_YUVA420P10:
-    case AV_PIX_FMT_YUVA420P16:
-    case AV_PIX_FMT_YUVA422P10:
-    case AV_PIX_FMT_YUVA422P12:
-    case AV_PIX_FMT_YUVA422P16:
-    case AV_PIX_FMT_YUVA444P10:
-    case AV_PIX_FMT_YUVA444P12:
-    case AV_PIX_FMT_YUVA444P16:
-    case AV_PIX_FMT_BAYER_RGGB16: {
-        const char *rep_tab[] = {
-            [FF_VK_REP_NATIVE] = "r16ui",
-            [FF_VK_REP_FLOAT] = "r16f",
-            [FF_VK_REP_INT] = "r16i",
-            [FF_VK_REP_UINT] = "r16ui",
-        };
-        return rep_tab[rep_fmt];
-    };
-    case AV_PIX_FMT_GRAY32:
-    case AV_PIX_FMT_GRAYF32:
-    case AV_PIX_FMT_GBRPF32:
-    case AV_PIX_FMT_GBRAPF32: {
-        const char *rep_tab[] = {
-            [FF_VK_REP_NATIVE] = "r32f",
-            [FF_VK_REP_FLOAT] = "r32f",
-            [FF_VK_REP_INT] = "r32i",
-            [FF_VK_REP_UINT] = "r32ui",
-        };
-        return rep_tab[rep_fmt];
-    };
-    case AV_PIX_FMT_GBRAP32: {
-        const char *rep_tab[] = {
-            [FF_VK_REP_NATIVE] = "r32ui",
-            [FF_VK_REP_FLOAT] = NULL,
-            [FF_VK_REP_INT] = "r32i",
-            [FF_VK_REP_UINT] = "r32ui",
-        };
-        return rep_tab[rep_fmt];
-    };
-    case AV_PIX_FMT_NV12:
-    case AV_PIX_FMT_NV16:
-    case AV_PIX_FMT_NV24: {
-        const char *rep_tab[] = {
-            [FF_VK_REP_NATIVE] = "rg8ui",
-            [FF_VK_REP_FLOAT] = "rg8",
-            [FF_VK_REP_INT] = "rg8i",
-            [FF_VK_REP_UINT] = "rg8ui",
-        };
-        return rep_tab[rep_fmt];
-    };
-    case AV_PIX_FMT_P010:
-    case AV_PIX_FMT_P210:
-    case AV_PIX_FMT_P410: {
-        const char *rep_tab[] = {
-            [FF_VK_REP_NATIVE] = "rgb10_a2ui",
-            [FF_VK_REP_FLOAT] = "rgb10_a2",
-            [FF_VK_REP_INT] = NULL,
-            [FF_VK_REP_UINT] = "rgb10_a2ui",
-        };
-        return rep_tab[rep_fmt];
-    };
-    case AV_PIX_FMT_P012:
-    case AV_PIX_FMT_P016:
-    case AV_PIX_FMT_P212:
-    case AV_PIX_FMT_P216:
-    case AV_PIX_FMT_P412:
-    case AV_PIX_FMT_P416: {
-        const char *rep_tab[] = {
-            [FF_VK_REP_NATIVE] = "rg16ui",
-            [FF_VK_REP_FLOAT] = "rg16",
-            [FF_VK_REP_INT] = "rg16i",
-            [FF_VK_REP_UINT] = "rg16ui",
-        };
-        return rep_tab[rep_fmt];
-    };
-    default:
-        return "rgba32f";
-    }
-}
-
-typedef struct ImageViewCtx {
-    int nb_views;
-    VkImageView views[];
-} ImageViewCtx;
-
-static void destroy_imageviews(void *opaque, uint8_t *data)
-{
-    FFVulkanContext *s = opaque;
-    FFVulkanFunctions *vk = &s->vkfn;
-    ImageViewCtx *iv = (ImageViewCtx *)data;
-
-    for (int i = 0; i < iv->nb_views; i++)
-        vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], s->hwctx->alloc);
-
-    av_free(iv);
-}
-
-static VkFormat map_fmt_to_rep(VkFormat fmt, enum FFVkShaderRepFormat rep_fmt)
-{
-#define REPS_FMT(fmt) \
-    [FF_VK_REP_NATIVE] = fmt ## _UINT, \
-    [FF_VK_REP_FLOAT]  = fmt ## _UNORM, \
-    [FF_VK_REP_INT]    = fmt ## _SINT, \
-    [FF_VK_REP_UINT]   = fmt ## _UINT,
-
-#define REPS_FMT_PACK(fmt, num) \
-    [FF_VK_REP_NATIVE] = fmt ## _UINT_PACK ## num, \
-    [FF_VK_REP_FLOAT]  = fmt ## _UNORM_PACK ## num, \
-    [FF_VK_REP_INT]    = fmt ## _SINT_PACK ## num, \
-    [FF_VK_REP_UINT]   = fmt ## _UINT_PACK ## num,
-
-    const VkFormat fmts_map[][4] = {
-        { REPS_FMT_PACK(VK_FORMAT_A2B10G10R10, 32) },
-        { REPS_FMT_PACK(VK_FORMAT_A2R10G10B10, 32) },
-        {
-            VK_FORMAT_B5G6R5_UNORM_PACK16,
-            VK_FORMAT_B5G6R5_UNORM_PACK16,
-            VK_FORMAT_UNDEFINED,
-            VK_FORMAT_UNDEFINED,
-        },
-        {
-            VK_FORMAT_R5G6B5_UNORM_PACK16,
-            VK_FORMAT_R5G6B5_UNORM_PACK16,
-            VK_FORMAT_UNDEFINED,
-            VK_FORMAT_UNDEFINED,
-        },
-        { REPS_FMT(VK_FORMAT_B8G8R8) },
-        { REPS_FMT(VK_FORMAT_B8G8R8A8) },
-        { REPS_FMT(VK_FORMAT_R8) },
-        { REPS_FMT(VK_FORMAT_R8G8) },
-        { REPS_FMT(VK_FORMAT_R8G8B8) },
-        { REPS_FMT(VK_FORMAT_R8G8B8A8) },
-        { REPS_FMT(VK_FORMAT_R16) },
-        { REPS_FMT(VK_FORMAT_R16G16) },
-        { REPS_FMT(VK_FORMAT_R16G16B16) },
-        { REPS_FMT(VK_FORMAT_R16G16B16A16) },
-        {
-            VK_FORMAT_R32_UINT,
-            VK_FORMAT_R32_SFLOAT,
-            VK_FORMAT_R32_SINT,
-            VK_FORMAT_R32_UINT,
-        },
-        {
-            VK_FORMAT_R32G32B32_SFLOAT,
-            VK_FORMAT_R32G32B32_SFLOAT,
-            VK_FORMAT_UNDEFINED,
-            VK_FORMAT_UNDEFINED,
-        },
-        {
-            VK_FORMAT_R32G32B32A32_SFLOAT,
-            VK_FORMAT_R32G32B32A32_SFLOAT,
-            VK_FORMAT_UNDEFINED,
-            VK_FORMAT_UNDEFINED,
-        },
-        {
-            VK_FORMAT_R32G32B32_UINT,
-            VK_FORMAT_UNDEFINED,
-            VK_FORMAT_R32G32B32_SINT,
-            VK_FORMAT_R32G32B32_UINT,
-        },
-        {
-            VK_FORMAT_R32G32B32A32_UINT,
-            VK_FORMAT_UNDEFINED,
-            VK_FORMAT_R32G32B32A32_SINT,
-            VK_FORMAT_R32G32B32A32_UINT,
-        },
-    };
-#undef REPS_FMT_PACK
-#undef REPS_FMT
-
-    if (fmt == VK_FORMAT_UNDEFINED)
-        return VK_FORMAT_UNDEFINED;
-
-    for (int i = 0; i < FF_ARRAY_ELEMS(fmts_map); i++) {
-        if (fmts_map[i][FF_VK_REP_NATIVE] == fmt ||
-            fmts_map[i][FF_VK_REP_FLOAT] == fmt ||
-            fmts_map[i][FF_VK_REP_INT] == fmt ||
-            fmts_map[i][FF_VK_REP_UINT] == fmt)
-            return fmts_map[i][rep_fmt];
-    }
-
-    return VK_FORMAT_UNDEFINED;
-}
-
-int ff_vk_create_imageview(FFVulkanContext *s,
-                           VkImageView *img_view, VkImageAspectFlags *aspect,
-                           AVFrame *f, int plane, enum FFVkShaderRepFormat rep_fmt)
-{
-    VkResult ret;
-    FFVulkanFunctions *vk = &s->vkfn;
-    AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
-    AVVulkanFramesContext *vkfc = hwfc->hwctx;
-    const VkFormat *rep_fmts = av_vkfmt_from_pixfmt(hwfc->sw_format);
-    AVVkFrame *vkf = (AVVkFrame *)f->data[0];
-    const int nb_images = ff_vk_count_images(vkf);
-
-    VkImageViewUsageCreateInfo view_usage_info = {
-        .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
-        .usage = vkfc->usage &
-                 (~(VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR |
-                    VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)),
-    };
-    VkImageViewCreateInfo view_create_info = {
-        .sType      = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
-        .pNext      = &view_usage_info,
-        .image      = vkf->img[FFMIN(plane, nb_images - 1)],
-        .viewType   = VK_IMAGE_VIEW_TYPE_2D,
-        .format     = map_fmt_to_rep(rep_fmts[plane], rep_fmt),
-        .components = ff_comp_identity_map,
-        .subresourceRange = {
-            .aspectMask = ff_vk_aspect_flag(f, plane),
-            .levelCount = 1,
-            .layerCount = 1,
-        },
-    };
-    if (view_create_info.format == VK_FORMAT_UNDEFINED) {
-        av_log(s, AV_LOG_ERROR, "Unable to find a compatible representation "
-                                "of format %i and mode %i\n",
-               rep_fmts[plane], rep_fmt);
-        return AVERROR(EINVAL);
-    }
-
-    ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info,
-                              s->hwctx->alloc, img_view);
-    if (ret != VK_SUCCESS) {
-        av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-
-    *aspect = view_create_info.subresourceRange.aspectMask;
-
-    return 0;
-}
-
-int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e,
-                            VkImageView views[AV_NUM_DATA_POINTERS],
-                            AVFrame *f, enum FFVkShaderRepFormat rep_fmt)
-{
-    int err;
-    VkResult ret;
-    AVBufferRef *buf;
-    FFVulkanFunctions *vk = &s->vkfn;
-    AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
-    AVVulkanFramesContext *vkfc = hwfc->hwctx;
-    const VkFormat *rep_fmts = av_vkfmt_from_pixfmt(hwfc->sw_format);
-    AVVkFrame *vkf = (AVVkFrame *)f->data[0];
-    const int nb_images = ff_vk_count_images(vkf);
-    const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
-
-    ImageViewCtx *iv;
-    const size_t buf_size = sizeof(*iv) + nb_planes*sizeof(VkImageView);
-    iv = av_mallocz(buf_size);
-    if (!iv)
-        return AVERROR(ENOMEM);
-
-    for (int i = 0; i < nb_planes; i++) {
-        VkImageViewUsageCreateInfo view_usage_info = {
-            .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
-            .usage = vkfc->usage &
-                     (~(VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR |
-                        VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)),
-        };
-        VkImageViewCreateInfo view_create_info = {
-            .sType      = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
-            .pNext      = &view_usage_info,
-            .image      = vkf->img[FFMIN(i, nb_images - 1)],
-            .viewType   = VK_IMAGE_VIEW_TYPE_2D,
-            .format     = map_fmt_to_rep(rep_fmts[i], rep_fmt),
-            .components = ff_comp_identity_map,
-            .subresourceRange = {
-                .aspectMask = ff_vk_aspect_flag(f, i),
-                .levelCount = 1,
-                .layerCount = 1,
-            },
-        };
-        if (view_create_info.format == VK_FORMAT_UNDEFINED) {
-            av_log(s, AV_LOG_ERROR, "Unable to find a compatible representation "
-                                    "of format %i and mode %i\n",
-                   rep_fmts[i], rep_fmt);
-            err = AVERROR(EINVAL);
-            goto fail;
-        }
-
-        ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info,
-                                  s->hwctx->alloc, &iv->views[i]);
-        if (ret != VK_SUCCESS) {
-            av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n",
-                   ff_vk_ret2str(ret));
-            err = AVERROR_EXTERNAL;
-            goto fail;
-        }
-
-        iv->nb_views++;
-    }
-
-    buf = av_buffer_create((uint8_t *)iv, buf_size, destroy_imageviews, s, 0);
-    if (!buf) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    /* Add to queue dependencies */
-    err = ff_vk_exec_add_dep_buf(s, e, &buf, 1, 0);
-    if (err < 0)
-        av_buffer_unref(&buf);
-
-    memcpy(views, iv->views, nb_planes*sizeof(*views));
-
-    return err;
-
-fail:
-    for (int i = 0; i < iv->nb_views; i++)
-        vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], s->hwctx->alloc);
-    av_free(iv);
-    return err;
-}
-
-void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e,
-                         AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar,
-                         VkPipelineStageFlags src_stage,
-                         VkPipelineStageFlags dst_stage,
-                         VkAccessFlagBits     new_access,
-                         VkImageLayout        new_layout,
-                         uint32_t             new_qf)
-{
-    int found = -1;
-    AVVkFrame *vkf = (AVVkFrame *)pic->data[0];
-    const int nb_images = ff_vk_count_images(vkf);
-    for (int i = 0; i < e->nb_frame_deps; i++)
-        if (e->frame_deps[i]->data[0] == pic->data[0]) {
-            if (e->frame_update[i])
-                found = i;
-            break;
-        }
-
-    for (int i = 0; i < nb_images; i++) {
-        bar[*nb_bar] = (VkImageMemoryBarrier2) {
-            .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
-            .pNext = NULL,
-            .srcStageMask = src_stage,
-            .dstStageMask = dst_stage,
-            .srcAccessMask = found >= 0 ? e->access_dst[found] : vkf->access[i],
-            .dstAccessMask = new_access,
-            .oldLayout = found >= 0 ? e->layout_dst[found] : vkf->layout[0],
-            .newLayout = new_layout,
-            .srcQueueFamilyIndex = found >= 0 ? e->queue_family_dst[found] : vkf->queue_family[0],
-            .dstQueueFamilyIndex = new_qf,
-            .image = vkf->img[i],
-            .subresourceRange = (VkImageSubresourceRange) {
-                .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
-                .layerCount = 1,
-                .levelCount = 1,
-            },
-        };
-        *nb_bar += 1;
-    }
-
-    ff_vk_exec_update_frame(s, e, pic, &bar[*nb_bar - nb_images], NULL);
-}
-
-int ff_vk_shader_init(FFVulkanContext *s, FFVulkanShader *shd, const char *name,
-                      VkPipelineStageFlags stage,
-                      const char *extensions[], int nb_extensions,
-                      int lg_x, int lg_y, int lg_z,
-                      uint32_t required_subgroup_size)
-{
-    av_bprint_init(&shd->src, 0, AV_BPRINT_SIZE_UNLIMITED);
-
-    shd->name = name;
-    shd->stage = stage;
-    shd->lg_size[0] = lg_x;
-    shd->lg_size[1] = lg_y;
-    shd->lg_size[2] = lg_z;
-
-    switch (shd->stage) {
-    case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
-    case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
-    case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
-    case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
-    case VK_SHADER_STAGE_MISS_BIT_KHR:
-    case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
-        shd->bind_point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
-        break;
-    case VK_SHADER_STAGE_COMPUTE_BIT:
-        shd->bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
-        break;
-    default:
-        shd->bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
-        break;
-    };
-
-    if (required_subgroup_size) {
-        shd->subgroup_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO;
-        shd->subgroup_info.requiredSubgroupSize = required_subgroup_size;
-    }
-
-    av_bprintf(&shd->src, "/* %s shader: %s */\n",
-               (stage == VK_SHADER_STAGE_TASK_BIT_EXT ||
-                stage == VK_SHADER_STAGE_MESH_BIT_EXT) ?
-               "Mesh" :
-               (shd->bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR) ?
-               "Raytrace" :
-               (shd->bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) ?
-               "Compute" : "Graphics",
-               name);
-    GLSLF(0, #version %i                                                  ,460);
-    GLSLC(0,                                                                  );
-
-    /* Common utilities */
-    GLSLC(0, #define IS_WITHIN(v1, v2) ((v1.x < v2.x) && (v1.y < v2.y))       );
-    GLSLC(0,                                                                  );
-    GLSLC(0, #extension GL_EXT_scalar_block_layout : require                  );
-    GLSLC(0, #extension GL_EXT_shader_explicit_arithmetic_types : require     );
-    GLSLC(0, #extension GL_EXT_control_flow_attributes : require              );
-    GLSLC(0, #extension GL_EXT_shader_image_load_formatted : require          );
-    if (s->extensions & FF_VK_EXT_EXPECT_ASSUME) {
-        GLSLC(0, #extension GL_EXT_expect_assume : require                    );
-    } else {
-        GLSLC(0, #define assumeEXT(x) (x)                                     );
-        GLSLC(0, #define expectEXT(x, c) (x)                                  );
-    }
-    if ((s->extensions & FF_VK_EXT_DEBUG_UTILS) &&
-        (s->extensions & FF_VK_EXT_RELAXED_EXTENDED_INSTR)) {
-        GLSLC(0, #extension GL_EXT_debug_printf : require                     );
-        GLSLC(0, #define DEBUG                                                );
-    }
-
-    if (stage == VK_SHADER_STAGE_TASK_BIT_EXT ||
-        stage == VK_SHADER_STAGE_MESH_BIT_EXT)
-        GLSLC(0, #extension GL_EXT_mesh_shader : require                      );
-
-    for (int i = 0; i < nb_extensions; i++)
-        GLSLF(0, #extension %s : %s                  ,extensions[i], "require");
-    GLSLC(0,                                                                  );
-
-    GLSLF(0, layout (local_size_x = %i, local_size_y = %i, local_size_z = %i) in;
-          , shd->lg_size[0], shd->lg_size[1], shd->lg_size[2]);
-    GLSLC(0,                                                                  );
-
-    return 0;
-}
-
-void ff_vk_shader_print(void *ctx, FFVulkanShader *shd, int prio)
-{
-    int line = 0;
-    const char *p = shd->src.str;
-    const char *start = p;
-    const size_t len = strlen(p);
-
-    AVBPrint buf;
-    av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
-
-    for (int i = 0; i < len; i++) {
-        if (p[i] == '\n') {
-            av_bprintf(&buf, "%i\t", ++line);
-            av_bprint_append_data(&buf, start, &p[i] - start + 1);
-            start = &p[i + 1];
-        }
-    }
-
-    av_log(ctx, prio, "Shader %s: \n%s", shd->name, buf.str);
-    av_bprint_finalize(&buf, NULL);
-}
-
-static int init_pipeline_layout(FFVulkanContext *s, FFVulkanShader *shd)
-{
-    VkResult ret;
-    FFVulkanFunctions *vk = &s->vkfn;
-    VkPipelineLayoutCreateInfo pipeline_layout_info;
-
-    /* Finally create the pipeline layout */
-    pipeline_layout_info = (VkPipelineLayoutCreateInfo) {
-        .sType                  = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
-        .pSetLayouts            = shd->desc_layout,
-        .setLayoutCount         = shd->nb_descriptor_sets,
-        .pushConstantRangeCount = shd->push_consts_num,
-        .pPushConstantRanges    = shd->push_consts,
-    };
-
-    ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &pipeline_layout_info,
-                                   s->hwctx->alloc, &shd->pipeline_layout);
-    if (ret != VK_SUCCESS) {
-        av_log(s, AV_LOG_ERROR, "Unable to init pipeline layout: %s\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-
-    return 0;
-}
-
-static int create_shader_module(FFVulkanContext *s, FFVulkanShader *shd,
-                                VkShaderModule *mod,
-                                uint8_t *spirv, size_t spirv_len)
-{
-    VkResult ret;
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    VkShaderModuleCreateInfo shader_module_info = {
-        .sType    = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
-        .pNext    = NULL,
-        .flags    = 0x0,
-        .pCode    = (void *)spirv,
-        .codeSize = spirv_len,
-    };
-
-    ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_module_info,
-                                 s->hwctx->alloc, mod);
-    if (ret != VK_SUCCESS) {
-        av_log(s, AV_LOG_ERROR, "Error creating shader module: %s\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-
-    return 0;
-}
-
-static int init_compute_pipeline(FFVulkanContext *s, FFVulkanShader *shd,
-                                 VkShaderModule mod, const char *entrypoint)
-{
-    VkResult ret;
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    VkComputePipelineCreateInfo pipeline_create_info = {
-        .sType  = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
-        .flags = (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) ?
-                 VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT : 0x0,
-        .layout = shd->pipeline_layout,
-        .stage = (VkPipelineShaderStageCreateInfo) {
-            .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
-            .pNext = shd->subgroup_info.requiredSubgroupSize ?
-                     &shd->subgroup_info : NULL,
-            .pName = entrypoint,
-            .flags = shd->subgroup_info.requiredSubgroupSize ?
-                     VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT : 0x0,
-            .stage = shd->stage,
-            .module = mod,
-        },
-    };
-
-    ret = vk->CreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1,
-                                     &pipeline_create_info,
-                                     s->hwctx->alloc, &shd->pipeline);
-    if (ret != VK_SUCCESS) {
-        av_log(s, AV_LOG_ERROR, "Unable to init compute pipeline: %s\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-
-    return 0;
-}
-
-static int create_shader_object(FFVulkanContext *s, FFVulkanShader *shd,
-                                uint8_t *spirv, size_t spirv_len,
-                                const char *entrypoint)
-{
-    VkResult ret;
-    FFVulkanFunctions *vk = &s->vkfn;
-    size_t shader_size = 0;
-
-    VkShaderCreateInfoEXT shader_obj_create = {
-        .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,
-        .flags = shd->subgroup_info.requiredSubgroupSize ?
-                 VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT : 0x0,
-        .stage = shd->stage,
-        .nextStage = 0,
-        .codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT,
-        .pCode = spirv,
-        .codeSize = spirv_len,
-        .pName = entrypoint,
-        .pSetLayouts = shd->desc_layout,
-        .setLayoutCount = shd->nb_descriptor_sets,
-        .pushConstantRangeCount = shd->push_consts_num,
-        .pPushConstantRanges = shd->push_consts,
-        .pSpecializationInfo = NULL,
-    };
-
-    ret = vk->CreateShadersEXT(s->hwctx->act_dev, 1, &shader_obj_create,
-                               s->hwctx->alloc, &shd->object);
-    if (ret != VK_SUCCESS) {
-        av_log(s, AV_LOG_ERROR, "Unable to create shader object: %s\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-
-    if (vk->GetShaderBinaryDataEXT(s->hwctx->act_dev, shd->object,
-                                   &shader_size, NULL) == VK_SUCCESS)
-        av_log(s, AV_LOG_VERBOSE, "Shader %s size: %zu binary (%zu SPIR-V)\n",
-               shd->name, shader_size, spirv_len);
-
-    return 0;
-}
-
-static int init_descriptors(FFVulkanContext *s, FFVulkanShader *shd)
-{
-    VkResult ret;
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    shd->desc_layout = av_malloc_array(shd->nb_descriptor_sets,
-                                       sizeof(*shd->desc_layout));
-    if (!shd->desc_layout)
-        return AVERROR(ENOMEM);
-
-    if (!(s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER)) {
-        int has_singular = 0;
-        int max_descriptors = 0;
-        for (int i = 0; i < shd->nb_descriptor_sets; i++) {
-            max_descriptors = FFMAX(max_descriptors, shd->desc_set[i].nb_bindings);
-            if (shd->desc_set[i].singular)
-                has_singular = 1;
-        }
-        shd->use_push = (s->extensions & FF_VK_EXT_PUSH_DESCRIPTOR) &&
-                        (max_descriptors <= s->push_desc_props.maxPushDescriptors) &&
-                        (shd->nb_descriptor_sets == 1) &&
-                        (has_singular == 0);
-    }
-
-    for (int i = 0; i < shd->nb_descriptor_sets; i++) {
-        FFVulkanDescriptorSet *set = &shd->desc_set[i];
-        VkDescriptorSetLayoutCreateInfo desc_layout_create = {
-            .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
-            .bindingCount = set->nb_bindings,
-            .pBindings = set->binding,
-            .flags = (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) ?
-                     VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT :
-                     (shd->use_push) ?
-                     VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR :
-                     0x0,
-        };
-
-        ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev,
-                                            &desc_layout_create,
-                                            s->hwctx->alloc,
-                                            &shd->desc_layout[i]);
-        if (ret != VK_SUCCESS) {
-            av_log(s, AV_LOG_ERROR, "Unable to create descriptor set layout: %s",
-                   ff_vk_ret2str(ret));
-            return AVERROR_EXTERNAL;
-        }
-
-        if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
-            vk->GetDescriptorSetLayoutSizeEXT(s->hwctx->act_dev, shd->desc_layout[i],
-                                              &set->layout_size);
-
-            set->aligned_size = FFALIGN(set->layout_size,
-                                        s->desc_buf_props.descriptorBufferOffsetAlignment);
-
-            for (int j = 0; j < set->nb_bindings; j++)
-                vk->GetDescriptorSetLayoutBindingOffsetEXT(s->hwctx->act_dev,
-                                                           shd->desc_layout[i],
-                                                           j,
-                                                           &set->binding_offset[j]);
-        }
-    }
-
-    return 0;
-}
-
-int ff_vk_shader_link(FFVulkanContext *s, FFVulkanShader *shd,
-                      uint8_t *spirv, size_t spirv_len,
-                      const char *entrypoint)
-{
-    int err;
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    err = init_descriptors(s, shd);
-    if (err < 0)
-        return err;
-
-    err = init_pipeline_layout(s, shd);
-    if (err < 0)
-        return err;
-
-    if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
-        shd->bound_buffer_indices = av_calloc(shd->nb_descriptor_sets,
-                                              sizeof(*shd->bound_buffer_indices));
-        if (!shd->bound_buffer_indices)
-            return AVERROR(ENOMEM);
-
-        for (int i = 0; i < shd->nb_descriptor_sets; i++)
-            shd->bound_buffer_indices[i] = i;
-    }
-
-    if (s->extensions & FF_VK_EXT_SHADER_OBJECT) {
-        err = create_shader_object(s, shd, spirv, spirv_len, entrypoint);
-        if (err < 0)
-            return err;
-    } else {
-        VkShaderModule mod;
-        err = create_shader_module(s, shd, &mod, spirv, spirv_len);
-        if (err < 0)
-            return err;
-
-        switch (shd->bind_point) {
-        case VK_PIPELINE_BIND_POINT_COMPUTE:
-            err = init_compute_pipeline(s, shd, mod, entrypoint);
-            break;
-        default:
-            av_log(s, AV_LOG_ERROR, "Unsupported shader type: %i\n",
-                   shd->bind_point);
-            err = AVERROR(EINVAL);
-            break;
-        };
-
-        vk->DestroyShaderModule(s->hwctx->act_dev, mod, s->hwctx->alloc);
-        if (err < 0)
-            return err;
-    }
-
-    return 0;
-}
-
-static const struct descriptor_props {
-    size_t struct_size; /* Size of the opaque which updates the descriptor */
-    const char *type;
-    int is_uniform;
-    int mem_quali;      /* Can use a memory qualifier */
-    int dim_needed;     /* Must indicate dimension */
-    int buf_content;    /* Must indicate buffer contents */
-} descriptor_props[] = {
-    [VK_DESCRIPTOR_TYPE_SAMPLER]                = { sizeof(VkDescriptorImageInfo),  "sampler",       1, 0, 0, 0, },
-    [VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE]          = { sizeof(VkDescriptorImageInfo),  "texture",       1, 0, 1, 0, },
-    [VK_DESCRIPTOR_TYPE_STORAGE_IMAGE]          = { sizeof(VkDescriptorImageInfo),  "image",         1, 1, 1, 0, },
-    [VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT]       = { sizeof(VkDescriptorImageInfo),  "subpassInput",  1, 0, 0, 0, },
-    [VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] = { sizeof(VkDescriptorImageInfo),  "sampler",       1, 0, 1, 0, },
-    [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER]         = { sizeof(VkDescriptorBufferInfo),  NULL,           1, 0, 0, 1, },
-    [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER]         = { sizeof(VkDescriptorBufferInfo), "buffer",        0, 1, 0, 1, },
-    [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo),  NULL,           1, 0, 0, 1, },
-    [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), "buffer",        0, 1, 0, 1, },
-    [VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER]   = { sizeof(VkBufferView),           "samplerBuffer", 1, 0, 0, 0, },
-    [VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER]   = { sizeof(VkBufferView),           "imageBuffer",   1, 0, 0, 0, },
-};
-
-int ff_vk_shader_add_descriptor_set(FFVulkanContext *s, FFVulkanShader *shd,
-                                    FFVulkanDescriptorSetBinding *desc, int nb,
-                                    int singular, int print_to_shader_only)
-{
-    int has_sampler = 0;
-    FFVulkanDescriptorSet *set;
-
-    if (print_to_shader_only)
-        goto print;
-
-    /* Actual layout allocated for the pipeline */
-    set = av_realloc_array(shd->desc_set,
-                           sizeof(*shd->desc_set),
-                           shd->nb_descriptor_sets + 1);
-    if (!set)
-        return AVERROR(ENOMEM);
-    shd->desc_set = set;
-
-    set = &set[shd->nb_descriptor_sets];
-    memset(set, 0, sizeof(*set));
-
-    set->binding = av_calloc(nb, sizeof(*set->binding));
-    if (!set->binding)
-        return AVERROR(ENOMEM);
-
-    set->binding_offset = av_calloc(nb, sizeof(*set->binding_offset));
-    if (!set->binding_offset) {
-        av_freep(&set->binding);
-        return AVERROR(ENOMEM);
-    }
-
-    for (int i = 0; i < nb; i++) {
-        set->binding[i].binding            = i;
-        set->binding[i].descriptorType     = desc[i].type;
-        set->binding[i].descriptorCount    = FFMAX(desc[i].elems, 1);
-        set->binding[i].stageFlags         = desc[i].stages;
-        set->binding[i].pImmutableSamplers = desc[i].samplers;
-
-        if (desc[i].type == VK_DESCRIPTOR_TYPE_SAMPLER ||
-            desc[i].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
-            has_sampler |= 1;
-    }
-
-    set->usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT |
-                 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
-    if (has_sampler)
-        set->usage |= VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT;
-
-    if (!(s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER)) {
-        for (int i = 0; i < nb; i++) {
-            int j;
-            VkDescriptorPoolSize *desc_pool_size;
-            for (j = 0; j < shd->nb_desc_pool_size; j++)
-                if (shd->desc_pool_size[j].type == desc[i].type)
-                    break;
-            if (j >= shd->nb_desc_pool_size) {
-                desc_pool_size = av_realloc_array(shd->desc_pool_size,
-                                                  sizeof(*desc_pool_size),
-                                                  shd->nb_desc_pool_size + 1);
-                if (!desc_pool_size)
-                    return AVERROR(ENOMEM);
-
-                shd->desc_pool_size = desc_pool_size;
-                shd->nb_desc_pool_size++;
-                memset(&desc_pool_size[j], 0, sizeof(VkDescriptorPoolSize));
-            }
-            shd->desc_pool_size[j].type             = desc[i].type;
-            shd->desc_pool_size[j].descriptorCount += FFMAX(desc[i].elems, 1);
-        }
-    }
-
-    set->singular = singular;
-    set->nb_bindings = nb;
-    shd->nb_descriptor_sets++;
-
-print:
-    /* Write shader info */
-    for (int i = 0; i < nb; i++) {
-        const struct descriptor_props *prop = &descriptor_props[desc[i].type];
-        GLSLA("layout (set = %i, binding = %i", FFMAX(shd->nb_descriptor_sets - 1, 0), i);
-
-        if (desc[i].mem_layout &&
-            (desc[i].type != VK_DESCRIPTOR_TYPE_STORAGE_IMAGE))
-            GLSLA(", %s", desc[i].mem_layout);
-
-        GLSLA(")");
-
-        if (prop->is_uniform)
-            GLSLA(" uniform");
-
-        if (prop->mem_quali && desc[i].mem_quali)
-            GLSLA(" %s", desc[i].mem_quali);
-
-        if (prop->type) {
-            GLSLA(" ");
-            if (desc[i].type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
-                if (desc[i].mem_layout) {
-                    int len = strlen(desc[i].mem_layout);
-                    if (desc[i].mem_layout[len - 1] == 'i' &&
-                        desc[i].mem_layout[len - 2] == 'u') {
-                        GLSLA("u");
-                    } else if (desc[i].mem_layout[len - 1] == 'i') {
-                        GLSLA("i");
-                    }
-                }
-            }
-            GLSLA("%s", prop->type);
-        }
-
-        if (prop->dim_needed)
-            GLSLA("%iD", desc[i].dimensions);
-
-        GLSLA(" %s", desc[i].name);
-
-        if (prop->buf_content) {
-            GLSLA(" {\n    ");
-            if (desc[i].buf_elems) {
-                GLSLA("%s", desc[i].buf_content);
-                GLSLA("[%i];", desc[i].buf_elems);
-            } else {
-                GLSLA("%s", desc[i].buf_content);
-            }
-            GLSLA("\n}");
-        } else if (desc[i].elems > 0) {
-            GLSLA("[%i]", desc[i].elems);
-        }
-
-        GLSLA(";");
-        GLSLA("\n");
-    }
-    GLSLA("\n");
-
-    return 0;
-}
-
-int ff_vk_shader_register_exec(FFVulkanContext *s, FFVkExecPool *pool,
-                               FFVulkanShader *shd)
-{
-    int err;
-    FFVulkanShaderData *sd;
-
-    if (!shd->nb_descriptor_sets)
-        return 0;
-
-    sd = av_realloc_array(pool->reg_shd,
-                          sizeof(*pool->reg_shd),
-                          pool->nb_reg_shd + 1);
-    if (!sd)
-        return AVERROR(ENOMEM);
-
-    pool->reg_shd = sd;
-    sd = &sd[pool->nb_reg_shd++];
-    memset(sd, 0, sizeof(*sd));
-
-    sd->shd = shd;
-    sd->nb_descriptor_sets = shd->nb_descriptor_sets;
-
-    if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
-        sd->desc_bind = av_malloc_array(sd->nb_descriptor_sets, sizeof(*sd->desc_bind));
-        if (!sd->desc_bind)
-            return AVERROR(ENOMEM);
-
-        sd->desc_set_buf = av_calloc(sd->nb_descriptor_sets, sizeof(*sd->desc_set_buf));
-        if (!sd->desc_set_buf)
-            return AVERROR(ENOMEM);
-
-        for (int i = 0; i < sd->nb_descriptor_sets; i++) {
-            FFVulkanDescriptorSet *set = &shd->desc_set[i];
-            FFVulkanDescriptorSetData *sdb = &sd->desc_set_buf[i];
-            int nb = set->singular ? 1 : pool->pool_size;
-
-            err = ff_vk_create_buf(s, &sdb->buf,
-                                   set->aligned_size*nb,
-                                   NULL, NULL, set->usage,
-                                   VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
-                                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
-                                   VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
-            if (err < 0)
-                return err;
-
-            err = ff_vk_map_buffer(s, &sdb->buf, &sdb->desc_mem, 0);
-            if (err < 0)
-                return err;
-
-            sd->desc_bind[i] = (VkDescriptorBufferBindingInfoEXT) {
-                .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT,
-                .usage = set->usage,
-                .address = sdb->buf.address,
-            };
-        }
-    } else if (!shd->use_push) {
-        VkResult ret;
-        FFVulkanFunctions *vk = &s->vkfn;
-        VkDescriptorSetLayout *tmp_layouts;
-        VkDescriptorSetAllocateInfo set_alloc_info;
-        VkDescriptorPoolCreateInfo pool_create_info;
-
-        for (int i = 0; i < shd->nb_desc_pool_size; i++)
-            shd->desc_pool_size[i].descriptorCount *= pool->pool_size;
-
-        pool_create_info = (VkDescriptorPoolCreateInfo) {
-            .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
-            .flags = 0,
-            .pPoolSizes = shd->desc_pool_size,
-            .poolSizeCount = shd->nb_desc_pool_size,
-            .maxSets = sd->nb_descriptor_sets*pool->pool_size,
-        };
-
-        ret = vk->CreateDescriptorPool(s->hwctx->act_dev, &pool_create_info,
-                                       s->hwctx->alloc, &sd->desc_pool);
-        if (ret != VK_SUCCESS) {
-            av_log(s, AV_LOG_ERROR, "Unable to create descriptor pool: %s\n",
-                   ff_vk_ret2str(ret));
-            return AVERROR_EXTERNAL;
-        }
-
-        tmp_layouts = av_malloc_array(pool_create_info.maxSets, sizeof(*tmp_layouts));
-        if (!tmp_layouts)
-            return AVERROR(ENOMEM);
-
-        /* Colate each execution context's descriptor set layouts */
-        for (int i = 0; i < pool->pool_size; i++)
-            for (int j = 0; j < sd->nb_descriptor_sets; j++)
-                tmp_layouts[i*sd->nb_descriptor_sets + j] = shd->desc_layout[j];
-
-        set_alloc_info = (VkDescriptorSetAllocateInfo) {
-            .sType              = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
-            .descriptorPool     = sd->desc_pool,
-            .pSetLayouts        = tmp_layouts,
-            .descriptorSetCount = pool_create_info.maxSets,
-        };
-
-        sd->desc_sets = av_malloc_array(pool_create_info.maxSets,
-                                        sizeof(*tmp_layouts));
-        if (!sd->desc_sets) {
-            av_free(tmp_layouts);
-            return AVERROR(ENOMEM);
-        }
-        ret = vk->AllocateDescriptorSets(s->hwctx->act_dev, &set_alloc_info,
-                                         sd->desc_sets);
-        av_free(tmp_layouts);
-        if (ret != VK_SUCCESS) {
-            av_log(s, AV_LOG_ERROR, "Unable to allocate descriptor set: %s\n",
-                   ff_vk_ret2str(ret));
-            av_freep(&sd->desc_sets);
-            return AVERROR_EXTERNAL;
-        }
-    }
-
-    return 0;
-}
-
-static inline FFVulkanShaderData *get_shd_data(FFVkExecContext *e,
-                                               FFVulkanShader *shd)
-{
-    for (int i = 0; i < e->parent->nb_reg_shd; i++)
-        if (e->parent->reg_shd[i].shd == shd)
-            return &e->parent->reg_shd[i];
-    return NULL;
-}
-
-static inline void update_set_descriptor(FFVulkanContext *s, FFVkExecContext *e,
-                                         FFVulkanShader *shd, int set,
-                                         int bind_idx, int array_idx,
-                                         VkDescriptorGetInfoEXT *desc_get_info,
-                                         size_t desc_size)
-{
-    FFVulkanFunctions *vk = &s->vkfn;
-    FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
-    FFVulkanShaderData *sd = get_shd_data(e, shd);
-    const size_t exec_offset = desc_set->singular ? 0 : desc_set->aligned_size*e->idx;
-
-    void *desc = sd->desc_set_buf[set].desc_mem +     /* Base */
-                 exec_offset +                        /* Execution context */
-                 desc_set->binding_offset[bind_idx] + /* Descriptor binding */
-                 array_idx*desc_size;                 /* Array position */
-
-    vk->GetDescriptorEXT(s->hwctx->act_dev, desc_get_info, desc_size, desc);
-}
-
-static inline void update_set_pool_write(FFVulkanContext *s, FFVkExecContext *e,
-                                         FFVulkanShader *shd, int set,
-                                         VkWriteDescriptorSet *write_info)
-{
-    FFVulkanFunctions *vk = &s->vkfn;
-    FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
-    FFVulkanShaderData *sd = get_shd_data(e, shd);
-
-    if (desc_set->singular) {
-        for (int i = 0; i < e->parent->pool_size; i++) {
-            write_info->dstSet = sd->desc_sets[i*sd->nb_descriptor_sets + set];
-            vk->UpdateDescriptorSets(s->hwctx->act_dev, 1, write_info, 0, NULL);
-        }
-    } else {
-        if (shd->use_push) {
-            vk->CmdPushDescriptorSetKHR(e->buf,
-                                        shd->bind_point,
-                                        shd->pipeline_layout,
-                                        set, 1,
-                                        write_info);
-        } else {
-            write_info->dstSet = sd->desc_sets[e->idx*sd->nb_descriptor_sets + set];
-            vk->UpdateDescriptorSets(s->hwctx->act_dev, 1, write_info, 0, NULL);
-        }
-    }
-}
-
-int ff_vk_shader_update_img(FFVulkanContext *s, FFVkExecContext *e,
-                            FFVulkanShader *shd, int set, int bind, int offs,
-                            VkImageView view, VkImageLayout layout,
-                            VkSampler sampler)
-{
-    FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
-
-    if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
-        VkDescriptorGetInfoEXT desc_get_info = {
-            .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
-            .type = desc_set->binding[bind].descriptorType,
-        };
-        VkDescriptorImageInfo desc_img_info = {
-            .imageView = view,
-            .sampler = sampler,
-            .imageLayout = layout,
-        };
-        size_t desc_size;
-
-        switch (desc_get_info.type) {
-        case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
-            desc_get_info.data.pSampledImage = &desc_img_info;
-            desc_size = s->desc_buf_props.sampledImageDescriptorSize;
-            break;
-        case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
-            desc_get_info.data.pStorageImage = &desc_img_info;
-            desc_size = s->desc_buf_props.storageImageDescriptorSize;
-            break;
-        case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
-            desc_get_info.data.pInputAttachmentImage = &desc_img_info;
-            desc_size = s->desc_buf_props.inputAttachmentDescriptorSize;
-            break;
-        case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
-            desc_get_info.data.pCombinedImageSampler = &desc_img_info;
-            desc_size = s->desc_buf_props.combinedImageSamplerDescriptorSize;
-            break;
-        default:
-            av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n",
-                   set, bind, desc_get_info.type);
-            return AVERROR(EINVAL);
-            break;
-        };
-
-        update_set_descriptor(s, e, shd, set, bind, offs,
-                              &desc_get_info, desc_size);
-    } else {
-        VkDescriptorImageInfo desc_pool_write_info_img = {
-            .sampler = sampler,
-            .imageView = view,
-            .imageLayout = layout,
-        };
-        VkWriteDescriptorSet desc_pool_write_info = {
-            .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
-            .dstBinding = bind,
-            .descriptorCount = 1,
-            .dstArrayElement = offs,
-            .descriptorType = desc_set->binding[bind].descriptorType,
-            .pImageInfo = &desc_pool_write_info_img,
-        };
-        update_set_pool_write(s, e, shd, set, &desc_pool_write_info);
-    }
-
-    return 0;
-}
-
-void ff_vk_shader_update_img_array(FFVulkanContext *s, FFVkExecContext *e,
-                                   FFVulkanShader *shd, AVFrame *f,
-                                   VkImageView *views, int set, int binding,
-                                   VkImageLayout layout, VkSampler sampler)
-{
-    AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
-    const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
-
-    for (int i = 0; i < nb_planes; i++)
-        ff_vk_shader_update_img(s, e, shd, set, binding, i,
-                                views[i], layout, sampler);
-}
-
-int ff_vk_shader_update_desc_buffer(FFVulkanContext *s, FFVkExecContext *e,
-                                    FFVulkanShader *shd,
-                                    int set, int bind, int elem,
-                                    FFVkBuffer *buf, VkDeviceSize offset, VkDeviceSize len,
-                                    VkFormat fmt)
-{
-    FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
-
-    if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
-        VkDescriptorGetInfoEXT desc_get_info = {
-            .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
-            .type = desc_set->binding[bind].descriptorType,
-        };
-        VkDescriptorAddressInfoEXT desc_buf_info = {
-            .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT,
-            .address = buf->address + offset,
-            .range = len,
-            .format = fmt,
-        };
-        size_t desc_size;
-
-        switch (desc_get_info.type) {
-        case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
-            desc_get_info.data.pUniformBuffer = &desc_buf_info;
-            desc_size = s->desc_buf_props.uniformBufferDescriptorSize;
-            break;
-        case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
-            desc_get_info.data.pStorageBuffer = &desc_buf_info;
-            desc_size = s->desc_buf_props.storageBufferDescriptorSize;
-            break;
-        case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
-            desc_get_info.data.pUniformTexelBuffer = &desc_buf_info;
-            desc_size = s->desc_buf_props.uniformTexelBufferDescriptorSize;
-            break;
-        case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
-            desc_get_info.data.pStorageTexelBuffer = &desc_buf_info;
-            desc_size = s->desc_buf_props.storageTexelBufferDescriptorSize;
-            break;
-        default:
-            av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n",
-                   set, bind, desc_get_info.type);
-            return AVERROR(EINVAL);
-            break;
-        };
-
-        update_set_descriptor(s, e, shd, set, bind, elem, &desc_get_info, desc_size);
-    } else {
-        VkDescriptorBufferInfo desc_pool_write_info_buf = {
-            .buffer = buf->buf,
-            .offset = buf->virtual_offset + offset,
-            .range = len,
-        };
-        VkWriteDescriptorSet desc_pool_write_info = {
-            .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
-            .dstBinding = bind,
-            .descriptorCount = 1,
-            .dstArrayElement = elem,
-            .descriptorType = desc_set->binding[bind].descriptorType,
-            .pBufferInfo = &desc_pool_write_info_buf,
-        };
-        update_set_pool_write(s, e, shd, set, &desc_pool_write_info);
-    }
-
-    return 0;
-}
-
-void ff_vk_shader_update_push_const(FFVulkanContext *s, FFVkExecContext *e,
-                                    FFVulkanShader *shd,
-                                    VkShaderStageFlagBits stage,
-                                    int offset, size_t size, void *src)
-{
-    FFVulkanFunctions *vk = &s->vkfn;
-    vk->CmdPushConstants(e->buf, shd->pipeline_layout,
-                         stage, offset, size, src);
-}
-
-void ff_vk_exec_bind_shader(FFVulkanContext *s, FFVkExecContext *e,
-                            FFVulkanShader *shd)
-{
-    FFVulkanFunctions *vk = &s->vkfn;
-    VkDeviceSize offsets[1024];
-    FFVulkanShaderData *sd = get_shd_data(e, shd);
-
-    if (s->extensions & FF_VK_EXT_SHADER_OBJECT) {
-        VkShaderStageFlagBits stages = shd->stage;
-        vk->CmdBindShadersEXT(e->buf, 1, &stages, &shd->object);
-    } else {
-        vk->CmdBindPipeline(e->buf, shd->bind_point, shd->pipeline);
-    }
-
-    if (sd && sd->nb_descriptor_sets) {
-        if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
-            for (int i = 0; i < sd->nb_descriptor_sets; i++)
-                offsets[i] = shd->desc_set[i].singular ? 0 : shd->desc_set[i].aligned_size*e->idx;
-
-            /* Bind descriptor buffers */
-            vk->CmdBindDescriptorBuffersEXT(e->buf, sd->nb_descriptor_sets, sd->desc_bind);
-            /* Binding offsets */
-            vk->CmdSetDescriptorBufferOffsetsEXT(e->buf, shd->bind_point, shd->pipeline_layout,
-                                                 0, sd->nb_descriptor_sets,
-                                                 shd->bound_buffer_indices, offsets);
-        } else if (!shd->use_push) {
-            vk->CmdBindDescriptorSets(e->buf, shd->bind_point, shd->pipeline_layout,
-                                      0, sd->nb_descriptor_sets,
-                                      &sd->desc_sets[e->idx*sd->nb_descriptor_sets],
-                                      0, NULL);
-        }
-    }
-}
-
-void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd)
-{
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    av_bprint_finalize(&shd->src, NULL);
-
-#if 0
-    if (shd->shader.module)
-        vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module,
-                                s->hwctx->alloc);
-#endif
-
-    if (shd->object)
-        vk->DestroyShaderEXT(s->hwctx->act_dev, shd->object, s->hwctx->alloc);
-    if (shd->pipeline)
-        vk->DestroyPipeline(s->hwctx->act_dev, shd->pipeline, s->hwctx->alloc);
-    if (shd->pipeline_layout)
-        vk->DestroyPipelineLayout(s->hwctx->act_dev, shd->pipeline_layout,
-                                  s->hwctx->alloc);
-
-    for (int i = 0; i < shd->nb_descriptor_sets; i++) {
-        FFVulkanDescriptorSet *set = &shd->desc_set[i];
-        av_free(set->binding);
-        av_free(set->binding_offset);
-    }
-
-    if (shd->desc_layout) {
-        for (int i = 0; i < shd->nb_descriptor_sets; i++)
-            if (shd->desc_layout[i])
-                vk->DestroyDescriptorSetLayout(s->hwctx->act_dev, shd->desc_layout[i],
-                                               s->hwctx->alloc);
-    }
-
-    av_freep(&shd->desc_pool_size);
-    av_freep(&shd->desc_layout);
-    av_freep(&shd->desc_set);
-    av_freep(&shd->bound_buffer_indices);
-    av_freep(&shd->push_consts);
-    shd->push_consts_num = 0;
-}
-
-void ff_vk_uninit(FFVulkanContext *s)
-{
-    av_freep(&s->query_props);
-    av_freep(&s->qf_props);
-    av_freep(&s->video_props);
-    av_freep(&s->coop_mat_props);
-    av_freep(&s->host_image_copy_layouts);
-
-    av_buffer_unref(&s->device_ref);
-    av_buffer_unref(&s->frames_ref);
-}
-
-int ff_vk_init(FFVulkanContext *s, void *log_parent,
-               AVBufferRef *device_ref, AVBufferRef *frames_ref)
-{
-    int err;
-
-    static const AVClass vulkan_context_class = {
-        .class_name       = "vk",
-        .version          = LIBAVUTIL_VERSION_INT,
-        .parent_log_context_offset = offsetof(FFVulkanContext, log_parent),
-    };
-
-    memset(s, 0, sizeof(*s));
-    s->log_parent = log_parent;
-    s->class      = &vulkan_context_class;
-
-    if (frames_ref) {
-        s->frames_ref = av_buffer_ref(frames_ref);
-        if (!s->frames_ref)
-            return AVERROR(ENOMEM);
-
-        s->frames = (AVHWFramesContext *)s->frames_ref->data;
-        s->hwfc = s->frames->hwctx;
-
-        device_ref = s->frames->device_ref;
-    }
-
-    s->device_ref = av_buffer_ref(device_ref);
-    if (!s->device_ref) {
-        ff_vk_uninit(s);
-        return AVERROR(ENOMEM);
-    }
-
-    s->device = (AVHWDeviceContext *)s->device_ref->data;
-    s->hwctx = s->device->hwctx;
-
-    s->extensions = ff_vk_extensions_to_mask(s->hwctx->enabled_dev_extensions,
-                                             s->hwctx->nb_enabled_dev_extensions);
-    s->extensions |= ff_vk_extensions_to_mask(s->hwctx->enabled_inst_extensions,
-                                              s->hwctx->nb_enabled_inst_extensions);
-
-    err = ff_vk_load_functions(s->device, &s->vkfn, s->extensions, 1, 1);
-    if (err < 0) {
-        ff_vk_uninit(s);
-        return err;
-    }
-
-    err = ff_vk_load_props(s);
-    if (err < 0) {
-        ff_vk_uninit(s);
-        return err;
-    }
-
-    return 0;
-}
-- 
2.49.1


From 748d3cd28818b7d8af7fc255b1b22dd9cf50b5a6 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:17:34 +0000
Subject: [PATCH 044/118] Changing vulkan file directory

---
 libavutil/vulkan/vulkan.c | 3029 +++++++++++++++++++++++++++++++++++++
 1 file changed, 3029 insertions(+)
 create mode 100644 libavutil/vulkan/vulkan.c

diff --git a/libavutil/vulkan/vulkan.c b/libavutil/vulkan/vulkan.c
new file mode 100644
index 0000000000..8f716c8b45
--- /dev/null
+++ b/libavutil/vulkan/vulkan.c
@@ -0,0 +1,3029 @@
+/*
+ * Copyright (c) Lynne
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/avassert.h"
+#include "libavutil/mem.h"
+
+#include "vulkan.h"
+#include "libavutil/vulkan_loader.h"
+
+const VkComponentMapping ff_comp_identity_map = {
+    .r = VK_COMPONENT_SWIZZLE_IDENTITY,
+    .g = VK_COMPONENT_SWIZZLE_IDENTITY,
+    .b = VK_COMPONENT_SWIZZLE_IDENTITY,
+    .a = VK_COMPONENT_SWIZZLE_IDENTITY,
+};
+
+/* Converts return values to strings */
+const char *ff_vk_ret2str(VkResult res)
+{
+#define CASE(VAL) case VAL: return #VAL
+    switch (res) {
+    CASE(VK_SUCCESS);
+    CASE(VK_NOT_READY);
+    CASE(VK_TIMEOUT);
+    CASE(VK_EVENT_SET);
+    CASE(VK_EVENT_RESET);
+    CASE(VK_INCOMPLETE);
+    CASE(VK_ERROR_OUT_OF_HOST_MEMORY);
+    CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY);
+    CASE(VK_ERROR_INITIALIZATION_FAILED);
+    CASE(VK_ERROR_DEVICE_LOST);
+    CASE(VK_ERROR_MEMORY_MAP_FAILED);
+    CASE(VK_ERROR_LAYER_NOT_PRESENT);
+    CASE(VK_ERROR_EXTENSION_NOT_PRESENT);
+    CASE(VK_ERROR_FEATURE_NOT_PRESENT);
+    CASE(VK_ERROR_INCOMPATIBLE_DRIVER);
+    CASE(VK_ERROR_TOO_MANY_OBJECTS);
+    CASE(VK_ERROR_FORMAT_NOT_SUPPORTED);
+    CASE(VK_ERROR_FRAGMENTED_POOL);
+    CASE(VK_ERROR_UNKNOWN);
+    CASE(VK_ERROR_OUT_OF_POOL_MEMORY);
+    CASE(VK_ERROR_INVALID_EXTERNAL_HANDLE);
+    CASE(VK_ERROR_FRAGMENTATION);
+    CASE(VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS);
+    CASE(VK_PIPELINE_COMPILE_REQUIRED);
+    CASE(VK_ERROR_SURFACE_LOST_KHR);
+    CASE(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR);
+    CASE(VK_SUBOPTIMAL_KHR);
+    CASE(VK_ERROR_OUT_OF_DATE_KHR);
+    CASE(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR);
+    CASE(VK_ERROR_VALIDATION_FAILED_EXT);
+    CASE(VK_ERROR_INVALID_SHADER_NV);
+    CASE(VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR);
+    CASE(VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR);
+    CASE(VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR);
+    CASE(VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR);
+    CASE(VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR);
+    CASE(VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT);
+    CASE(VK_ERROR_NOT_PERMITTED_KHR);
+    CASE(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT);
+    CASE(VK_THREAD_IDLE_KHR);
+    CASE(VK_THREAD_DONE_KHR);
+    CASE(VK_OPERATION_DEFERRED_KHR);
+    CASE(VK_OPERATION_NOT_DEFERRED_KHR);
+    default: return "Unknown error";
+    }
+#undef CASE
+}
+
+/* Malitia pura, Khronos */
+#define FN_MAP_TO(dst_t, dst_name, src_t, src_name)                                 \
+    dst_t ff_vk_map_ ##src_name## _to_ ##dst_name(src_t src) \
+    {                                                                   \
+        dst_t dst = 0x0;                                                \
+        MAP_TO(VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT,                   \
+               VK_IMAGE_USAGE_SAMPLED_BIT);                             \
+        MAP_TO(VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT,                    \
+               VK_IMAGE_USAGE_TRANSFER_SRC_BIT);                        \
+        MAP_TO(VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT,                    \
+               VK_IMAGE_USAGE_TRANSFER_DST_BIT);                        \
+        MAP_TO(VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT,                   \
+               VK_IMAGE_USAGE_STORAGE_BIT);                             \
+        MAP_TO(VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT,                \
+               VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);                    \
+        MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR,         \
+               VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR);                \
+        MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR,            \
+               VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR);                \
+        MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR,            \
+               VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR);                \
+        MAP_TO(VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR,          \
+               VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR);                \
+        MAP_TO(VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT,         \
+               VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT);                   \
+        return dst;                                                     \
+    }
+
+#define MAP_TO(flag1, flag2) if (src & flag2) dst |= flag1;
+FN_MAP_TO(VkFormatFeatureFlagBits2, feats, VkImageUsageFlags, usage)
+#undef MAP_TO
+#define MAP_TO(flag1, flag2) if (src & flag1) dst |= flag2;
+FN_MAP_TO(VkImageUsageFlags, usage, VkFormatFeatureFlagBits2, feats)
+#undef MAP_TO
+#undef FN_MAP_TO
+
+static void load_enabled_qfs(FFVulkanContext *s)
+{
+    s->nb_qfs = 0;
+    for (int i = 0; i < s->hwctx->nb_qf; i++) {
+        /* Skip duplicates */
+        int skip = 0;
+        for (int j = 0; j < s->nb_qfs; j++) {
+            if (s->qfs[j] == s->hwctx->qf[i].idx) {
+                skip = 1;
+                break;
+            }
+        }
+        if (skip)
+            continue;
+
+        s->qfs[s->nb_qfs++] = s->hwctx->qf[i].idx;
+    }
+}
+
+int ff_vk_load_props(FFVulkanContext *s)
+{
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    s->props = (VkPhysicalDeviceProperties2) {
+        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
+    };
+
+    FF_VK_STRUCT_EXT(s, &s->props, &s->props_11, FF_VK_EXT_NO_FLAG,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES);
+    FF_VK_STRUCT_EXT(s, &s->props, &s->driver_props, FF_VK_EXT_NO_FLAG,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES);
+    FF_VK_STRUCT_EXT(s, &s->props, &s->subgroup_props, FF_VK_EXT_NO_FLAG,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES);
+
+    FF_VK_STRUCT_EXT(s, &s->props, &s->push_desc_props, FF_VK_EXT_PUSH_DESCRIPTOR,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR);
+    FF_VK_STRUCT_EXT(s, &s->props, &s->hprops, FF_VK_EXT_EXTERNAL_HOST_MEMORY,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT);
+    FF_VK_STRUCT_EXT(s, &s->props, &s->coop_matrix_props, FF_VK_EXT_COOP_MATRIX,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR);
+    FF_VK_STRUCT_EXT(s, &s->props, &s->desc_buf_props, FF_VK_EXT_DESCRIPTOR_BUFFER,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT);
+    FF_VK_STRUCT_EXT(s, &s->props, &s->optical_flow_props, FF_VK_EXT_OPTICAL_FLOW,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV);
+    FF_VK_STRUCT_EXT(s, &s->props, &s->host_image_props, FF_VK_EXT_HOST_IMAGE_COPY,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT);
+
+    s->feats = (VkPhysicalDeviceFeatures2) {
+        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
+    };
+
+    FF_VK_STRUCT_EXT(s, &s->feats, &s->feats_12, FF_VK_EXT_NO_FLAG,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES);
+    FF_VK_STRUCT_EXT(s, &s->feats, &s->atomic_float_feats, FF_VK_EXT_ATOMIC_FLOAT,
+                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT);
+
+    /* Try allocating 1024 layouts */
+    s->host_image_copy_layouts = av_malloc(sizeof(*s->host_image_copy_layouts)*1024);
+    s->host_image_props.pCopySrcLayouts = s->host_image_copy_layouts;
+    s->host_image_props.copySrcLayoutCount = 512;
+    s->host_image_props.pCopyDstLayouts = s->host_image_copy_layouts + 512;
+    s->host_image_props.copyDstLayoutCount = 512;
+
+    vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props);
+
+    /* Check if we had enough memory for all layouts */
+    if (s->host_image_props.copySrcLayoutCount == 512 ||
+        s->host_image_props.copyDstLayoutCount == 512) {
+        VkImageLayout *new_array;
+        size_t new_size;
+        s->host_image_props.pCopySrcLayouts =
+        s->host_image_props.pCopyDstLayouts = NULL;
+        s->host_image_props.copySrcLayoutCount =
+        s->host_image_props.copyDstLayoutCount = 0;
+        vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props);
+
+        new_size = s->host_image_props.copySrcLayoutCount +
+                   s->host_image_props.copyDstLayoutCount;
+        new_size *= sizeof(*s->host_image_copy_layouts);
+        new_array = av_realloc(s->host_image_copy_layouts, new_size);
+        if (!new_array)
+            return AVERROR(ENOMEM);
+
+        s->host_image_copy_layouts = new_array;
+        s->host_image_props.pCopySrcLayouts = new_array;
+        s->host_image_props.pCopyDstLayouts = new_array + s->host_image_props.copySrcLayoutCount;
+        vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props);
+    }
+
+    vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops);
+    vk->GetPhysicalDeviceFeatures2(s->hwctx->phys_dev, &s->feats);
+
+    load_enabled_qfs(s);
+
+    if (s->qf_props)
+        return 0;
+
+    vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &s->tot_nb_qfs, NULL);
+
+    s->qf_props = av_calloc(s->tot_nb_qfs, sizeof(*s->qf_props));
+    if (!s->qf_props)
+        return AVERROR(ENOMEM);
+
+    s->query_props = av_calloc(s->tot_nb_qfs, sizeof(*s->query_props));
+    if (!s->qf_props) {
+        av_freep(&s->qf_props);
+        return AVERROR(ENOMEM);
+    }
+
+    s->video_props = av_calloc(s->tot_nb_qfs, sizeof(*s->video_props));
+    if (!s->video_props) {
+        av_freep(&s->qf_props);
+        av_freep(&s->query_props);
+        return AVERROR(ENOMEM);
+    }
+
+    for (uint32_t i = 0; i < s->tot_nb_qfs; i++) {
+        s->qf_props[i] = (VkQueueFamilyProperties2) {
+            .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
+        };
+
+        FF_VK_STRUCT_EXT(s, &s->qf_props[i], &s->query_props[i], FF_VK_EXT_NO_FLAG,
+                         VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR);
+        FF_VK_STRUCT_EXT(s, &s->qf_props[i], &s->video_props[i], FF_VK_EXT_VIDEO_QUEUE,
+                         VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR);
+    }
+
+    vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &s->tot_nb_qfs, s->qf_props);
+
+    if (s->extensions & FF_VK_EXT_COOP_MATRIX) {
+        vk->GetPhysicalDeviceCooperativeMatrixPropertiesKHR(s->hwctx->phys_dev,
+                                                            &s->coop_mat_props_nb, NULL);
+
+        if (s->coop_mat_props_nb) {
+            s->coop_mat_props = av_malloc_array(s->coop_mat_props_nb,
+                                                sizeof(VkCooperativeMatrixPropertiesKHR));
+            for (int i = 0; i < s->coop_mat_props_nb; i++) {
+                s->coop_mat_props[i] = (VkCooperativeMatrixPropertiesKHR) {
+                    .sType = VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_KHR,
+                };
+            }
+
+            vk->GetPhysicalDeviceCooperativeMatrixPropertiesKHR(s->hwctx->phys_dev,
+                                                                &s->coop_mat_props_nb,
+                                                                s->coop_mat_props);
+        }
+    }
+
+    return 0;
+}
+
+AVVulkanDeviceQueueFamily *ff_vk_qf_find(FFVulkanContext *s,
+                                         VkQueueFlagBits dev_family,
+                                         VkVideoCodecOperationFlagBitsKHR vid_ops)
+{
+    for (int i = 0; i < s->hwctx->nb_qf; i++) {
+        if ((s->hwctx->qf[i].flags & dev_family) &&
+            (s->hwctx->qf[i].video_caps & vid_ops) == vid_ops) {
+            return &s->hwctx->qf[i];
+        }
+    }
+    return NULL;
+}
+
+void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
+{
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    for (int i = 0; i < pool->pool_size; i++) {
+        FFVkExecContext *e = &pool->contexts[i];
+
+        if (e->fence) {
+            if (e->had_submission)
+                vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
+            vk->DestroyFence(s->hwctx->act_dev, e->fence, s->hwctx->alloc);
+        }
+
+        ff_vk_exec_discard_deps(s, e);
+
+        av_free(e->frame_deps);
+        av_free(e->sw_frame_deps);
+        av_free(e->buf_deps);
+        av_free(e->queue_family_dst);
+        av_free(e->layout_dst);
+        av_free(e->access_dst);
+        av_free(e->frame_update);
+        av_free(e->frame_locked);
+        av_free(e->sem_sig);
+        av_free(e->sem_sig_val_dst);
+        av_free(e->sem_wait);
+    }
+
+    /* Free shader-specific data */
+    for (int i = 0; i < pool->nb_reg_shd; i++) {
+        FFVulkanShaderData *sd = &pool->reg_shd[i];
+
+        if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
+            for (int j = 0; j < sd->nb_descriptor_sets; j++) {
+                FFVulkanDescriptorSetData *set_data = &sd->desc_set_buf[j];
+                if (set_data->buf.mem)
+                    ff_vk_unmap_buffer(s, &set_data->buf, 0);
+                ff_vk_free_buf(s, &set_data->buf);
+            }
+        }
+
+        if (sd->desc_pool)
+            vk->DestroyDescriptorPool(s->hwctx->act_dev, sd->desc_pool,
+                                      s->hwctx->alloc);
+
+        av_freep(&sd->desc_set_buf);
+        av_freep(&sd->desc_bind);
+        av_freep(&sd->desc_sets);
+    }
+
+    av_freep(&pool->reg_shd);
+
+    for (int i = 0; i < pool->pool_size; i++) {
+        if (pool->cmd_buf_pools[i])
+            vk->FreeCommandBuffers(s->hwctx->act_dev, pool->cmd_buf_pools[i],
+                                   1, &pool->cmd_bufs[i]);
+
+        if (pool->cmd_buf_pools[i])
+            vk->DestroyCommandPool(s->hwctx->act_dev, pool->cmd_buf_pools[i], s->hwctx->alloc);
+    }
+    if (pool->query_pool)
+        vk->DestroyQueryPool(s->hwctx->act_dev, pool->query_pool, s->hwctx->alloc);
+
+    av_free(pool->query_data);
+    av_free(pool->cmd_buf_pools);
+    av_free(pool->cmd_bufs);
+    av_free(pool->contexts);
+}
+
+int ff_vk_exec_pool_init(FFVulkanContext *s, AVVulkanDeviceQueueFamily *qf,
+                         FFVkExecPool *pool, int nb_contexts,
+                         int nb_queries, VkQueryType query_type, int query_64bit,
+                         const void *query_create_pnext)
+{
+    int err;
+    VkResult ret;
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    VkCommandPoolCreateInfo cqueue_create;
+    VkCommandBufferAllocateInfo cbuf_create;
+
+    const VkQueryPoolVideoEncodeFeedbackCreateInfoKHR *ef = NULL;
+
+    atomic_init(&pool->idx, 0);
+
+    if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) {
+        ef = ff_vk_find_struct(query_create_pnext,
+                               VK_STRUCTURE_TYPE_QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR);
+        if (!ef)
+            return AVERROR(EINVAL);
+    }
+
+    /* Allocate space for command buffer pools */
+    pool->cmd_buf_pools = av_malloc(nb_contexts*sizeof(*pool->cmd_buf_pools));
+    if (!pool->cmd_buf_pools) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    /* Allocate space for command buffers */
+    pool->cmd_bufs = av_malloc(nb_contexts*sizeof(*pool->cmd_bufs));
+    if (!pool->cmd_bufs) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    for (int i = 0; i < nb_contexts; i++) {
+        /* Create command pool */
+        cqueue_create = (VkCommandPoolCreateInfo) {
+            .sType              = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+            .flags              = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
+                                  VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
+            .queueFamilyIndex   = qf->idx,
+        };
+
+        ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create,
+                                    s->hwctx->alloc, &pool->cmd_buf_pools[i]);
+        if (ret != VK_SUCCESS) {
+            av_log(s, AV_LOG_ERROR, "Command pool creation failure: %s\n",
+                   ff_vk_ret2str(ret));
+            err = AVERROR_EXTERNAL;
+            goto fail;
+        }
+
+        /* Allocate command buffer */
+        cbuf_create = (VkCommandBufferAllocateInfo) {
+            .sType              = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+            .level              = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+            .commandPool        = pool->cmd_buf_pools[i],
+            .commandBufferCount = 1,
+        };
+        ret = vk->AllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create,
+                                         &pool->cmd_bufs[i]);
+        if (ret != VK_SUCCESS) {
+            av_log(s, AV_LOG_ERROR, "Command buffer alloc failure: %s\n",
+                   ff_vk_ret2str(ret));
+            err = AVERROR_EXTERNAL;
+            goto fail;
+        }
+    }
+
+    /* Query pool */
+    if (nb_queries) {
+        VkQueryPoolCreateInfo query_pool_info = {
+            .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
+            .pNext = query_create_pnext,
+            .queryType = query_type,
+            .queryCount = nb_queries*nb_contexts,
+        };
+        ret = vk->CreateQueryPool(s->hwctx->act_dev, &query_pool_info,
+                                  s->hwctx->alloc, &pool->query_pool);
+        if (ret != VK_SUCCESS) {
+            av_log(s, AV_LOG_ERROR, "Query pool alloc failure: %s\n",
+                   ff_vk_ret2str(ret));
+            err = AVERROR_EXTERNAL;
+            goto fail;
+        }
+
+        pool->nb_queries = nb_queries;
+        pool->query_status_stride = 1 + 1; /* One result, one status by default */
+        pool->query_results = nb_queries;
+        pool->query_statuses = nb_queries;
+
+        /* Video encode queries produce two results per query */
+        if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) {
+            int nb_results = av_popcount(ef->encodeFeedbackFlags);
+            pool->query_status_stride = nb_results + 1;
+            pool->query_results *= nb_results;
+        } else if (query_type == VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR) {
+            pool->query_status_stride = 1;
+            pool->query_results = 0;
+        }
+
+        pool->qd_size = (pool->query_results + pool->query_statuses)*(query_64bit ? 8 : 4);
+
+        /* Allocate space for the query data */
+        pool->query_data = av_calloc(nb_contexts, pool->qd_size);
+        if (!pool->query_data) {
+            err = AVERROR(ENOMEM);
+            goto fail;
+        }
+    }
+
+    /* Allocate space for the contexts */
+    pool->contexts = av_calloc(nb_contexts, sizeof(*pool->contexts));
+    if (!pool->contexts) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    pool->pool_size = nb_contexts;
+
+    /* Init contexts */
+    for (int i = 0; i < pool->pool_size; i++) {
+        FFVkExecContext *e = &pool->contexts[i];
+        VkFenceCreateInfo fence_create = {
+            .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+            .flags = VK_FENCE_CREATE_SIGNALED_BIT,
+        };
+
+        /* Fence */
+        ret = vk->CreateFence(s->hwctx->act_dev, &fence_create, s->hwctx->alloc,
+                              &e->fence);
+        if (ret != VK_SUCCESS) {
+            av_log(s, AV_LOG_ERROR, "Failed to create submission fence: %s\n",
+                   ff_vk_ret2str(ret));
+            return AVERROR_EXTERNAL;
+        }
+
+        e->idx = i;
+        e->parent = pool;
+
+        /* Query data */
+        e->query_data = ((uint8_t *)pool->query_data) + pool->qd_size*i;
+        e->query_idx = nb_queries*i;
+
+        /* Command buffer */
+        e->buf = pool->cmd_bufs[i];
+
+        /* Queue index distribution */
+        e->qi = i % qf->num;
+        e->qf = qf->idx;
+        vk->GetDeviceQueue(s->hwctx->act_dev, qf->idx, e->qi, &e->queue);
+    }
+
+    return 0;
+
+fail:
+    ff_vk_exec_pool_free(s, pool);
+    return err;
+}
+
+VkResult ff_vk_exec_get_query(FFVulkanContext *s, FFVkExecContext *e,
+                              void **data, VkQueryResultFlagBits flags)
+{
+    FFVulkanFunctions *vk = &s->vkfn;
+    const FFVkExecPool *pool = e->parent;
+    VkQueryResultFlags qf = flags & ~(VK_QUERY_RESULT_64_BIT |
+                                      VK_QUERY_RESULT_WITH_STATUS_BIT_KHR);
+
+    if (!e->query_data) {
+        av_log(s, AV_LOG_ERROR, "Requested a query with a NULL query_data pointer!\n");
+        return VK_INCOMPLETE;
+    }
+
+    qf |= pool->query_64bit ?
+          VK_QUERY_RESULT_64_BIT : 0x0;
+    qf |= pool->query_statuses ?
+          VK_QUERY_RESULT_WITH_STATUS_BIT_KHR : 0x0;
+
+    if (data)
+        *data = e->query_data;
+
+    return vk->GetQueryPoolResults(s->hwctx->act_dev, pool->query_pool,
+                                   e->query_idx,
+                                   pool->nb_queries,
+                                   pool->qd_size, e->query_data,
+                                   pool->qd_size, qf);
+}
+
+FFVkExecContext *ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
+{
+    return &pool->contexts[atomic_fetch_add(&pool->idx, 1) % pool->pool_size];
+}
+
+void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
+{
+    FFVulkanFunctions *vk = &s->vkfn;
+    vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
+    ff_vk_exec_discard_deps(s, e);
+}
+
+int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
+{
+    VkResult ret;
+    FFVulkanFunctions *vk = &s->vkfn;
+    const FFVkExecPool *pool = e->parent;
+
+    VkCommandBufferBeginInfo cmd_start = {
+        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+        .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
+    };
+
+    /* Wait for the fence to be signalled */
+    vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
+    vk->ResetFences(s->hwctx->act_dev, 1, &e->fence);
+
+    /* Discard queue dependencies */
+    ff_vk_exec_discard_deps(s, e);
+
+    ret = vk->BeginCommandBuffer(e->buf, &cmd_start);
+    if (ret != VK_SUCCESS) {
+        av_log(s, AV_LOG_ERROR, "Failed to start command recoding: %s\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+
+    if (pool->nb_queries)
+        vk->CmdResetQueryPool(e->buf, pool->query_pool,
+                              e->query_idx, pool->nb_queries);
+
+    return 0;
+}
+
+void ff_vk_exec_discard_deps(FFVulkanContext *s, FFVkExecContext *e)
+{
+    for (int j = 0; j < e->nb_buf_deps; j++)
+        av_buffer_unref(&e->buf_deps[j]);
+    e->nb_buf_deps = 0;
+
+    for (int j = 0; j < e->nb_sw_frame_deps; j++)
+        av_frame_free(&e->sw_frame_deps[j]);
+    e->nb_sw_frame_deps = 0;
+
+    for (int j = 0; j < e->nb_frame_deps; j++) {
+        AVFrame *f = e->frame_deps[j];
+        if (e->frame_locked[j]) {
+            AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
+            AVVulkanFramesContext *vkfc = hwfc->hwctx;
+            AVVkFrame *vkf = (AVVkFrame *)f->data[0];
+            vkfc->unlock_frame(hwfc, vkf);
+            e->frame_locked[j] = 0;
+        }
+        e->frame_update[j] = 0;
+    }
+    e->nb_frame_deps = 0;
+
+    e->sem_wait_cnt = 0;
+    e->sem_sig_cnt = 0;
+    e->sem_sig_val_dst_cnt = 0;
+}
+
+int ff_vk_exec_add_dep_buf(FFVulkanContext *s, FFVkExecContext *e,
+                           AVBufferRef **deps, int nb_deps, int ref)
+{
+    AVBufferRef **dst = av_fast_realloc(e->buf_deps, &e->buf_deps_alloc_size,
+                                        (e->nb_buf_deps + nb_deps) * sizeof(*dst));
+    if (!dst) {
+        ff_vk_exec_discard_deps(s, e);
+        return AVERROR(ENOMEM);
+    }
+
+    e->buf_deps = dst;
+
+    for (int i = 0; i < nb_deps; i++) {
+        if (!deps[i])
+            continue;
+
+        e->buf_deps[e->nb_buf_deps] = ref ? av_buffer_ref(deps[i]) : deps[i];
+        if (!e->buf_deps[e->nb_buf_deps]) {
+            ff_vk_exec_discard_deps(s, e);
+            return AVERROR(ENOMEM);
+        }
+        e->nb_buf_deps++;
+    }
+
+    return 0;
+}
+
+int ff_vk_exec_add_dep_sw_frame(FFVulkanContext *s, FFVkExecContext *e,
+                                AVFrame *f)
+{
+    AVFrame **dst = av_fast_realloc(e->sw_frame_deps, &e->sw_frame_deps_alloc_size,
+                                    (e->nb_sw_frame_deps + 1) * sizeof(*dst));
+    if (!dst) {
+        ff_vk_exec_discard_deps(s, e);
+        return AVERROR(ENOMEM);
+    }
+
+    e->sw_frame_deps = dst;
+
+    e->sw_frame_deps[e->nb_sw_frame_deps] = av_frame_clone(f);
+    if (!e->sw_frame_deps[e->nb_sw_frame_deps]) {
+        ff_vk_exec_discard_deps(s, e);
+        return AVERROR(ENOMEM);
+    }
+
+    e->nb_sw_frame_deps++;
+
+    return 0;
+}
+
+#define ARR_REALLOC(str, arr, alloc_s, cnt)                               \
+    do {                                                                  \
+        arr = av_fast_realloc(str->arr, alloc_s, (cnt + 1)*sizeof(*arr)); \
+        if (!arr) {                                                       \
+            ff_vk_exec_discard_deps(s, e);                                \
+            return AVERROR(ENOMEM);                                       \
+        }                                                                 \
+        str->arr = arr;                                                   \
+    } while (0)
+
+typedef struct TempSyncCtx {
+    int nb_sem;
+    VkSemaphore sem[];
+} TempSyncCtx;
+
+static void destroy_tmp_semaphores(void *opaque, uint8_t *data)
+{
+    FFVulkanContext *s = opaque;
+    FFVulkanFunctions *vk = &s->vkfn;
+    TempSyncCtx *ts = (TempSyncCtx *)data;
+
+    for (int i = 0; i < ts->nb_sem; i++)
+        vk->DestroySemaphore(s->hwctx->act_dev, ts->sem[i], s->hwctx->alloc);
+
+    av_free(ts);
+}
+
+int ff_vk_exec_add_dep_wait_sem(FFVulkanContext *s, FFVkExecContext *e,
+                                VkSemaphore sem, uint64_t val,
+                                VkPipelineStageFlagBits2 stage)
+{
+    VkSemaphoreSubmitInfo *sem_wait;
+    ARR_REALLOC(e, sem_wait, &e->sem_wait_alloc, e->sem_wait_cnt);
+
+    e->sem_wait[e->sem_wait_cnt++] = (VkSemaphoreSubmitInfo) {
+        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
+        .semaphore = sem,
+        .value = val,
+        .stageMask = stage,
+    };
+
+    return 0;
+}
+
+int ff_vk_exec_add_dep_bool_sem(FFVulkanContext *s, FFVkExecContext *e,
+                                VkSemaphore *sem, int nb,
+                                VkPipelineStageFlagBits2 stage,
+                                int wait)
+{
+    int err;
+    size_t buf_size;
+    AVBufferRef *buf;
+    TempSyncCtx *ts;
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    /* Do not transfer ownership if we're signalling a binary semaphore,
+     * since we're probably exporting it. */
+    if (!wait) {
+        for (int i = 0; i < nb; i++) {
+            VkSemaphoreSubmitInfo *sem_sig;
+            ARR_REALLOC(e, sem_sig, &e->sem_sig_alloc, e->sem_sig_cnt);
+
+            e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
+                .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
+                .semaphore = sem[i],
+                .stageMask = stage,
+            };
+        }
+
+        return 0;
+    }
+
+    buf_size = sizeof(*ts) + sizeof(VkSemaphore)*nb;
+    ts = av_mallocz(buf_size);
+    if (!ts) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    memcpy(ts->sem, sem, nb*sizeof(*sem));
+    ts->nb_sem = nb;
+
+    buf = av_buffer_create((uint8_t *)ts, buf_size, destroy_tmp_semaphores, s, 0);
+    if (!buf) {
+        av_free(ts);
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    err = ff_vk_exec_add_dep_buf(s, e, &buf, 1, 0);
+    if (err < 0) {
+        av_buffer_unref(&buf);
+        return err;
+    }
+
+    for (int i = 0; i < nb; i++) {
+        err = ff_vk_exec_add_dep_wait_sem(s, e, sem[i], 0, stage);
+        if (err < 0)
+            return err;
+    }
+
+    return 0;
+
+fail:
+    for (int i = 0; i < nb; i++)
+        vk->DestroySemaphore(s->hwctx->act_dev, sem[i], s->hwctx->alloc);
+
+    return err;
+}
+
+int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f,
+                             VkPipelineStageFlagBits2 wait_stage,
+                             VkPipelineStageFlagBits2 signal_stage)
+{
+    uint8_t *frame_locked;
+    uint8_t *frame_update;
+    AVFrame **frame_deps;
+    AVBufferRef **buf_deps;
+    VkImageLayout *layout_dst;
+    uint32_t *queue_family_dst;
+    VkAccessFlagBits *access_dst;
+
+    AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
+    AVVulkanFramesContext *vkfc = hwfc->hwctx;
+    AVVkFrame *vkf = (AVVkFrame *)f->data[0];
+    int nb_images = ff_vk_count_images(vkf);
+
+    /* Don't add duplicates */
+    for (int i = 0; i < e->nb_frame_deps; i++)
+        if (e->frame_deps[i]->data[0] == f->data[0])
+            return 1;
+
+    ARR_REALLOC(e, layout_dst,       &e->layout_dst_alloc,       e->nb_frame_deps);
+    ARR_REALLOC(e, queue_family_dst, &e->queue_family_dst_alloc, e->nb_frame_deps);
+    ARR_REALLOC(e, access_dst,       &e->access_dst_alloc,       e->nb_frame_deps);
+
+    ARR_REALLOC(e, frame_locked, &e->frame_locked_alloc_size, e->nb_frame_deps);
+    ARR_REALLOC(e, frame_update, &e->frame_update_alloc_size, e->nb_frame_deps);
+    ARR_REALLOC(e, frame_deps,   &e->frame_deps_alloc_size,   e->nb_frame_deps);
+
+    /* prepare_frame in hwcontext_vulkan.c uses the regular frame management
+     * code but has no frame yet, and it doesn't need to actually store a ref
+     * to the frame. */
+    if (f->buf[0]) {
+        ARR_REALLOC(e, buf_deps, &e->buf_deps_alloc_size, e->nb_buf_deps);
+        e->buf_deps[e->nb_buf_deps] = av_buffer_ref(f->buf[0]);
+        if (!e->buf_deps[e->nb_buf_deps]) {
+            ff_vk_exec_discard_deps(s, e);
+            return AVERROR(ENOMEM);
+        }
+        e->nb_buf_deps++;
+    }
+
+    e->frame_deps[e->nb_frame_deps] = f;
+
+    vkfc->lock_frame(hwfc, vkf);
+    e->frame_locked[e->nb_frame_deps] = 1;
+    e->frame_update[e->nb_frame_deps] = 0;
+    e->nb_frame_deps++;
+
+    for (int i = 0; i < nb_images; i++) {
+        VkSemaphoreSubmitInfo *sem_wait;
+        VkSemaphoreSubmitInfo *sem_sig;
+        uint64_t **sem_sig_val_dst;
+
+        ARR_REALLOC(e, sem_wait, &e->sem_wait_alloc, e->sem_wait_cnt);
+        ARR_REALLOC(e, sem_sig, &e->sem_sig_alloc, e->sem_sig_cnt);
+        ARR_REALLOC(e, sem_sig_val_dst, &e->sem_sig_val_dst_alloc, e->sem_sig_val_dst_cnt);
+
+        e->sem_wait[e->sem_wait_cnt++] = (VkSemaphoreSubmitInfo) {
+            .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
+            .semaphore = vkf->sem[i],
+            .value = vkf->sem_value[i],
+            .stageMask = wait_stage,
+        };
+
+        e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
+            .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
+            .semaphore = vkf->sem[i],
+            .value = vkf->sem_value[i] + 1,
+            .stageMask = signal_stage,
+        };
+
+        e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = &vkf->sem_value[i];
+        e->sem_sig_val_dst_cnt++;
+    }
+
+    return 0;
+}
+
+void ff_vk_exec_update_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f,
+                             VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar)
+{
+    int i;
+    for (i = 0; i < e->nb_frame_deps; i++)
+        if (e->frame_deps[i]->data[0] == f->data[0])
+            break;
+    av_assert0(i < e->nb_frame_deps);
+
+    /* Don't update duplicates */
+    if (nb_img_bar && !e->frame_update[i])
+        (*nb_img_bar)++;
+
+    e->queue_family_dst[i] = bar->dstQueueFamilyIndex;
+    e->access_dst[i] = bar->dstAccessMask;
+    e->layout_dst[i] = bar->newLayout;
+    e->frame_update[i] = 1;
+}
+
+int ff_vk_exec_mirror_sem_value(FFVulkanContext *s, FFVkExecContext *e,
+                                VkSemaphore *dst, uint64_t *dst_val,
+                                AVFrame *f)
+{
+    uint64_t **sem_sig_val_dst;
+    AVVkFrame *vkf = (AVVkFrame *)f->data[0];
+
+    /* Reject unknown frames */
+    int i;
+    for (i = 0; i < e->nb_frame_deps; i++)
+        if (e->frame_deps[i]->data[0] == f->data[0])
+            break;
+    if (i == e->nb_frame_deps)
+        return AVERROR(EINVAL);
+
+    ARR_REALLOC(e, sem_sig_val_dst, &e->sem_sig_val_dst_alloc, e->sem_sig_val_dst_cnt);
+
+    *dst     = vkf->sem[0];
+    *dst_val = vkf->sem_value[0];
+
+    e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = dst_val;
+    e->sem_sig_val_dst_cnt++;
+
+    return 0;
+}
+
+int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
+{
+    VkResult ret;
+    FFVulkanFunctions *vk = &s->vkfn;
+    VkCommandBufferSubmitInfo cmd_buf_info = (VkCommandBufferSubmitInfo) {
+        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
+        .commandBuffer = e->buf,
+    };
+    VkSubmitInfo2 submit_info = (VkSubmitInfo2) {
+        .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
+        .pCommandBufferInfos = &cmd_buf_info,
+        .commandBufferInfoCount = 1,
+        .pWaitSemaphoreInfos = e->sem_wait,
+        .waitSemaphoreInfoCount = e->sem_wait_cnt,
+        .pSignalSemaphoreInfos = e->sem_sig,
+        .signalSemaphoreInfoCount = e->sem_sig_cnt,
+    };
+
+    ret = vk->EndCommandBuffer(e->buf);
+    if (ret != VK_SUCCESS) {
+        av_log(s, AV_LOG_ERROR, "Unable to finish command buffer: %s\n",
+               ff_vk_ret2str(ret));
+        ff_vk_exec_discard_deps(s, e);
+        return AVERROR_EXTERNAL;
+    }
+
+    s->hwctx->lock_queue(s->device, e->qf, e->qi);
+    ret = vk->QueueSubmit2(e->queue, 1, &submit_info, e->fence);
+    s->hwctx->unlock_queue(s->device, e->qf, e->qi);
+
+    if (ret != VK_SUCCESS) {
+        av_log(s, AV_LOG_ERROR, "Unable to submit command buffer: %s\n",
+               ff_vk_ret2str(ret));
+        ff_vk_exec_discard_deps(s, e);
+        return AVERROR_EXTERNAL;
+    }
+
+    for (int i = 0; i < e->sem_sig_val_dst_cnt; i++)
+        *e->sem_sig_val_dst[i] += 1;
+
+    /* Unlock all frames */
+    for (int j = 0; j < e->nb_frame_deps; j++) {
+        if (e->frame_locked[j]) {
+            AVFrame *f = e->frame_deps[j];
+            AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
+            AVVulkanFramesContext *vkfc = hwfc->hwctx;
+            AVVkFrame *vkf = (AVVkFrame *)f->data[0];
+
+            if (e->frame_update[j]) {
+                int nb_images = ff_vk_count_images(vkf);
+                for (int i = 0; i < nb_images; i++) {
+                    vkf->layout[i] = e->layout_dst[j];
+                    vkf->access[i] = e->access_dst[j];
+                    vkf->queue_family[i] = e->queue_family_dst[j];
+                }
+            }
+            vkfc->unlock_frame(hwfc, vkf);
+            e->frame_locked[j] = 0;
+        }
+    }
+
+    e->had_submission = 1;
+
+    return 0;
+}
+
+int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req,
+                    VkMemoryPropertyFlagBits req_flags, void *alloc_extension,
+                    VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
+{
+    VkResult ret;
+    int index = -1;
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    VkMemoryAllocateInfo alloc_info = {
+        .sType           = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+        .pNext           = alloc_extension,
+    };
+
+    alloc_info.allocationSize = req->size;
+
+    /* The vulkan spec requires memory types to be sorted in the "optimal"
+     * order, so the first matching type we find will be the best/fastest one */
+    for (int i = 0; i < s->mprops.memoryTypeCount; i++) {
+        /* The memory type must be supported by the requirements (bitfield) */
+        if (!(req->memoryTypeBits & (1 << i)))
+            continue;
+
+        /* The memory type flags must include our properties */
+        if ((req_flags != UINT32_MAX) &&
+            ((s->mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags))
+            continue;
+
+        /* Found a suitable memory type */
+        index = i;
+        break;
+    }
+
+    if (index < 0) {
+        av_log(s, AV_LOG_ERROR, "No memory type found for flags 0x%x\n",
+               req_flags);
+        return AVERROR(EINVAL);
+    }
+
+    alloc_info.memoryTypeIndex = index;
+
+    ret = vk->AllocateMemory(s->hwctx->act_dev, &alloc_info,
+                             s->hwctx->alloc, mem);
+    if (ret != VK_SUCCESS)
+        return AVERROR(ENOMEM);
+
+    if (mem_flags)
+        *mem_flags |= s->mprops.memoryTypes[index].propertyFlags;
+
+    return 0;
+}
+
+int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size,
+                     void *pNext, void *alloc_pNext,
+                     VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
+{
+    int err;
+    VkResult ret;
+    int use_ded_mem;
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    /* Buffer usage flags corresponding to buffer descriptor types */
+    const VkBufferUsageFlags desc_usage =
+        VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
+        VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
+        VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
+        VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
+
+    if ((s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) && (usage & desc_usage))
+        usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
+
+    VkBufferCreateInfo buf_spawn = {
+        .sType       = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+        .pNext       = pNext,
+        .usage       = usage,
+        .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
+        .size        = flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT ?
+                       FFALIGN(size, s->props.properties.limits.minMemoryMapAlignment) :
+                       size,
+    };
+
+    VkMemoryAllocateFlagsInfo alloc_flags = {
+        .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
+        .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
+    };
+    VkBufferMemoryRequirementsInfo2 req_desc = {
+        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
+    };
+    VkMemoryDedicatedAllocateInfo ded_alloc = {
+        .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
+        .pNext = alloc_pNext,
+    };
+    VkMemoryDedicatedRequirements ded_req = {
+        .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
+    };
+    VkMemoryRequirements2 req = {
+        .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
+        .pNext = &ded_req,
+    };
+
+    av_log(s, AV_LOG_DEBUG, "Creating a buffer of %"SIZE_SPECIFIER" bytes, "
+                            "usage: 0x%x, flags: 0x%x\n",
+           size, usage, flags);
+
+    ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, s->hwctx->alloc, &buf->buf);
+    if (ret != VK_SUCCESS) {
+        av_log(s, AV_LOG_ERROR, "Failed to create buffer: %s\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+
+    req_desc.buffer = buf->buf;
+
+    vk->GetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req);
+
+    /* In case the implementation prefers/requires dedicated allocation */
+    use_ded_mem = ded_req.prefersDedicatedAllocation |
+                  ded_req.requiresDedicatedAllocation;
+    if (use_ded_mem) {
+        ded_alloc.buffer = buf->buf;
+        ded_alloc.pNext = alloc_pNext;
+        alloc_pNext = &ded_alloc;
+    }
+
+    if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
+        alloc_flags.pNext = alloc_pNext;
+        alloc_pNext = &alloc_flags;
+    }
+
+    err = ff_vk_alloc_mem(s, &req.memoryRequirements, flags, alloc_pNext,
+                          &buf->flags, &buf->mem);
+    if (err)
+        return err;
+
+    ret = vk->BindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0);
+    if (ret != VK_SUCCESS) {
+        av_log(s, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+
+    if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
+        VkBufferDeviceAddressInfo address_info = {
+            .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
+            .buffer = buf->buf,
+        };
+        buf->address = vk->GetBufferDeviceAddress(s->hwctx->act_dev, &address_info);
+    }
+
+    buf->size = size;
+
+    return 0;
+}
+
+int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer **buf, uint8_t *mem[],
+                      int nb_buffers, int invalidate)
+{
+    VkResult ret;
+    FFVulkanFunctions *vk = &s->vkfn;
+    VkMappedMemoryRange inval_list[64];
+    int inval_count = 0;
+
+    for (int i = 0; i < nb_buffers; i++) {
+        void *dst;
+        ret = vk->MapMemory(s->hwctx->act_dev, buf[i]->mem, 0,
+                            VK_WHOLE_SIZE, 0, &dst);
+        if (ret != VK_SUCCESS) {
+            av_log(s, AV_LOG_ERROR, "Failed to map buffer memory: %s\n",
+                   ff_vk_ret2str(ret));
+            return AVERROR_EXTERNAL;
+        }
+        mem[i] = buf[i]->mapped_mem = dst;
+    }
+
+    if (!invalidate)
+        return 0;
+
+    for (int i = 0; i < nb_buffers; i++) {
+        const VkMappedMemoryRange ival_buf = {
+            .sType  = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+            .memory = buf[i]->mem,
+            .size   = VK_WHOLE_SIZE,
+        };
+        if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
+            continue;
+        inval_list[inval_count++] = ival_buf;
+    }
+
+    if (inval_count) {
+        ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count,
+                                               inval_list);
+        if (ret != VK_SUCCESS) {
+            av_log(s, AV_LOG_ERROR, "Failed to invalidate memory: %s\n",
+                   ff_vk_ret2str(ret));
+            return AVERROR_EXTERNAL;
+        }
+    }
+
+    return 0;
+}
+
+int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers,
+                        int flush)
+{
+    int err = 0;
+    VkResult ret;
+    FFVulkanFunctions *vk = &s->vkfn;
+    VkMappedMemoryRange flush_list[64];
+    int flush_count = 0;
+
+    if (flush) {
+        for (int i = 0; i < nb_buffers; i++) {
+            const VkMappedMemoryRange flush_buf = {
+                .sType  = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+                .memory = buf[i]->mem,
+                .size   = VK_WHOLE_SIZE,
+            };
+
+            av_assert0(!buf[i]->host_ref);
+            if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
+                continue;
+            flush_list[flush_count++] = flush_buf;
+        }
+    }
+
+    if (flush_count) {
+        ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, flush_count,
+                                          flush_list);
+        if (ret != VK_SUCCESS) {
+            av_log(s, AV_LOG_ERROR, "Failed to flush memory: %s\n",
+                   ff_vk_ret2str(ret));
+            err = AVERROR_EXTERNAL; /* We still want to try to unmap them */
+        }
+    }
+
+    for (int i = 0; i < nb_buffers; i++) {
+        vk->UnmapMemory(s->hwctx->act_dev, buf[i]->mem);
+        buf[i]->mapped_mem = NULL;
+    }
+
+    return err;
+}
+
+void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf)
+{
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    if (!buf || !s->hwctx)
+        return;
+
+    if (buf->mapped_mem && !buf->host_ref)
+        ff_vk_unmap_buffer(s, buf, 0);
+    if (buf->buf != VK_NULL_HANDLE)
+        vk->DestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc);
+    if (buf->mem != VK_NULL_HANDLE)
+        vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc);
+    if (buf->host_ref)
+        av_buffer_unref(&buf->host_ref);
+
+    buf->buf = VK_NULL_HANDLE;
+    buf->mem = VK_NULL_HANDLE;
+    buf->mapped_mem = NULL;
+}
+
+static void free_data_buf(void *opaque, uint8_t *data)
+{
+    FFVulkanContext *ctx = opaque;
+    FFVkBuffer *buf = (FFVkBuffer *)data;
+    ff_vk_free_buf(ctx, buf);
+    av_free(data);
+}
+
+static AVBufferRef *alloc_data_buf(void *opaque, size_t size)
+{
+    AVBufferRef *ref;
+    uint8_t *buf = av_mallocz(size);
+    if (!buf)
+        return NULL;
+
+    ref = av_buffer_create(buf, size, free_data_buf, opaque, 0);
+    if (!ref)
+        av_free(buf);
+    return ref;
+}
+
+int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVBufferPool **buf_pool,
+                            AVBufferRef **buf, VkBufferUsageFlags usage,
+                            void *create_pNext, size_t size,
+                            VkMemoryPropertyFlagBits mem_props)
+{
+    int err;
+    AVBufferRef *ref;
+    FFVkBuffer *data;
+
+    *buf = NULL;
+
+    if (!(*buf_pool)) {
+        *buf_pool = av_buffer_pool_init2(sizeof(FFVkBuffer), ctx,
+                                         alloc_data_buf, NULL);
+        if (!(*buf_pool))
+            return AVERROR(ENOMEM);
+    }
+
+    *buf = ref = av_buffer_pool_get(*buf_pool);
+    if (!ref)
+        return AVERROR(ENOMEM);
+
+    data = (FFVkBuffer *)ref->data;
+    data->stage = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
+    data->access = VK_ACCESS_2_NONE;
+
+    if (data->size >= size)
+        return 0;
+
+    ff_vk_free_buf(ctx, data);
+    memset(data, 0, sizeof(*data));
+
+    err = ff_vk_create_buf(ctx, data, size,
+                           create_pNext, NULL, usage,
+                           mem_props);
+    if (err < 0) {
+        av_buffer_unref(&ref);
+        *buf = NULL;
+        return err;
+    }
+
+    if (mem_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
+        err = ff_vk_map_buffer(ctx, data, &data->mapped_mem, 0);
+        if (err < 0) {
+            av_buffer_unref(&ref);
+            *buf = NULL;
+            return err;
+        }
+    }
+
+    return 0;
+}
+
+static int create_mapped_buffer(FFVulkanContext *s,
+                                FFVkBuffer *vkb, VkBufferUsageFlags usage,
+                                size_t size,
+                                VkExternalMemoryBufferCreateInfo *create_desc,
+                                VkImportMemoryHostPointerInfoEXT *import_desc,
+                                VkMemoryHostPointerPropertiesEXT props)
+{
+    int err;
+    VkResult ret;
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    VkBufferCreateInfo buf_spawn = {
+        .sType       = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+        .pNext       = create_desc,
+        .usage       = usage,
+        .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
+        .size        = size,
+    };
+    VkMemoryRequirements req = {
+        .size           = size,
+        .alignment      = s->hprops.minImportedHostPointerAlignment,
+        .memoryTypeBits = props.memoryTypeBits,
+    };
+
+    err = ff_vk_alloc_mem(s, &req,
+                          VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
+                          import_desc, &vkb->flags, &vkb->mem);
+    if (err < 0)
+        return err;
+
+    ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, s->hwctx->alloc, &vkb->buf);
+    if (ret != VK_SUCCESS) {
+        vk->FreeMemory(s->hwctx->act_dev, vkb->mem, s->hwctx->alloc);
+        return AVERROR_EXTERNAL;
+    }
+
+    ret = vk->BindBufferMemory(s->hwctx->act_dev, vkb->buf, vkb->mem, 0);
+    if (ret != VK_SUCCESS) {
+        vk->FreeMemory(s->hwctx->act_dev, vkb->mem, s->hwctx->alloc);
+        vk->DestroyBuffer(s->hwctx->act_dev, vkb->buf, s->hwctx->alloc);
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+static void destroy_avvkbuf(void *opaque, uint8_t *data)
+{
+    FFVulkanContext *s = opaque;
+    FFVkBuffer *buf = (FFVkBuffer *)data;
+    ff_vk_free_buf(s, buf);
+    av_free(buf);
+}
+
+int ff_vk_host_map_buffer(FFVulkanContext *s, AVBufferRef **dst,
+                          uint8_t *src_data, const AVBufferRef *src_buf,
+                          VkBufferUsageFlags usage)
+{
+    int err;
+    VkResult ret;
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    VkExternalMemoryBufferCreateInfo create_desc = {
+        .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
+        .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
+    };
+    VkMemoryAllocateFlagsInfo alloc_flags = {
+        .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
+        .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
+    };
+    VkImportMemoryHostPointerInfoEXT import_desc = {
+        .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT,
+        .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
+        .pNext = usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT ? &alloc_flags : NULL,
+    };
+    VkMemoryHostPointerPropertiesEXT props;
+
+    AVBufferRef *ref;
+    FFVkBuffer *vkb;
+    size_t offs;
+    size_t buffer_size;
+
+    *dst = NULL;
+
+    /* Get the previous point at which mapping was possible and use it */
+    offs = (uintptr_t)src_data % s->hprops.minImportedHostPointerAlignment;
+    import_desc.pHostPointer = src_data - offs;
+
+    props = (VkMemoryHostPointerPropertiesEXT) {
+        VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT,
+    };
+    ret = vk->GetMemoryHostPointerPropertiesEXT(s->hwctx->act_dev,
+                                                import_desc.handleType,
+                                                import_desc.pHostPointer,
+                                                &props);
+    if (!(ret == VK_SUCCESS && props.memoryTypeBits))
+        return AVERROR(EINVAL);
+
+    /* Ref the source buffer */
+    ref = av_buffer_ref(src_buf);
+    if (!ref)
+        return AVERROR(ENOMEM);
+
+    /* Add the offset at the start, which gets ignored */
+    const ptrdiff_t src_offset = src_data - src_buf->data;
+    buffer_size = offs + (src_buf->size - src_offset);
+    buffer_size = FFALIGN(buffer_size, s->props.properties.limits.minMemoryMapAlignment);
+    buffer_size = FFALIGN(buffer_size, s->hprops.minImportedHostPointerAlignment);
+
+    /* Create a buffer struct */
+    vkb = av_mallocz(sizeof(*vkb));
+    if (!vkb) {
+        av_buffer_unref(&ref);
+        return AVERROR(ENOMEM);
+    }
+
+    err = create_mapped_buffer(s, vkb, usage,
+                               buffer_size, &create_desc, &import_desc,
+                               props);
+    if (err < 0) {
+        av_buffer_unref(&ref);
+        av_free(vkb);
+        return err;
+    }
+
+    if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
+        VkBufferDeviceAddressInfo address_info = {
+            .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
+            .buffer = vkb->buf,
+        };
+        vkb->address = vk->GetBufferDeviceAddress(s->hwctx->act_dev, &address_info);
+    }
+
+    vkb->host_ref       = ref;
+    vkb->virtual_offset = offs;
+    vkb->address       += offs;
+    vkb->mapped_mem     = src_data;
+    vkb->size           = buffer_size - offs;
+    vkb->flags         |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+
+    /* Create a ref */
+    *dst = av_buffer_create((uint8_t *)vkb, sizeof(*vkb),
+                            destroy_avvkbuf, s, 0);
+    if (!(*dst)) {
+        destroy_avvkbuf(s, (uint8_t *)vkb);
+        *dst = NULL;
+        return AVERROR(ENOMEM);
+    }
+
+    return 0;
+}
+
+int ff_vk_shader_add_push_const(FFVulkanShader *shd, int offset, int size,
+                                VkShaderStageFlagBits stage)
+{
+    VkPushConstantRange *pc;
+
+    shd->push_consts = av_realloc_array(shd->push_consts,
+                                        sizeof(*shd->push_consts),
+                                        shd->push_consts_num + 1);
+    if (!shd->push_consts)
+        return AVERROR(ENOMEM);
+
+    pc = &shd->push_consts[shd->push_consts_num++];
+    memset(pc, 0, sizeof(*pc));
+
+    pc->stageFlags = stage;
+    pc->offset = offset;
+    pc->size = size;
+
+    return 0;
+}
+
+int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler,
+                       int unnorm_coords, VkFilter filt)
+{
+    VkResult ret;
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    VkSamplerCreateInfo sampler_info = {
+        .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
+        .magFilter = filt,
+        .minFilter = sampler_info.magFilter,
+        .mipmapMode = unnorm_coords ? VK_SAMPLER_MIPMAP_MODE_NEAREST :
+                                      VK_SAMPLER_MIPMAP_MODE_LINEAR,
+        .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
+        .addressModeV = sampler_info.addressModeU,
+        .addressModeW = sampler_info.addressModeU,
+        .anisotropyEnable = VK_FALSE,
+        .compareOp = VK_COMPARE_OP_NEVER,
+        .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
+        .unnormalizedCoordinates = unnorm_coords,
+    };
+
+    ret = vk->CreateSampler(s->hwctx->act_dev, &sampler_info,
+                            s->hwctx->alloc, sampler);
+    if (ret != VK_SUCCESS) {
+        av_log(s, AV_LOG_ERROR, "Unable to init sampler: %s\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+VkImageAspectFlags ff_vk_aspect_flag(AVFrame *f, int p)
+{
+    AVVkFrame *vkf = (AVVkFrame *)f->data[0];
+    AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
+    int nb_images = ff_vk_count_images(vkf);
+    int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
+
+    static const VkImageAspectFlags plane_aspect[] = { VK_IMAGE_ASPECT_PLANE_0_BIT,
+                                                       VK_IMAGE_ASPECT_PLANE_1_BIT,
+                                                       VK_IMAGE_ASPECT_PLANE_2_BIT, };
+
+    if (ff_vk_mt_is_np_rgb(hwfc->sw_format) || (nb_planes == nb_images))
+        return VK_IMAGE_ASPECT_COLOR_BIT;
+
+    return plane_aspect[p];
+}
+
+int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt)
+{
+    if (pix_fmt == AV_PIX_FMT_ABGR   || pix_fmt == AV_PIX_FMT_BGRA   ||
+        pix_fmt == AV_PIX_FMT_RGBA   || pix_fmt == AV_PIX_FMT_RGB24  ||
+        pix_fmt == AV_PIX_FMT_BGR24  || pix_fmt == AV_PIX_FMT_RGB48  ||
+        pix_fmt == AV_PIX_FMT_RGBA64 || pix_fmt == AV_PIX_FMT_RGB565 ||
+        pix_fmt == AV_PIX_FMT_BGR565 || pix_fmt == AV_PIX_FMT_BGR0   ||
+        pix_fmt == AV_PIX_FMT_0BGR   || pix_fmt == AV_PIX_FMT_RGB0   ||
+        pix_fmt == AV_PIX_FMT_GBRP10  || pix_fmt == AV_PIX_FMT_GBRP12 ||
+        pix_fmt == AV_PIX_FMT_GBRP14  || pix_fmt == AV_PIX_FMT_GBRP16 ||
+        pix_fmt == AV_PIX_FMT_GBRAP   || pix_fmt == AV_PIX_FMT_GBRAP10 ||
+        pix_fmt == AV_PIX_FMT_GBRAP12 || pix_fmt == AV_PIX_FMT_GBRAP14 ||
+        pix_fmt == AV_PIX_FMT_GBRAP16 || pix_fmt == AV_PIX_FMT_GBRAP32 ||
+        pix_fmt == AV_PIX_FMT_GBRPF32 || pix_fmt == AV_PIX_FMT_GBRAPF32 ||
+        pix_fmt == AV_PIX_FMT_X2RGB10 || pix_fmt == AV_PIX_FMT_X2BGR10 ||
+        pix_fmt == AV_PIX_FMT_RGBAF32 || pix_fmt == AV_PIX_FMT_RGBF32 ||
+        pix_fmt == AV_PIX_FMT_RGBA128 || pix_fmt == AV_PIX_FMT_RGB96 ||
+        pix_fmt == AV_PIX_FMT_GBRP || pix_fmt == AV_PIX_FMT_BAYER_RGGB16)
+        return 1;
+    return 0;
+}
+
+void ff_vk_set_perm(enum AVPixelFormat pix_fmt, int lut[4], int inv)
+{
+    switch (pix_fmt) {
+    case AV_PIX_FMT_GBRP:
+    case AV_PIX_FMT_GBRAP:
+    case AV_PIX_FMT_GBRAP10:
+    case AV_PIX_FMT_GBRAP12:
+    case AV_PIX_FMT_GBRAP14:
+    case AV_PIX_FMT_GBRAP16:
+    case AV_PIX_FMT_GBRP10:
+    case AV_PIX_FMT_GBRP12:
+    case AV_PIX_FMT_GBRP14:
+    case AV_PIX_FMT_GBRP16:
+    case AV_PIX_FMT_GBRPF32:
+    case AV_PIX_FMT_GBRAP32:
+    case AV_PIX_FMT_GBRAPF32:
+        lut[0] = 1;
+        lut[1] = 2;
+        lut[2] = 0;
+        lut[3] = 3;
+        break;
+    default:
+        lut[0] = 0;
+        lut[1] = 1;
+        lut[2] = 2;
+        lut[3] = 3;
+        break;
+    }
+
+    if (inv) {
+        int lut_tmp[4] = { lut[0], lut[1], lut[2], lut[3] };
+        for (int i = 0; i < 4; i++)
+            lut[lut_tmp[i]] = i;
+    }
+
+    return;
+}
+
+const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pix_fmt,
+                                 enum FFVkShaderRepFormat rep_fmt)
+{
+    switch (pix_fmt) {
+    case AV_PIX_FMT_RGBA:
+    case AV_PIX_FMT_BGRA:
+    case AV_PIX_FMT_RGB24:
+    case AV_PIX_FMT_BGR24:
+    case AV_PIX_FMT_BGR0:
+    case AV_PIX_FMT_RGB0:
+    case AV_PIX_FMT_RGB565:
+    case AV_PIX_FMT_BGR565:
+    case AV_PIX_FMT_UYVA:
+    case AV_PIX_FMT_YUYV422:
+    case AV_PIX_FMT_UYVY422: {
+        const char *rep_tab[] = {
+            [FF_VK_REP_NATIVE] = "rgba8ui",
+            [FF_VK_REP_FLOAT] = "rgba8",
+            [FF_VK_REP_INT] = "rgba8i",
+            [FF_VK_REP_UINT] = "rgba8ui",
+        };
+        return rep_tab[rep_fmt];
+    }
+    case AV_PIX_FMT_X2RGB10:
+    case AV_PIX_FMT_X2BGR10:
+    case AV_PIX_FMT_Y210:
+    case AV_PIX_FMT_XV30: {
+        const char *rep_tab[] = {
+            [FF_VK_REP_NATIVE] = "rgb10_a2ui",
+            [FF_VK_REP_FLOAT] = "rgb10_a2",
+            [FF_VK_REP_INT] = NULL,
+            [FF_VK_REP_UINT] = "rgb10_a2ui",
+        };
+        return rep_tab[rep_fmt];
+    }
+    case AV_PIX_FMT_RGB48:
+    case AV_PIX_FMT_RGBA64:
+    case AV_PIX_FMT_Y212:
+    case AV_PIX_FMT_Y216:
+    case AV_PIX_FMT_XV36:
+    case AV_PIX_FMT_XV48: {
+        const char *rep_tab[] = {
+            [FF_VK_REP_NATIVE] = "rgba16ui",
+            [FF_VK_REP_FLOAT] = "rgba16",
+            [FF_VK_REP_INT] = "rgba16i",
+            [FF_VK_REP_UINT] = "rgba16ui",
+        };
+        return rep_tab[rep_fmt];
+    }
+    case AV_PIX_FMT_RGBF32:
+    case AV_PIX_FMT_RGBAF32: {
+        const char *rep_tab[] = {
+            [FF_VK_REP_NATIVE] = "rgba32f",
+            [FF_VK_REP_FLOAT] = "rgba32f",
+            [FF_VK_REP_INT] = "rgba32i",
+            [FF_VK_REP_UINT] = "rgba32ui",
+        };
+        return rep_tab[rep_fmt];
+    }
+    case AV_PIX_FMT_RGB96:
+    case AV_PIX_FMT_RGBA128: {
+        const char *rep_tab[] = {
+            [FF_VK_REP_NATIVE] = "rgba32ui",
+            [FF_VK_REP_FLOAT] = NULL,
+            [FF_VK_REP_INT] = "rgba32i",
+            [FF_VK_REP_UINT] = "rgba32ui",
+        };
+        return rep_tab[rep_fmt];
+    }
+    case AV_PIX_FMT_GBRP:
+    case AV_PIX_FMT_GRAY8:
+    case AV_PIX_FMT_GBRAP:
+    case AV_PIX_FMT_YUV420P:
+    case AV_PIX_FMT_YUV422P:
+    case AV_PIX_FMT_YUV444P:
+    case AV_PIX_FMT_YUVA420P:
+    case AV_PIX_FMT_YUVA422P:
+    case AV_PIX_FMT_YUVA444P: {
+        const char *rep_tab[] = {
+            [FF_VK_REP_NATIVE] = "r8ui",
+            [FF_VK_REP_FLOAT] = "r8",
+            [FF_VK_REP_INT] = "r8i",
+            [FF_VK_REP_UINT] = "r8ui",
+        };
+        return rep_tab[rep_fmt];
+    };
+    case AV_PIX_FMT_GRAY10:
+    case AV_PIX_FMT_GRAY12:
+    case AV_PIX_FMT_GRAY14:
+    case AV_PIX_FMT_GRAY16:
+    case AV_PIX_FMT_GBRAP10:
+    case AV_PIX_FMT_GBRAP12:
+    case AV_PIX_FMT_GBRAP14:
+    case AV_PIX_FMT_GBRAP16:
+    case AV_PIX_FMT_GBRP10:
+    case AV_PIX_FMT_GBRP12:
+    case AV_PIX_FMT_GBRP14:
+    case AV_PIX_FMT_GBRP16:
+    case AV_PIX_FMT_YUV420P10:
+    case AV_PIX_FMT_YUV420P12:
+    case AV_PIX_FMT_YUV420P16:
+    case AV_PIX_FMT_YUV422P10:
+    case AV_PIX_FMT_YUV422P12:
+    case AV_PIX_FMT_YUV422P16:
+    case AV_PIX_FMT_YUV444P10:
+    case AV_PIX_FMT_YUV444P12:
+    case AV_PIX_FMT_YUV444P16:
+    case AV_PIX_FMT_YUVA420P10:
+    case AV_PIX_FMT_YUVA420P16:
+    case AV_PIX_FMT_YUVA422P10:
+    case AV_PIX_FMT_YUVA422P12:
+    case AV_PIX_FMT_YUVA422P16:
+    case AV_PIX_FMT_YUVA444P10:
+    case AV_PIX_FMT_YUVA444P12:
+    case AV_PIX_FMT_YUVA444P16:
+    case AV_PIX_FMT_BAYER_RGGB16: {
+        const char *rep_tab[] = {
+            [FF_VK_REP_NATIVE] = "r16ui",
+            [FF_VK_REP_FLOAT] = "r16f",
+            [FF_VK_REP_INT] = "r16i",
+            [FF_VK_REP_UINT] = "r16ui",
+        };
+        return rep_tab[rep_fmt];
+    };
+    case AV_PIX_FMT_GRAY32:
+    case AV_PIX_FMT_GRAYF32:
+    case AV_PIX_FMT_GBRPF32:
+    case AV_PIX_FMT_GBRAPF32: {
+        const char *rep_tab[] = {
+            [FF_VK_REP_NATIVE] = "r32f",
+            [FF_VK_REP_FLOAT] = "r32f",
+            [FF_VK_REP_INT] = "r32i",
+            [FF_VK_REP_UINT] = "r32ui",
+        };
+        return rep_tab[rep_fmt];
+    };
+    case AV_PIX_FMT_GBRAP32: {
+        const char *rep_tab[] = {
+            [FF_VK_REP_NATIVE] = "r32ui",
+            [FF_VK_REP_FLOAT] = NULL,
+            [FF_VK_REP_INT] = "r32i",
+            [FF_VK_REP_UINT] = "r32ui",
+        };
+        return rep_tab[rep_fmt];
+    };
+    case AV_PIX_FMT_NV12:
+    case AV_PIX_FMT_NV16:
+    case AV_PIX_FMT_NV24: {
+        const char *rep_tab[] = {
+            [FF_VK_REP_NATIVE] = "rg8ui",
+            [FF_VK_REP_FLOAT] = "rg8",
+            [FF_VK_REP_INT] = "rg8i",
+            [FF_VK_REP_UINT] = "rg8ui",
+        };
+        return rep_tab[rep_fmt];
+    };
+    case AV_PIX_FMT_P010:
+    case AV_PIX_FMT_P210:
+    case AV_PIX_FMT_P410: {
+        const char *rep_tab[] = {
+            [FF_VK_REP_NATIVE] = "rgb10_a2ui",
+            [FF_VK_REP_FLOAT] = "rgb10_a2",
+            [FF_VK_REP_INT] = NULL,
+            [FF_VK_REP_UINT] = "rgb10_a2ui",
+        };
+        return rep_tab[rep_fmt];
+    };
+    case AV_PIX_FMT_P012:
+    case AV_PIX_FMT_P016:
+    case AV_PIX_FMT_P212:
+    case AV_PIX_FMT_P216:
+    case AV_PIX_FMT_P412:
+    case AV_PIX_FMT_P416: {
+        const char *rep_tab[] = {
+            [FF_VK_REP_NATIVE] = "rg16ui",
+            [FF_VK_REP_FLOAT] = "rg16",
+            [FF_VK_REP_INT] = "rg16i",
+            [FF_VK_REP_UINT] = "rg16ui",
+        };
+        return rep_tab[rep_fmt];
+    };
+    default:
+        return "rgba32f";
+    }
+}
+
+typedef struct ImageViewCtx {
+    int nb_views;
+    VkImageView views[];
+} ImageViewCtx;
+
+static void destroy_imageviews(void *opaque, uint8_t *data)
+{
+    FFVulkanContext *s = opaque;
+    FFVulkanFunctions *vk = &s->vkfn;
+    ImageViewCtx *iv = (ImageViewCtx *)data;
+
+    for (int i = 0; i < iv->nb_views; i++)
+        vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], s->hwctx->alloc);
+
+    av_free(iv);
+}
+
+static VkFormat map_fmt_to_rep(VkFormat fmt, enum FFVkShaderRepFormat rep_fmt)
+{
+#define REPS_FMT(fmt) \
+    [FF_VK_REP_NATIVE] = fmt ## _UINT, \
+    [FF_VK_REP_FLOAT]  = fmt ## _UNORM, \
+    [FF_VK_REP_INT]    = fmt ## _SINT, \
+    [FF_VK_REP_UINT]   = fmt ## _UINT,
+
+#define REPS_FMT_PACK(fmt, num) \
+    [FF_VK_REP_NATIVE] = fmt ## _UINT_PACK ## num, \
+    [FF_VK_REP_FLOAT]  = fmt ## _UNORM_PACK ## num, \
+    [FF_VK_REP_INT]    = fmt ## _SINT_PACK ## num, \
+    [FF_VK_REP_UINT]   = fmt ## _UINT_PACK ## num,
+
+    const VkFormat fmts_map[][4] = {
+        { REPS_FMT_PACK(VK_FORMAT_A2B10G10R10, 32) },
+        { REPS_FMT_PACK(VK_FORMAT_A2R10G10B10, 32) },
+        {
+            VK_FORMAT_B5G6R5_UNORM_PACK16,
+            VK_FORMAT_B5G6R5_UNORM_PACK16,
+            VK_FORMAT_UNDEFINED,
+            VK_FORMAT_UNDEFINED,
+        },
+        {
+            VK_FORMAT_R5G6B5_UNORM_PACK16,
+            VK_FORMAT_R5G6B5_UNORM_PACK16,
+            VK_FORMAT_UNDEFINED,
+            VK_FORMAT_UNDEFINED,
+        },
+        { REPS_FMT(VK_FORMAT_B8G8R8) },
+        { REPS_FMT(VK_FORMAT_B8G8R8A8) },
+        { REPS_FMT(VK_FORMAT_R8) },
+        { REPS_FMT(VK_FORMAT_R8G8) },
+        { REPS_FMT(VK_FORMAT_R8G8B8) },
+        { REPS_FMT(VK_FORMAT_R8G8B8A8) },
+        { REPS_FMT(VK_FORMAT_R16) },
+        { REPS_FMT(VK_FORMAT_R16G16) },
+        { REPS_FMT(VK_FORMAT_R16G16B16) },
+        { REPS_FMT(VK_FORMAT_R16G16B16A16) },
+        {
+            VK_FORMAT_R32_UINT,
+            VK_FORMAT_R32_SFLOAT,
+            VK_FORMAT_R32_SINT,
+            VK_FORMAT_R32_UINT,
+        },
+        {
+            VK_FORMAT_R32G32B32_SFLOAT,
+            VK_FORMAT_R32G32B32_SFLOAT,
+            VK_FORMAT_UNDEFINED,
+            VK_FORMAT_UNDEFINED,
+        },
+        {
+            VK_FORMAT_R32G32B32A32_SFLOAT,
+            VK_FORMAT_R32G32B32A32_SFLOAT,
+            VK_FORMAT_UNDEFINED,
+            VK_FORMAT_UNDEFINED,
+        },
+        {
+            VK_FORMAT_R32G32B32_UINT,
+            VK_FORMAT_UNDEFINED,
+            VK_FORMAT_R32G32B32_SINT,
+            VK_FORMAT_R32G32B32_UINT,
+        },
+        {
+            VK_FORMAT_R32G32B32A32_UINT,
+            VK_FORMAT_UNDEFINED,
+            VK_FORMAT_R32G32B32A32_SINT,
+            VK_FORMAT_R32G32B32A32_UINT,
+        },
+    };
+#undef REPS_FMT_PACK
+#undef REPS_FMT
+
+    if (fmt == VK_FORMAT_UNDEFINED)
+        return VK_FORMAT_UNDEFINED;
+
+    for (int i = 0; i < FF_ARRAY_ELEMS(fmts_map); i++) {
+        if (fmts_map[i][FF_VK_REP_NATIVE] == fmt ||
+            fmts_map[i][FF_VK_REP_FLOAT] == fmt ||
+            fmts_map[i][FF_VK_REP_INT] == fmt ||
+            fmts_map[i][FF_VK_REP_UINT] == fmt)
+            return fmts_map[i][rep_fmt];
+    }
+
+    return VK_FORMAT_UNDEFINED;
+}
+
+int ff_vk_create_imageview(FFVulkanContext *s,
+                           VkImageView *img_view, VkImageAspectFlags *aspect,
+                           AVFrame *f, int plane, enum FFVkShaderRepFormat rep_fmt)
+{
+    VkResult ret;
+    FFVulkanFunctions *vk = &s->vkfn;
+    AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
+    AVVulkanFramesContext *vkfc = hwfc->hwctx;
+    const VkFormat *rep_fmts = av_vkfmt_from_pixfmt(hwfc->sw_format);
+    AVVkFrame *vkf = (AVVkFrame *)f->data[0];
+    const int nb_images = ff_vk_count_images(vkf);
+
+    VkImageViewUsageCreateInfo view_usage_info = {
+        .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
+        .usage = vkfc->usage &
+                 (~(VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR |
+                    VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)),
+    };
+    VkImageViewCreateInfo view_create_info = {
+        .sType      = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+        .pNext      = &view_usage_info,
+        .image      = vkf->img[FFMIN(plane, nb_images - 1)],
+        .viewType   = VK_IMAGE_VIEW_TYPE_2D,
+        .format     = map_fmt_to_rep(rep_fmts[plane], rep_fmt),
+        .components = ff_comp_identity_map,
+        .subresourceRange = {
+            .aspectMask = ff_vk_aspect_flag(f, plane),
+            .levelCount = 1,
+            .layerCount = 1,
+        },
+    };
+    if (view_create_info.format == VK_FORMAT_UNDEFINED) {
+        av_log(s, AV_LOG_ERROR, "Unable to find a compatible representation "
+                                "of format %i and mode %i\n",
+               rep_fmts[plane], rep_fmt);
+        return AVERROR(EINVAL);
+    }
+
+    ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info,
+                              s->hwctx->alloc, img_view);
+    if (ret != VK_SUCCESS) {
+        av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+
+    *aspect = view_create_info.subresourceRange.aspectMask;
+
+    return 0;
+}
+
+int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e,
+                            VkImageView views[AV_NUM_DATA_POINTERS],
+                            AVFrame *f, enum FFVkShaderRepFormat rep_fmt)
+{
+    int err;
+    VkResult ret;
+    AVBufferRef *buf;
+    FFVulkanFunctions *vk = &s->vkfn;
+    AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
+    AVVulkanFramesContext *vkfc = hwfc->hwctx;
+    const VkFormat *rep_fmts = av_vkfmt_from_pixfmt(hwfc->sw_format);
+    AVVkFrame *vkf = (AVVkFrame *)f->data[0];
+    const int nb_images = ff_vk_count_images(vkf);
+    const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
+
+    ImageViewCtx *iv;
+    const size_t buf_size = sizeof(*iv) + nb_planes*sizeof(VkImageView);
+    iv = av_mallocz(buf_size);
+    if (!iv)
+        return AVERROR(ENOMEM);
+
+    for (int i = 0; i < nb_planes; i++) {
+        VkImageViewUsageCreateInfo view_usage_info = {
+            .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
+            .usage = vkfc->usage &
+                     (~(VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR |
+                        VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)),
+        };
+        VkImageViewCreateInfo view_create_info = {
+            .sType      = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+            .pNext      = &view_usage_info,
+            .image      = vkf->img[FFMIN(i, nb_images - 1)],
+            .viewType   = VK_IMAGE_VIEW_TYPE_2D,
+            .format     = map_fmt_to_rep(rep_fmts[i], rep_fmt),
+            .components = ff_comp_identity_map,
+            .subresourceRange = {
+                .aspectMask = ff_vk_aspect_flag(f, i),
+                .levelCount = 1,
+                .layerCount = 1,
+            },
+        };
+        if (view_create_info.format == VK_FORMAT_UNDEFINED) {
+            av_log(s, AV_LOG_ERROR, "Unable to find a compatible representation "
+                                    "of format %i and mode %i\n",
+                   rep_fmts[i], rep_fmt);
+            err = AVERROR(EINVAL);
+            goto fail;
+        }
+
+        ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info,
+                                  s->hwctx->alloc, &iv->views[i]);
+        if (ret != VK_SUCCESS) {
+            av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n",
+                   ff_vk_ret2str(ret));
+            err = AVERROR_EXTERNAL;
+            goto fail;
+        }
+
+        iv->nb_views++;
+    }
+
+    buf = av_buffer_create((uint8_t *)iv, buf_size, destroy_imageviews, s, 0);
+    if (!buf) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    /* Add to queue dependencies */
+    err = ff_vk_exec_add_dep_buf(s, e, &buf, 1, 0);
+    if (err < 0)
+        av_buffer_unref(&buf);
+
+    memcpy(views, iv->views, nb_planes*sizeof(*views));
+
+    return err;
+
+fail:
+    for (int i = 0; i < iv->nb_views; i++)
+        vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], s->hwctx->alloc);
+    av_free(iv);
+    return err;
+}
+
+void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e,
+                         AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar,
+                         VkPipelineStageFlags src_stage,
+                         VkPipelineStageFlags dst_stage,
+                         VkAccessFlagBits     new_access,
+                         VkImageLayout        new_layout,
+                         uint32_t             new_qf)
+{
+    int found = -1;
+    AVVkFrame *vkf = (AVVkFrame *)pic->data[0];
+    const int nb_images = ff_vk_count_images(vkf);
+    for (int i = 0; i < e->nb_frame_deps; i++)
+        if (e->frame_deps[i]->data[0] == pic->data[0]) {
+            if (e->frame_update[i])
+                found = i;
+            break;
+        }
+
+    for (int i = 0; i < nb_images; i++) {
+        bar[*nb_bar] = (VkImageMemoryBarrier2) {
+            .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
+            .pNext = NULL,
+            .srcStageMask = src_stage,
+            .dstStageMask = dst_stage,
+            .srcAccessMask = found >= 0 ? e->access_dst[found] : vkf->access[i],
+            .dstAccessMask = new_access,
+            .oldLayout = found >= 0 ? e->layout_dst[found] : vkf->layout[0],
+            .newLayout = new_layout,
+            .srcQueueFamilyIndex = found >= 0 ? e->queue_family_dst[found] : vkf->queue_family[0],
+            .dstQueueFamilyIndex = new_qf,
+            .image = vkf->img[i],
+            .subresourceRange = (VkImageSubresourceRange) {
+                .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+                .layerCount = 1,
+                .levelCount = 1,
+            },
+        };
+        *nb_bar += 1;
+    }
+
+    ff_vk_exec_update_frame(s, e, pic, &bar[*nb_bar - nb_images], NULL);
+}
+
+int ff_vk_shader_init(FFVulkanContext *s, FFVulkanShader *shd, const char *name,
+                      VkPipelineStageFlags stage,
+                      const char *extensions[], int nb_extensions,
+                      int lg_x, int lg_y, int lg_z,
+                      uint32_t required_subgroup_size)
+{
+    av_bprint_init(&shd->src, 0, AV_BPRINT_SIZE_UNLIMITED);
+
+    shd->name = name;
+    shd->stage = stage;
+    shd->lg_size[0] = lg_x;
+    shd->lg_size[1] = lg_y;
+    shd->lg_size[2] = lg_z;
+
+    switch (shd->stage) {
+    case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
+    case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
+    case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
+    case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
+    case VK_SHADER_STAGE_MISS_BIT_KHR:
+    case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
+        shd->bind_point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
+        break;
+    case VK_SHADER_STAGE_COMPUTE_BIT:
+        shd->bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
+        break;
+    default:
+        shd->bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
+        break;
+    };
+
+    if (required_subgroup_size) {
+        shd->subgroup_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO;
+        shd->subgroup_info.requiredSubgroupSize = required_subgroup_size;
+    }
+
+    av_bprintf(&shd->src, "/* %s shader: %s */\n",
+               (stage == VK_SHADER_STAGE_TASK_BIT_EXT ||
+                stage == VK_SHADER_STAGE_MESH_BIT_EXT) ?
+               "Mesh" :
+               (shd->bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR) ?
+               "Raytrace" :
+               (shd->bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) ?
+               "Compute" : "Graphics",
+               name);
+    GLSLF(0, #version %i                                                  ,460);
+    GLSLC(0,                                                                  );
+
+    /* Common utilities */
+    GLSLC(0, #define IS_WITHIN(v1, v2) ((v1.x < v2.x) && (v1.y < v2.y))       );
+    GLSLC(0,                                                                  );
+    GLSLC(0, #extension GL_EXT_scalar_block_layout : require                  );
+    GLSLC(0, #extension GL_EXT_shader_explicit_arithmetic_types : require     );
+    GLSLC(0, #extension GL_EXT_control_flow_attributes : require              );
+    GLSLC(0, #extension GL_EXT_shader_image_load_formatted : require          );
+    if (s->extensions & FF_VK_EXT_EXPECT_ASSUME) {
+        GLSLC(0, #extension GL_EXT_expect_assume : require                    );
+    } else {
+        GLSLC(0, #define assumeEXT(x) (x)                                     );
+        GLSLC(0, #define expectEXT(x, c) (x)                                  );
+    }
+    if ((s->extensions & FF_VK_EXT_DEBUG_UTILS) &&
+        (s->extensions & FF_VK_EXT_RELAXED_EXTENDED_INSTR)) {
+        GLSLC(0, #extension GL_EXT_debug_printf : require                     );
+        GLSLC(0, #define DEBUG                                                );
+    }
+
+    if (stage == VK_SHADER_STAGE_TASK_BIT_EXT ||
+        stage == VK_SHADER_STAGE_MESH_BIT_EXT)
+        GLSLC(0, #extension GL_EXT_mesh_shader : require                      );
+
+    for (int i = 0; i < nb_extensions; i++)
+        GLSLF(0, #extension %s : %s                  ,extensions[i], "require");
+    GLSLC(0,                                                                  );
+
+    GLSLF(0, layout (local_size_x = %i, local_size_y = %i, local_size_z = %i) in;
+          , shd->lg_size[0], shd->lg_size[1], shd->lg_size[2]);
+    GLSLC(0,                                                                  );
+
+    return 0;
+}
+
+void ff_vk_shader_print(void *ctx, FFVulkanShader *shd, int prio)
+{
+    int line = 0;
+    const char *p = shd->src.str;
+    const char *start = p;
+    const size_t len = strlen(p);
+
+    AVBPrint buf;
+    av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
+
+    for (int i = 0; i < len; i++) {
+        if (p[i] == '\n') {
+            av_bprintf(&buf, "%i\t", ++line);
+            av_bprint_append_data(&buf, start, &p[i] - start + 1);
+            start = &p[i + 1];
+        }
+    }
+
+    av_log(ctx, prio, "Shader %s: \n%s", shd->name, buf.str);
+    av_bprint_finalize(&buf, NULL);
+}
+
+static int init_pipeline_layout(FFVulkanContext *s, FFVulkanShader *shd)
+{
+    VkResult ret;
+    FFVulkanFunctions *vk = &s->vkfn;
+    VkPipelineLayoutCreateInfo pipeline_layout_info;
+
+    /* Finally create the pipeline layout */
+    pipeline_layout_info = (VkPipelineLayoutCreateInfo) {
+        .sType                  = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+        .pSetLayouts            = shd->desc_layout,
+        .setLayoutCount         = shd->nb_descriptor_sets,
+        .pushConstantRangeCount = shd->push_consts_num,
+        .pPushConstantRanges    = shd->push_consts,
+    };
+
+    ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &pipeline_layout_info,
+                                   s->hwctx->alloc, &shd->pipeline_layout);
+    if (ret != VK_SUCCESS) {
+        av_log(s, AV_LOG_ERROR, "Unable to init pipeline layout: %s\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+static int create_shader_module(FFVulkanContext *s, FFVulkanShader *shd,
+                                VkShaderModule *mod,
+                                uint8_t *spirv, size_t spirv_len)
+{
+    VkResult ret;
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    VkShaderModuleCreateInfo shader_module_info = {
+        .sType    = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
+        .pNext    = NULL,
+        .flags    = 0x0,
+        .pCode    = (void *)spirv,
+        .codeSize = spirv_len,
+    };
+
+    ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_module_info,
+                                 s->hwctx->alloc, mod);
+    if (ret != VK_SUCCESS) {
+        av_log(s, AV_LOG_ERROR, "Error creating shader module: %s\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+static int init_compute_pipeline(FFVulkanContext *s, FFVulkanShader *shd,
+                                 VkShaderModule mod, const char *entrypoint)
+{
+    VkResult ret;
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    VkComputePipelineCreateInfo pipeline_create_info = {
+        .sType  = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
+        .flags = (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) ?
+                 VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT : 0x0,
+        .layout = shd->pipeline_layout,
+        .stage = (VkPipelineShaderStageCreateInfo) {
+            .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+            .pNext = shd->subgroup_info.requiredSubgroupSize ?
+                     &shd->subgroup_info : NULL,
+            .pName = entrypoint,
+            .flags = shd->subgroup_info.requiredSubgroupSize ?
+                     VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT : 0x0,
+            .stage = shd->stage,
+            .module = mod,
+        },
+    };
+
+    ret = vk->CreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1,
+                                     &pipeline_create_info,
+                                     s->hwctx->alloc, &shd->pipeline);
+    if (ret != VK_SUCCESS) {
+        av_log(s, AV_LOG_ERROR, "Unable to init compute pipeline: %s\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+static int create_shader_object(FFVulkanContext *s, FFVulkanShader *shd,
+                                uint8_t *spirv, size_t spirv_len,
+                                const char *entrypoint)
+{
+    VkResult ret;
+    FFVulkanFunctions *vk = &s->vkfn;
+    size_t shader_size = 0;
+
+    VkShaderCreateInfoEXT shader_obj_create = {
+        .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,
+        .flags = shd->subgroup_info.requiredSubgroupSize ?
+                 VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT : 0x0,
+        .stage = shd->stage,
+        .nextStage = 0,
+        .codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT,
+        .pCode = spirv,
+        .codeSize = spirv_len,
+        .pName = entrypoint,
+        .pSetLayouts = shd->desc_layout,
+        .setLayoutCount = shd->nb_descriptor_sets,
+        .pushConstantRangeCount = shd->push_consts_num,
+        .pPushConstantRanges = shd->push_consts,
+        .pSpecializationInfo = NULL,
+    };
+
+    ret = vk->CreateShadersEXT(s->hwctx->act_dev, 1, &shader_obj_create,
+                               s->hwctx->alloc, &shd->object);
+    if (ret != VK_SUCCESS) {
+        av_log(s, AV_LOG_ERROR, "Unable to create shader object: %s\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+
+    if (vk->GetShaderBinaryDataEXT(s->hwctx->act_dev, shd->object,
+                                   &shader_size, NULL) == VK_SUCCESS)
+        av_log(s, AV_LOG_VERBOSE, "Shader %s size: %"SIZE_SPECIFIER" binary (%"SIZE_SPECIFIER" SPIR-V)\n",
+               shd->name, shader_size, spirv_len);
+
+    return 0;
+}
+
+static int init_descriptors(FFVulkanContext *s, FFVulkanShader *shd)
+{
+    VkResult ret;
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    shd->desc_layout = av_malloc_array(shd->nb_descriptor_sets,
+                                       sizeof(*shd->desc_layout));
+    if (!shd->desc_layout)
+        return AVERROR(ENOMEM);
+
+    if (!(s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER)) {
+        int has_singular = 0;
+        int max_descriptors = 0;
+        for (int i = 0; i < shd->nb_descriptor_sets; i++) {
+            max_descriptors = FFMAX(max_descriptors, shd->desc_set[i].nb_bindings);
+            if (shd->desc_set[i].singular)
+                has_singular = 1;
+        }
+        shd->use_push = (s->extensions & FF_VK_EXT_PUSH_DESCRIPTOR) &&
+                        (max_descriptors <= s->push_desc_props.maxPushDescriptors) &&
+                        (shd->nb_descriptor_sets == 1) &&
+                        (has_singular == 0);
+    }
+
+    for (int i = 0; i < shd->nb_descriptor_sets; i++) {
+        FFVulkanDescriptorSet *set = &shd->desc_set[i];
+        VkDescriptorSetLayoutCreateInfo desc_layout_create = {
+            .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+            .bindingCount = set->nb_bindings,
+            .pBindings = set->binding,
+            .flags = (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) ?
+                     VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT :
+                     (shd->use_push) ?
+                     VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR :
+                     0x0,
+        };
+
+        ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev,
+                                            &desc_layout_create,
+                                            s->hwctx->alloc,
+                                            &shd->desc_layout[i]);
+        if (ret != VK_SUCCESS) {
+            av_log(s, AV_LOG_ERROR, "Unable to create descriptor set layout: %s",
+                   ff_vk_ret2str(ret));
+            return AVERROR_EXTERNAL;
+        }
+
+        if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
+            vk->GetDescriptorSetLayoutSizeEXT(s->hwctx->act_dev, shd->desc_layout[i],
+                                              &set->layout_size);
+
+            set->aligned_size = FFALIGN(set->layout_size,
+                                        s->desc_buf_props.descriptorBufferOffsetAlignment);
+
+            for (int j = 0; j < set->nb_bindings; j++)
+                vk->GetDescriptorSetLayoutBindingOffsetEXT(s->hwctx->act_dev,
+                                                           shd->desc_layout[i],
+                                                           j,
+                                                           &set->binding_offset[j]);
+        }
+    }
+
+    return 0;
+}
+
+int ff_vk_shader_link(FFVulkanContext *s, FFVulkanShader *shd,
+                      uint8_t *spirv, size_t spirv_len,
+                      const char *entrypoint)
+{
+    int err;
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    err = init_descriptors(s, shd);
+    if (err < 0)
+        return err;
+
+    err = init_pipeline_layout(s, shd);
+    if (err < 0)
+        return err;
+
+    if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
+        shd->bound_buffer_indices = av_calloc(shd->nb_descriptor_sets,
+                                              sizeof(*shd->bound_buffer_indices));
+        if (!shd->bound_buffer_indices)
+            return AVERROR(ENOMEM);
+
+        for (int i = 0; i < shd->nb_descriptor_sets; i++)
+            shd->bound_buffer_indices[i] = i;
+    }
+
+    if (s->extensions & FF_VK_EXT_SHADER_OBJECT) {
+        err = create_shader_object(s, shd, spirv, spirv_len, entrypoint);
+        if (err < 0)
+            return err;
+    } else {
+        VkShaderModule mod;
+        err = create_shader_module(s, shd, &mod, spirv, spirv_len);
+        if (err < 0)
+            return err;
+
+        switch (shd->bind_point) {
+        case VK_PIPELINE_BIND_POINT_COMPUTE:
+            err = init_compute_pipeline(s, shd, mod, entrypoint);
+            break;
+        default:
+            av_log(s, AV_LOG_ERROR, "Unsupported shader type: %i\n",
+                   shd->bind_point);
+            err = AVERROR(EINVAL);
+            break;
+        };
+
+        vk->DestroyShaderModule(s->hwctx->act_dev, mod, s->hwctx->alloc);
+        if (err < 0)
+            return err;
+    }
+
+    return 0;
+}
+
+static const struct descriptor_props {
+    size_t struct_size; /* Size of the opaque which updates the descriptor */
+    const char *type;
+    int is_uniform;
+    int mem_quali;      /* Can use a memory qualifier */
+    int dim_needed;     /* Must indicate dimension */
+    int buf_content;    /* Must indicate buffer contents */
+} descriptor_props[] = {
+    [VK_DESCRIPTOR_TYPE_SAMPLER]                = { sizeof(VkDescriptorImageInfo),  "sampler",       1, 0, 0, 0, },
+    [VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE]          = { sizeof(VkDescriptorImageInfo),  "texture",       1, 0, 1, 0, },
+    [VK_DESCRIPTOR_TYPE_STORAGE_IMAGE]          = { sizeof(VkDescriptorImageInfo),  "image",         1, 1, 1, 0, },
+    [VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT]       = { sizeof(VkDescriptorImageInfo),  "subpassInput",  1, 0, 0, 0, },
+    [VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] = { sizeof(VkDescriptorImageInfo),  "sampler",       1, 0, 1, 0, },
+    [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER]         = { sizeof(VkDescriptorBufferInfo),  NULL,           1, 0, 0, 1, },
+    [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER]         = { sizeof(VkDescriptorBufferInfo), "buffer",        0, 1, 0, 1, },
+    [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo),  NULL,           1, 0, 0, 1, },
+    [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), "buffer",        0, 1, 0, 1, },
+    [VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER]   = { sizeof(VkBufferView),           "samplerBuffer", 1, 0, 0, 0, },
+    [VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER]   = { sizeof(VkBufferView),           "imageBuffer",   1, 0, 0, 0, },
+};
+
+int ff_vk_shader_add_descriptor_set(FFVulkanContext *s, FFVulkanShader *shd,
+                                    FFVulkanDescriptorSetBinding *desc, int nb,
+                                    int singular, int print_to_shader_only)
+{
+    int has_sampler = 0;
+    FFVulkanDescriptorSet *set;
+
+    if (print_to_shader_only)
+        goto print;
+
+    /* Actual layout allocated for the pipeline */
+    set = av_realloc_array(shd->desc_set,
+                           sizeof(*shd->desc_set),
+                           shd->nb_descriptor_sets + 1);
+    if (!set)
+        return AVERROR(ENOMEM);
+    shd->desc_set = set;
+
+    set = &set[shd->nb_descriptor_sets];
+    memset(set, 0, sizeof(*set));
+
+    set->binding = av_calloc(nb, sizeof(*set->binding));
+    if (!set->binding)
+        return AVERROR(ENOMEM);
+
+    set->binding_offset = av_calloc(nb, sizeof(*set->binding_offset));
+    if (!set->binding_offset) {
+        av_freep(&set->binding);
+        return AVERROR(ENOMEM);
+    }
+
+    for (int i = 0; i < nb; i++) {
+        set->binding[i].binding            = i;
+        set->binding[i].descriptorType     = desc[i].type;
+        set->binding[i].descriptorCount    = FFMAX(desc[i].elems, 1);
+        set->binding[i].stageFlags         = desc[i].stages;
+        set->binding[i].pImmutableSamplers = desc[i].samplers;
+
+        if (desc[i].type == VK_DESCRIPTOR_TYPE_SAMPLER ||
+            desc[i].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
+            has_sampler |= 1;
+    }
+
+    set->usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT |
+                 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
+    if (has_sampler)
+        set->usage |= VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT;
+
+    if (!(s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER)) {
+        for (int i = 0; i < nb; i++) {
+            int j;
+            VkDescriptorPoolSize *desc_pool_size;
+            for (j = 0; j < shd->nb_desc_pool_size; j++)
+                if (shd->desc_pool_size[j].type == desc[i].type)
+                    break;
+            if (j >= shd->nb_desc_pool_size) {
+                desc_pool_size = av_realloc_array(shd->desc_pool_size,
+                                                  sizeof(*desc_pool_size),
+                                                  shd->nb_desc_pool_size + 1);
+                if (!desc_pool_size)
+                    return AVERROR(ENOMEM);
+
+                shd->desc_pool_size = desc_pool_size;
+                shd->nb_desc_pool_size++;
+                memset(&desc_pool_size[j], 0, sizeof(VkDescriptorPoolSize));
+            }
+            shd->desc_pool_size[j].type             = desc[i].type;
+            shd->desc_pool_size[j].descriptorCount += FFMAX(desc[i].elems, 1);
+        }
+    }
+
+    set->singular = singular;
+    set->nb_bindings = nb;
+    shd->nb_descriptor_sets++;
+
+print:
+    /* Write shader info */
+    for (int i = 0; i < nb; i++) {
+        const struct descriptor_props *prop = &descriptor_props[desc[i].type];
+        GLSLA("layout (set = %i, binding = %i", FFMAX(shd->nb_descriptor_sets - 1, 0), i);
+
+        if (desc[i].mem_layout &&
+            (desc[i].type != VK_DESCRIPTOR_TYPE_STORAGE_IMAGE))
+            GLSLA(", %s", desc[i].mem_layout);
+
+        GLSLA(")");
+
+        if (prop->is_uniform)
+            GLSLA(" uniform");
+
+        if (prop->mem_quali && desc[i].mem_quali)
+            GLSLA(" %s", desc[i].mem_quali);
+
+        if (prop->type) {
+            GLSLA(" ");
+            if (desc[i].type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
+                if (desc[i].mem_layout) {
+                    int len = strlen(desc[i].mem_layout);
+                    if (desc[i].mem_layout[len - 1] == 'i' &&
+                        desc[i].mem_layout[len - 2] == 'u') {
+                        GLSLA("u");
+                    } else if (desc[i].mem_layout[len - 1] == 'i') {
+                        GLSLA("i");
+                    }
+                }
+            }
+            GLSLA("%s", prop->type);
+        }
+
+        if (prop->dim_needed)
+            GLSLA("%iD", desc[i].dimensions);
+
+        GLSLA(" %s", desc[i].name);
+
+        if (prop->buf_content) {
+            GLSLA(" {\n    ");
+            if (desc[i].buf_elems) {
+                GLSLA("%s", desc[i].buf_content);
+                GLSLA("[%i];", desc[i].buf_elems);
+            } else {
+                GLSLA("%s", desc[i].buf_content);
+            }
+            GLSLA("\n}");
+        } else if (desc[i].elems > 0) {
+            GLSLA("[%i]", desc[i].elems);
+        }
+
+        GLSLA(";");
+        GLSLA("\n");
+    }
+    GLSLA("\n");
+
+    return 0;
+}
+
+int ff_vk_shader_register_exec(FFVulkanContext *s, FFVkExecPool *pool,
+                               FFVulkanShader *shd)
+{
+    int err;
+    FFVulkanShaderData *sd;
+
+    if (!shd->nb_descriptor_sets)
+        return 0;
+
+    sd = av_realloc_array(pool->reg_shd,
+                          sizeof(*pool->reg_shd),
+                          pool->nb_reg_shd + 1);
+    if (!sd)
+        return AVERROR(ENOMEM);
+
+    pool->reg_shd = sd;
+    sd = &sd[pool->nb_reg_shd++];
+    memset(sd, 0, sizeof(*sd));
+
+    sd->shd = shd;
+    sd->nb_descriptor_sets = shd->nb_descriptor_sets;
+
+    if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
+        sd->desc_bind = av_malloc_array(sd->nb_descriptor_sets, sizeof(*sd->desc_bind));
+        if (!sd->desc_bind)
+            return AVERROR(ENOMEM);
+
+        sd->desc_set_buf = av_calloc(sd->nb_descriptor_sets, sizeof(*sd->desc_set_buf));
+        if (!sd->desc_set_buf)
+            return AVERROR(ENOMEM);
+
+        for (int i = 0; i < sd->nb_descriptor_sets; i++) {
+            FFVulkanDescriptorSet *set = &shd->desc_set[i];
+            FFVulkanDescriptorSetData *sdb = &sd->desc_set_buf[i];
+            int nb = set->singular ? 1 : pool->pool_size;
+
+            err = ff_vk_create_buf(s, &sdb->buf,
+                                   set->aligned_size*nb,
+                                   NULL, NULL, set->usage,
+                                   VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+                                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+                                   VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
+            if (err < 0)
+                return err;
+
+            err = ff_vk_map_buffer(s, &sdb->buf, &sdb->desc_mem, 0);
+            if (err < 0)
+                return err;
+
+            sd->desc_bind[i] = (VkDescriptorBufferBindingInfoEXT) {
+                .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT,
+                .usage = set->usage,
+                .address = sdb->buf.address,
+            };
+        }
+    } else if (!shd->use_push) {
+        VkResult ret;
+        FFVulkanFunctions *vk = &s->vkfn;
+        VkDescriptorSetLayout *tmp_layouts;
+        VkDescriptorSetAllocateInfo set_alloc_info;
+        VkDescriptorPoolCreateInfo pool_create_info;
+
+        for (int i = 0; i < shd->nb_desc_pool_size; i++)
+            shd->desc_pool_size[i].descriptorCount *= pool->pool_size;
+
+        pool_create_info = (VkDescriptorPoolCreateInfo) {
+            .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
+            .flags = 0,
+            .pPoolSizes = shd->desc_pool_size,
+            .poolSizeCount = shd->nb_desc_pool_size,
+            .maxSets = sd->nb_descriptor_sets*pool->pool_size,
+        };
+
+        ret = vk->CreateDescriptorPool(s->hwctx->act_dev, &pool_create_info,
+                                       s->hwctx->alloc, &sd->desc_pool);
+        if (ret != VK_SUCCESS) {
+            av_log(s, AV_LOG_ERROR, "Unable to create descriptor pool: %s\n",
+                   ff_vk_ret2str(ret));
+            return AVERROR_EXTERNAL;
+        }
+
+        tmp_layouts = av_malloc_array(pool_create_info.maxSets, sizeof(*tmp_layouts));
+        if (!tmp_layouts)
+            return AVERROR(ENOMEM);
+
+        /* Colate each execution context's descriptor set layouts */
+        for (int i = 0; i < pool->pool_size; i++)
+            for (int j = 0; j < sd->nb_descriptor_sets; j++)
+                tmp_layouts[i*sd->nb_descriptor_sets + j] = shd->desc_layout[j];
+
+        set_alloc_info = (VkDescriptorSetAllocateInfo) {
+            .sType              = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+            .descriptorPool     = sd->desc_pool,
+            .pSetLayouts        = tmp_layouts,
+            .descriptorSetCount = pool_create_info.maxSets,
+        };
+
+        sd->desc_sets = av_malloc_array(pool_create_info.maxSets,
+                                        sizeof(*tmp_layouts));
+        if (!sd->desc_sets) {
+            av_free(tmp_layouts);
+            return AVERROR(ENOMEM);
+        }
+        ret = vk->AllocateDescriptorSets(s->hwctx->act_dev, &set_alloc_info,
+                                         sd->desc_sets);
+        av_free(tmp_layouts);
+        if (ret != VK_SUCCESS) {
+            av_log(s, AV_LOG_ERROR, "Unable to allocate descriptor set: %s\n",
+                   ff_vk_ret2str(ret));
+            av_freep(&sd->desc_sets);
+            return AVERROR_EXTERNAL;
+        }
+    }
+
+    return 0;
+}
+
+static inline FFVulkanShaderData *get_shd_data(FFVkExecContext *e,
+                                               FFVulkanShader *shd)
+{
+    for (int i = 0; i < e->parent->nb_reg_shd; i++)
+        if (e->parent->reg_shd[i].shd == shd)
+            return &e->parent->reg_shd[i];
+    return NULL;
+}
+
+static inline void update_set_descriptor(FFVulkanContext *s, FFVkExecContext *e,
+                                         FFVulkanShader *shd, int set,
+                                         int bind_idx, int array_idx,
+                                         VkDescriptorGetInfoEXT *desc_get_info,
+                                         size_t desc_size)
+{
+    FFVulkanFunctions *vk = &s->vkfn;
+    FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
+    FFVulkanShaderData *sd = get_shd_data(e, shd);
+    const size_t exec_offset = desc_set->singular ? 0 : desc_set->aligned_size*e->idx;
+
+    void *desc = sd->desc_set_buf[set].desc_mem +     /* Base */
+                 exec_offset +                        /* Execution context */
+                 desc_set->binding_offset[bind_idx] + /* Descriptor binding */
+                 array_idx*desc_size;                 /* Array position */
+
+    vk->GetDescriptorEXT(s->hwctx->act_dev, desc_get_info, desc_size, desc);
+}
+
+static inline void update_set_pool_write(FFVulkanContext *s, FFVkExecContext *e,
+                                         FFVulkanShader *shd, int set,
+                                         VkWriteDescriptorSet *write_info)
+{
+    FFVulkanFunctions *vk = &s->vkfn;
+    FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
+    FFVulkanShaderData *sd = get_shd_data(e, shd);
+
+    if (desc_set->singular) {
+        for (int i = 0; i < e->parent->pool_size; i++) {
+            write_info->dstSet = sd->desc_sets[i*sd->nb_descriptor_sets + set];
+            vk->UpdateDescriptorSets(s->hwctx->act_dev, 1, write_info, 0, NULL);
+        }
+    } else {
+        if (shd->use_push) {
+            vk->CmdPushDescriptorSetKHR(e->buf,
+                                        shd->bind_point,
+                                        shd->pipeline_layout,
+                                        set, 1,
+                                        write_info);
+        } else {
+            write_info->dstSet = sd->desc_sets[e->idx*sd->nb_descriptor_sets + set];
+            vk->UpdateDescriptorSets(s->hwctx->act_dev, 1, write_info, 0, NULL);
+        }
+    }
+}
+
+int ff_vk_shader_update_img(FFVulkanContext *s, FFVkExecContext *e,
+                            FFVulkanShader *shd, int set, int bind, int offs,
+                            VkImageView view, VkImageLayout layout,
+                            VkSampler sampler)
+{
+    FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
+
+    if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
+        VkDescriptorGetInfoEXT desc_get_info = {
+            .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
+            .type = desc_set->binding[bind].descriptorType,
+        };
+        VkDescriptorImageInfo desc_img_info = {
+            .imageView = view,
+            .sampler = sampler,
+            .imageLayout = layout,
+        };
+        size_t desc_size;
+
+        switch (desc_get_info.type) {
+        case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+            desc_get_info.data.pSampledImage = &desc_img_info;
+            desc_size = s->desc_buf_props.sampledImageDescriptorSize;
+            break;
+        case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+            desc_get_info.data.pStorageImage = &desc_img_info;
+            desc_size = s->desc_buf_props.storageImageDescriptorSize;
+            break;
+        case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
+            desc_get_info.data.pInputAttachmentImage = &desc_img_info;
+            desc_size = s->desc_buf_props.inputAttachmentDescriptorSize;
+            break;
+        case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+            desc_get_info.data.pCombinedImageSampler = &desc_img_info;
+            desc_size = s->desc_buf_props.combinedImageSamplerDescriptorSize;
+            break;
+        default:
+            av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n",
+                   set, bind, desc_get_info.type);
+            return AVERROR(EINVAL);
+            break;
+        };
+
+        update_set_descriptor(s, e, shd, set, bind, offs,
+                              &desc_get_info, desc_size);
+    } else {
+        VkDescriptorImageInfo desc_pool_write_info_img = {
+            .sampler = sampler,
+            .imageView = view,
+            .imageLayout = layout,
+        };
+        VkWriteDescriptorSet desc_pool_write_info = {
+            .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+            .dstBinding = bind,
+            .descriptorCount = 1,
+            .dstArrayElement = offs,
+            .descriptorType = desc_set->binding[bind].descriptorType,
+            .pImageInfo = &desc_pool_write_info_img,
+        };
+        update_set_pool_write(s, e, shd, set, &desc_pool_write_info);
+    }
+
+    return 0;
+}
+
+void ff_vk_shader_update_img_array(FFVulkanContext *s, FFVkExecContext *e,
+                                   FFVulkanShader *shd, AVFrame *f,
+                                   VkImageView *views, int set, int binding,
+                                   VkImageLayout layout, VkSampler sampler)
+{
+    AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
+    const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
+
+    for (int i = 0; i < nb_planes; i++)
+        ff_vk_shader_update_img(s, e, shd, set, binding, i,
+                                views[i], layout, sampler);
+}
+
+int ff_vk_shader_update_desc_buffer(FFVulkanContext *s, FFVkExecContext *e,
+                                    FFVulkanShader *shd,
+                                    int set, int bind, int elem,
+                                    FFVkBuffer *buf, VkDeviceSize offset, VkDeviceSize len,
+                                    VkFormat fmt)
+{
+    FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
+
+    if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
+        VkDescriptorGetInfoEXT desc_get_info = {
+            .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
+            .type = desc_set->binding[bind].descriptorType,
+        };
+        VkDescriptorAddressInfoEXT desc_buf_info = {
+            .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT,
+            .address = buf->address + offset,
+            .range = len,
+            .format = fmt,
+        };
+        size_t desc_size;
+
+        switch (desc_get_info.type) {
+        case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+            desc_get_info.data.pUniformBuffer = &desc_buf_info;
+            desc_size = s->desc_buf_props.uniformBufferDescriptorSize;
+            break;
+        case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+            desc_get_info.data.pStorageBuffer = &desc_buf_info;
+            desc_size = s->desc_buf_props.storageBufferDescriptorSize;
+            break;
+        case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+            desc_get_info.data.pUniformTexelBuffer = &desc_buf_info;
+            desc_size = s->desc_buf_props.uniformTexelBufferDescriptorSize;
+            break;
+        case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+            desc_get_info.data.pStorageTexelBuffer = &desc_buf_info;
+            desc_size = s->desc_buf_props.storageTexelBufferDescriptorSize;
+            break;
+        default:
+            av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n",
+                   set, bind, desc_get_info.type);
+            return AVERROR(EINVAL);
+            break;
+        };
+
+        update_set_descriptor(s, e, shd, set, bind, elem, &desc_get_info, desc_size);
+    } else {
+        VkDescriptorBufferInfo desc_pool_write_info_buf = {
+            .buffer = buf->buf,
+            .offset = buf->virtual_offset + offset,
+            .range = len,
+        };
+        VkWriteDescriptorSet desc_pool_write_info = {
+            .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+            .dstBinding = bind,
+            .descriptorCount = 1,
+            .dstArrayElement = elem,
+            .descriptorType = desc_set->binding[bind].descriptorType,
+            .pBufferInfo = &desc_pool_write_info_buf,
+        };
+        update_set_pool_write(s, e, shd, set, &desc_pool_write_info);
+    }
+
+    return 0;
+}
+
+void ff_vk_shader_update_push_const(FFVulkanContext *s, FFVkExecContext *e,
+                                    FFVulkanShader *shd,
+                                    VkShaderStageFlagBits stage,
+                                    int offset, size_t size, void *src)
+{
+    FFVulkanFunctions *vk = &s->vkfn;
+    vk->CmdPushConstants(e->buf, shd->pipeline_layout,
+                         stage, offset, size, src);
+}
+
+void ff_vk_exec_bind_shader(FFVulkanContext *s, FFVkExecContext *e,
+                            FFVulkanShader *shd)
+{
+    FFVulkanFunctions *vk = &s->vkfn;
+    VkDeviceSize offsets[1024];
+    FFVulkanShaderData *sd = get_shd_data(e, shd);
+
+    if (s->extensions & FF_VK_EXT_SHADER_OBJECT) {
+        VkShaderStageFlagBits stages = shd->stage;
+        vk->CmdBindShadersEXT(e->buf, 1, &stages, &shd->object);
+    } else {
+        vk->CmdBindPipeline(e->buf, shd->bind_point, shd->pipeline);
+    }
+
+    if (sd && sd->nb_descriptor_sets) {
+        if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
+            for (int i = 0; i < sd->nb_descriptor_sets; i++)
+                offsets[i] = shd->desc_set[i].singular ? 0 : shd->desc_set[i].aligned_size*e->idx;
+
+            /* Bind descriptor buffers */
+            vk->CmdBindDescriptorBuffersEXT(e->buf, sd->nb_descriptor_sets, sd->desc_bind);
+            /* Binding offsets */
+            vk->CmdSetDescriptorBufferOffsetsEXT(e->buf, shd->bind_point, shd->pipeline_layout,
+                                                 0, sd->nb_descriptor_sets,
+                                                 shd->bound_buffer_indices, offsets);
+        } else if (!shd->use_push) {
+            vk->CmdBindDescriptorSets(e->buf, shd->bind_point, shd->pipeline_layout,
+                                      0, sd->nb_descriptor_sets,
+                                      &sd->desc_sets[e->idx*sd->nb_descriptor_sets],
+                                      0, NULL);
+        }
+    }
+}
+
+void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd)
+{
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    av_bprint_finalize(&shd->src, NULL);
+
+#if 0
+    if (shd->shader.module)
+        vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module,
+                                s->hwctx->alloc);
+#endif
+
+    if (shd->object)
+        vk->DestroyShaderEXT(s->hwctx->act_dev, shd->object, s->hwctx->alloc);
+    if (shd->pipeline)
+        vk->DestroyPipeline(s->hwctx->act_dev, shd->pipeline, s->hwctx->alloc);
+    if (shd->pipeline_layout)
+        vk->DestroyPipelineLayout(s->hwctx->act_dev, shd->pipeline_layout,
+                                  s->hwctx->alloc);
+
+    for (int i = 0; i < shd->nb_descriptor_sets; i++) {
+        FFVulkanDescriptorSet *set = &shd->desc_set[i];
+        av_free(set->binding);
+        av_free(set->binding_offset);
+    }
+
+    if (shd->desc_layout) {
+        for (int i = 0; i < shd->nb_descriptor_sets; i++)
+            if (shd->desc_layout[i])
+                vk->DestroyDescriptorSetLayout(s->hwctx->act_dev, shd->desc_layout[i],
+                                               s->hwctx->alloc);
+    }
+
+    av_freep(&shd->desc_pool_size);
+    av_freep(&shd->desc_layout);
+    av_freep(&shd->desc_set);
+    av_freep(&shd->bound_buffer_indices);
+    av_freep(&shd->push_consts);
+    shd->push_consts_num = 0;
+}
+
+void ff_vk_uninit(FFVulkanContext *s)
+{
+    av_freep(&s->query_props);
+    av_freep(&s->qf_props);
+    av_freep(&s->video_props);
+    av_freep(&s->coop_mat_props);
+    av_freep(&s->host_image_copy_layouts);
+
+    av_buffer_unref(&s->device_ref);
+    av_buffer_unref(&s->frames_ref);
+}
+
+int ff_vk_init(FFVulkanContext *s, void *log_parent,
+               AVBufferRef *device_ref, AVBufferRef *frames_ref)
+{
+    int err;
+
+    static const AVClass vulkan_context_class = {
+        .class_name       = "vk",
+        .version          = LIBAVUTIL_VERSION_INT,
+        .parent_log_context_offset = offsetof(FFVulkanContext, log_parent),
+    };
+
+    memset(s, 0, sizeof(*s));
+    s->log_parent = log_parent;
+    s->class      = &vulkan_context_class;
+
+    if (frames_ref) {
+        s->frames_ref = av_buffer_ref(frames_ref);
+        if (!s->frames_ref)
+            return AVERROR(ENOMEM);
+
+        s->frames = (AVHWFramesContext *)s->frames_ref->data;
+        s->hwfc = s->frames->hwctx;
+
+        device_ref = s->frames->device_ref;
+    }
+
+    s->device_ref = av_buffer_ref(device_ref);
+    if (!s->device_ref) {
+        ff_vk_uninit(s);
+        return AVERROR(ENOMEM);
+    }
+
+    s->device = (AVHWDeviceContext *)s->device_ref->data;
+    s->hwctx = s->device->hwctx;
+
+    s->extensions = ff_vk_extensions_to_mask(s->hwctx->enabled_dev_extensions,
+                                             s->hwctx->nb_enabled_dev_extensions);
+    s->extensions |= ff_vk_extensions_to_mask(s->hwctx->enabled_inst_extensions,
+                                              s->hwctx->nb_enabled_inst_extensions);
+
+    err = ff_vk_load_functions(s->device, &s->vkfn, s->extensions, 1, 1);
+    if (err < 0) {
+        ff_vk_uninit(s);
+        return err;
+    }
+
+    err = ff_vk_load_props(s);
+    if (err < 0) {
+        ff_vk_uninit(s);
+        return err;
+    }
+
+    return 0;
+}
-- 
2.49.1


From b1e3cb34245f62dc74c3c26a2fc6d6b330d957ca Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:18:20 +0000
Subject: [PATCH 045/118] Changing vulkan file directory

---
 libavutil/vulkan.h | 665 ---------------------------------------------
 1 file changed, 665 deletions(-)
 delete mode 100644 libavutil/vulkan.h

diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h
deleted file mode 100644
index e1c9a5792f..0000000000
--- a/libavutil/vulkan.h
+++ /dev/null
@@ -1,665 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVUTIL_VULKAN_H
-#define AVUTIL_VULKAN_H
-
-#define VK_NO_PROTOTYPES
-
-#include <stdatomic.h>
-
-#include "pixdesc.h"
-#include "bprint.h"
-#include "hwcontext.h"
-#include "vulkan_functions.h"
-#include "hwcontext_vulkan.h"
-
-/* GLSL management macros */
-#define INDENT(N) INDENT_##N
-#define INDENT_0
-#define INDENT_1 INDENT_0 "    "
-#define INDENT_2 INDENT_1 INDENT_1
-#define INDENT_3 INDENT_2 INDENT_1
-#define INDENT_4 INDENT_3 INDENT_1
-#define INDENT_5 INDENT_4 INDENT_1
-#define INDENT_6 INDENT_5 INDENT_1
-#define C(N, S)          INDENT(N) #S "\n"
-
-#define GLSLC(N, S)                     \
-    do {                                \
-        av_bprintf(&shd->src, C(N, S)); \
-    } while (0)
-
-#define GLSLA(...)                          \
-    do {                                    \
-        av_bprintf(&shd->src, __VA_ARGS__); \
-    } while (0)
-
-#define GLSLF(N, S, ...)                             \
-    do {                                             \
-        av_bprintf(&shd->src, C(N, S), __VA_ARGS__); \
-    } while (0)
-
-#define GLSLD(D)                                        \
-    do {                                                \
-        av_bprintf(&shd->src, "\n");                    \
-        av_bprint_append_data(&shd->src, D, strlen(D)); \
-        av_bprintf(&shd->src, "\n");                    \
-    } while (0)
-
-/* Helper, pretty much every Vulkan return value needs to be checked */
-#define RET(x)                                                                 \
-    do {                                                                       \
-        if ((err = (x)) < 0)                                                   \
-            goto fail;                                                         \
-    } while (0)
-
-#define DUP_SAMPLER(x) { x, x, x, x }
-
-typedef struct FFVulkanDescriptorSetBinding {
-    const char         *name;
-    VkDescriptorType    type;
-    const char         *mem_layout;  /* Storage images (rgba8, etc.) and buffers (std430, etc.) */
-    const char         *mem_quali;   /* readonly, writeonly, etc. */
-    const char         *buf_content; /* For buffers */
-    uint32_t            dimensions;  /* Needed for e.g. sampler%iD */
-    uint32_t            elems;       /* 0 - scalar, 1 or more - vector */
-    VkShaderStageFlags  stages;
-    uint32_t            buf_elems;   /* Appends [buf_elems] to the contents. Avoids manually printing to a string. */
-    VkSampler           samplers[4]; /* Sampler to use for all elems */
-} FFVulkanDescriptorSetBinding;
-
-typedef struct FFVkBuffer {
-    VkBuffer buf;
-    VkDeviceMemory mem;
-    VkMemoryPropertyFlagBits flags;
-    size_t size;
-    VkDeviceAddress address;
-
-    /* Local use only */
-    VkPipelineStageFlags2 stage;
-    VkAccessFlags2 access;
-
-    /* Only valid when allocated via ff_vk_get_pooled_buffer with HOST_VISIBLE or
-     * via ff_vk_host_map_buffer */
-    uint8_t *mapped_mem;
-
-    /* Set by ff_vk_host_map_buffer. This is the offset at which the buffer data
-     * actually begins at.
-     * The address and mapped_mem fields will be offset by this amount. */
-    size_t virtual_offset;
-
-    /* If host mapping, reference to the backing host memory buffer */
-    AVBufferRef *host_ref;
-} FFVkBuffer;
-
-typedef struct FFVkExecContext {
-    uint32_t idx;
-    const struct FFVkExecPool *parent;
-    int had_submission;
-
-    /* Queue for the execution context */
-    VkQueue queue;
-    int qf;
-    int qi;
-
-    /* Command buffer for the context */
-    VkCommandBuffer buf;
-
-    /* Fence for the command buffer */
-    VkFence fence;
-
-    /* Opaque data, untouched, free to use by users */
-    void *opaque;
-
-    void *query_data;
-    int query_idx;
-
-    /* Buffer dependencies */
-    AVBufferRef **buf_deps;
-    int nb_buf_deps;
-    unsigned int buf_deps_alloc_size;
-
-    /* Frame dependencies */
-    AVFrame **frame_deps;
-    unsigned int frame_deps_alloc_size;
-    int nb_frame_deps;
-
-    /* Software frame dependencies */
-    AVFrame **sw_frame_deps;
-    unsigned int sw_frame_deps_alloc_size;
-    int nb_sw_frame_deps;
-
-    VkSemaphoreSubmitInfo *sem_wait;
-    unsigned int sem_wait_alloc;
-    int sem_wait_cnt;
-
-    VkSemaphoreSubmitInfo *sem_sig;
-    unsigned int sem_sig_alloc;
-    int sem_sig_cnt;
-
-    uint64_t **sem_sig_val_dst;
-    unsigned int sem_sig_val_dst_alloc;
-    int sem_sig_val_dst_cnt;
-
-    uint8_t *frame_locked;
-    unsigned int frame_locked_alloc_size;
-
-    VkAccessFlagBits *access_dst;
-    unsigned int access_dst_alloc;
-
-    VkImageLayout *layout_dst;
-    unsigned int layout_dst_alloc;
-
-    uint32_t *queue_family_dst;
-    unsigned int queue_family_dst_alloc;
-
-    uint8_t *frame_update;
-    unsigned int frame_update_alloc_size;
-} FFVkExecContext;
-
-typedef struct FFVulkanDescriptorSet {
-    /* Descriptor buffer */
-    VkDeviceSize layout_size;
-    VkDeviceSize aligned_size; /* descriptorBufferOffsetAlignment */
-    VkBufferUsageFlags usage;
-
-    VkDescriptorSetLayoutBinding *binding;
-    VkDeviceSize *binding_offset;
-    int nb_bindings;
-
-    /* Descriptor set is shared between all submissions */
-    int singular;
-} FFVulkanDescriptorSet;
-
-typedef struct FFVulkanShader {
-    /* Name for id/debugging purposes */
-    const char *name;
-
-    /* Shader text */
-    AVBPrint src;
-
-    /* Compute shader local group sizes */
-    int lg_size[3];
-
-    /* Shader bind point/type */
-    VkPipelineStageFlags stage;
-    VkPipelineBindPoint bind_point;
-
-    /* Creation info */
-    VkPipelineShaderStageRequiredSubgroupSizeCreateInfo subgroup_info;
-
-    /* Base shader object */
-    VkShaderEXT object;
-    VkPipeline pipeline;
-
-    /* Pipeline layout */
-    VkPipelineLayout pipeline_layout;
-
-    /* Push consts */
-    VkPushConstantRange *push_consts;
-    int push_consts_num;
-
-    /* Descriptor sets */
-    FFVulkanDescriptorSet *desc_set;
-    int nb_descriptor_sets;
-
-    /* Descriptor buffer */
-    VkDescriptorSetLayout *desc_layout;
-    uint32_t *bound_buffer_indices;
-
-    /* Descriptor pool */
-    int use_push;
-    VkDescriptorPoolSize *desc_pool_size;
-    int nb_desc_pool_size;
-} FFVulkanShader;
-
-typedef struct FFVulkanDescriptorSetData {
-    /* Descriptor buffer */
-    FFVkBuffer buf;
-    uint8_t *desc_mem;
-} FFVulkanDescriptorSetData;
-
-typedef struct FFVulkanShaderData {
-    /* Shader to which this data belongs to */
-    FFVulkanShader *shd;
-    int nb_descriptor_sets;
-
-    /* Descriptor buffer */
-    FFVulkanDescriptorSetData *desc_set_buf;
-    VkDescriptorBufferBindingInfoEXT *desc_bind;
-
-    /* Descriptor pools */
-    VkDescriptorSet *desc_sets;
-    VkDescriptorPool desc_pool;
-} FFVulkanShaderData;
-
-typedef struct FFVkExecPool {
-    FFVkExecContext *contexts;
-    atomic_uint_least64_t idx;
-
-    VkCommandPool *cmd_buf_pools;
-    VkCommandBuffer *cmd_bufs;
-    int pool_size;
-
-    VkQueryPool query_pool;
-    void *query_data;
-    int query_results;
-    int query_statuses;
-    int query_64bit;
-    int query_status_stride;
-    int nb_queries;
-    size_t qd_size;
-
-    /* Registered shaders' data */
-    FFVulkanShaderData *reg_shd;
-    int nb_reg_shd;
-} FFVkExecPool;
-
-typedef struct FFVulkanContext {
-    const AVClass *class;
-    void *log_parent;
-
-    FFVulkanFunctions     vkfn;
-    FFVulkanExtensions    extensions;
-    VkPhysicalDeviceProperties2 props;
-    VkPhysicalDeviceVulkan11Properties props_11;
-    VkPhysicalDeviceDriverProperties driver_props;
-    VkPhysicalDeviceMemoryProperties mprops;
-    VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops;
-    VkPhysicalDeviceDescriptorBufferPropertiesEXT desc_buf_props;
-    VkPhysicalDeviceSubgroupSizeControlProperties subgroup_props;
-    VkPhysicalDeviceCooperativeMatrixPropertiesKHR coop_matrix_props;
-    VkPhysicalDevicePushDescriptorPropertiesKHR push_desc_props;
-    VkPhysicalDeviceOpticalFlowPropertiesNV optical_flow_props;
-    VkQueueFamilyQueryResultStatusPropertiesKHR *query_props;
-    VkQueueFamilyVideoPropertiesKHR *video_props;
-    VkQueueFamilyProperties2 *qf_props;
-    int tot_nb_qfs;
-    VkPhysicalDeviceHostImageCopyPropertiesEXT host_image_props;
-    VkImageLayout *host_image_copy_layouts;
-
-    VkCooperativeMatrixPropertiesKHR *coop_mat_props;
-    uint32_t coop_mat_props_nb;
-
-    VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float_feats;
-    VkPhysicalDeviceVulkan12Features feats_12;
-    VkPhysicalDeviceFeatures2 feats;
-
-    AVBufferRef           *device_ref;
-    AVHWDeviceContext     *device;
-    AVVulkanDeviceContext *hwctx;
-
-    AVBufferRef           *input_frames_ref;
-    AVBufferRef           *frames_ref;
-    AVHWFramesContext     *frames;
-    AVVulkanFramesContext *hwfc;
-
-    uint32_t               qfs[64];
-    int                    nb_qfs;
-
-    /* Properties */
-    int                 output_width;
-    int                output_height;
-    enum AVPixelFormat output_format;
-    enum AVPixelFormat  input_format;
-} FFVulkanContext;
-
-static inline int ff_vk_count_images(AVVkFrame *f)
-{
-    int cnt = 0;
-    while (cnt < FF_ARRAY_ELEMS(f->img) && f->img[cnt])
-        cnt++;
-
-    return cnt;
-}
-
-static inline const void *ff_vk_find_struct(const void *chain, VkStructureType stype)
-{
-    const VkBaseInStructure *in = chain;
-    while (in) {
-        if (in->sType == stype)
-            return in;
-
-        in = in->pNext;
-    }
-
-    return NULL;
-}
-
-static inline void ff_vk_link_struct(void *chain, const void *in)
-{
-    VkBaseOutStructure *out = chain;
-    while (out->pNext)
-        out = out->pNext;
-
-    out->pNext = (void *)in;
-}
-
-#define FF_VK_STRUCT_EXT(CTX, BASE, STRUCT_P, EXT_FLAG, TYPE) \
-    do {                                                      \
-        if ((EXT_FLAG == FF_VK_EXT_NO_FLAG) ||                \
-            ((CTX)->extensions & EXT_FLAG)) {                 \
-            (STRUCT_P)->sType = TYPE;                         \
-            ff_vk_link_struct(BASE, STRUCT_P);                \
-        }                                                     \
-    } while (0)
-
-/* Identity mapping - r = r, b = b, g = g, a = a */
-extern const VkComponentMapping ff_comp_identity_map;
-
-/**
- * Initializes the AVClass, in case this context is not used
- * as the main user's context.
- * May use either a frames context reference, or a device context reference.
- */
-int ff_vk_init(FFVulkanContext *s, void *log_parent,
-               AVBufferRef *device_ref, AVBufferRef *frames_ref);
-
-/**
- * Converts Vulkan return values to strings
- */
-const char *ff_vk_ret2str(VkResult res);
-
-/**
- * Map between usage and features.
- */
-VkImageUsageFlags ff_vk_map_feats_to_usage(VkFormatFeatureFlagBits2 feats);
-VkFormatFeatureFlagBits2 ff_vk_map_usage_to_feats(VkImageUsageFlags usage);
-
-/**
- * Returns 1 if pixfmt is a usable RGB format.
- */
-int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt);
-
-/**
- * Since storage images may not be swizzled, we have to do this in the
- * shader itself. This fills in a lookup table to do it.
- */
-void ff_vk_set_perm(enum AVPixelFormat pix_fmt, int lut[4], int inv);
-
-/**
- * Get the aspect flag for a plane from an image.
- */
-VkImageAspectFlags ff_vk_aspect_flag(AVFrame *f, int p);
-
-/**
- * Returns the format to use for images in shaders.
- */
-enum FFVkShaderRepFormat {
-    /* Native format with no conversion. May require casting. */
-    FF_VK_REP_NATIVE = 0,
-    /* Float conversion of the native format. */
-    FF_VK_REP_FLOAT,
-    /* Signed integer version of the native format */
-    FF_VK_REP_INT,
-    /* Unsigned integer version of the native format */
-    FF_VK_REP_UINT,
-};
-const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pix_fmt,
-                                 enum FFVkShaderRepFormat rep_fmt);
-
-/**
- * Loads props/mprops/driver_props
- */
-int ff_vk_load_props(FFVulkanContext *s);
-
-/**
- * Chooses an appropriate QF.
- */
-AVVulkanDeviceQueueFamily *ff_vk_qf_find(FFVulkanContext *s,
-                                         VkQueueFlagBits dev_family,
-                                         VkVideoCodecOperationFlagBitsKHR vid_ops);
-
-/**
- * Allocates/frees an execution pool.
- * If used in a multi-threaded context, there must be at least as many contexts
- * as there are threads.
- * ff_vk_exec_pool_init_desc() MUST be called if ff_vk_exec_descriptor_set_add()
- * has been called.
- */
-int ff_vk_exec_pool_init(FFVulkanContext *s, AVVulkanDeviceQueueFamily *qf,
-                         FFVkExecPool *pool, int nb_contexts,
-                         int nb_queries, VkQueryType query_type, int query_64bit,
-                         const void *query_create_pnext);
-void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool);
-
-/**
- * Retrieve an execution pool. Threadsafe.
- */
-FFVkExecContext *ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool);
-
-/**
- * Performs nb_queries queries and returns their results and statuses.
- * 64_BIT and WITH_STATUS flags are ignored as 64_BIT must be specified via
- * query_64bit in ff_vk_exec_pool_init() and WITH_STATUS is always enabled.
- */
-VkResult ff_vk_exec_get_query(FFVulkanContext *s, FFVkExecContext *e,
-                              void **data, VkQueryResultFlagBits flags);
-
-/**
- * Start/submit/wait an execution.
- * ff_vk_exec_start() always waits on a submission, so using ff_vk_exec_wait()
- * is not necessary (unless using it is just better).
- */
-int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e);
-int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e);
-void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e);
-
-/**
- * Execution dependency management.
- * Can attach buffers to executions that will only be unref'd once the
- * buffer has finished executing.
- * Adding a frame dep will *lock the frame*, until either the dependencies
- * are discarded, the execution is submitted, or a failure happens.
- * update_frame will update the frame's properties before it is unlocked,
- * only if submission was successful.
- */
-int ff_vk_exec_add_dep_buf(FFVulkanContext *s, FFVkExecContext *e,
-                           AVBufferRef **deps, int nb_deps, int ref);
-int ff_vk_exec_add_dep_wait_sem(FFVulkanContext *s, FFVkExecContext *e,
-                                VkSemaphore sem, uint64_t val,
-                                VkPipelineStageFlagBits2 stage);
-int ff_vk_exec_add_dep_bool_sem(FFVulkanContext *s, FFVkExecContext *e,
-                                VkSemaphore *sem, int nb,
-                                VkPipelineStageFlagBits2 stage,
-                                int wait); /* Ownership transferred if !wait */
-int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f,
-                             VkPipelineStageFlagBits2 wait_stage,
-                             VkPipelineStageFlagBits2 signal_stage);
-int ff_vk_exec_add_dep_sw_frame(FFVulkanContext *s, FFVkExecContext *e,
-                                AVFrame *f);
-void ff_vk_exec_update_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f,
-                             VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar);
-int ff_vk_exec_mirror_sem_value(FFVulkanContext *s, FFVkExecContext *e,
-                                VkSemaphore *dst, uint64_t *dst_val,
-                                AVFrame *f);
-void ff_vk_exec_discard_deps(FFVulkanContext *s, FFVkExecContext *e);
-
-/**
- * Create a single imageview for a given plane.
- */
-int ff_vk_create_imageview(FFVulkanContext *s,
-                           VkImageView *img_view, VkImageAspectFlags *aspect,
-                           AVFrame *f, int plane, enum FFVkShaderRepFormat rep_fmt);
-
-/**
- * Create an imageview and add it as a dependency to an execution.
- */
-int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e,
-                            VkImageView views[AV_NUM_DATA_POINTERS],
-                            AVFrame *f, enum FFVkShaderRepFormat rep_fmt);
-
-void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e,
-                         AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar,
-                         VkPipelineStageFlags src_stage,
-                         VkPipelineStageFlags dst_stage,
-                         VkAccessFlagBits     new_access,
-                         VkImageLayout        new_layout,
-                         uint32_t             new_qf);
-
-/**
- * Memory/buffer/image allocation helpers.
- */
-int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req,
-                    VkMemoryPropertyFlagBits req_flags, void *alloc_extension,
-                    VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem);
-int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size,
-                     void *pNext, void *alloc_pNext,
-                     VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags);
-
-/**
- * Buffer management code.
- */
-int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer **buf, uint8_t *mem[],
-                      int nb_buffers, int invalidate);
-int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers,
-                        int flush);
-
-static inline int ff_vk_map_buffer(FFVulkanContext *s, FFVkBuffer *buf, uint8_t **mem,
-                                   int invalidate)
-{
-    return ff_vk_map_buffers(s, (FFVkBuffer *[]){ buf }, mem,
-                             1, invalidate);
-}
-
-static inline int ff_vk_unmap_buffer(FFVulkanContext *s, FFVkBuffer *buf, int flush)
-{
-    return ff_vk_unmap_buffers(s, (FFVkBuffer *[]){ buf }, 1, flush);
-}
-
-void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf);
-
-/** Initialize a pool and create AVBufferRefs containing FFVkBuffer.
- * Threadsafe to use. Buffers are automatically mapped on creation if
- * VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT is set in mem_props. Users should
- * synchronize access themselvesd. Mainly meant for device-local buffers. */
-int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVBufferPool **buf_pool,
-                            AVBufferRef **buf, VkBufferUsageFlags usage,
-                            void *create_pNext, size_t size,
-                            VkMemoryPropertyFlagBits mem_props);
-
-/** Maps a system RAM buffer into a Vulkan buffer.
- * References the source buffer.
- */
-int ff_vk_host_map_buffer(FFVulkanContext *s, AVBufferRef **dst,
-                          uint8_t *src_data, const AVBufferRef *src_buf,
-                          VkBufferUsageFlags usage);
-
-/**
- * Create a sampler.
- */
-int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler,
-                       int unnorm_coords, VkFilter filt);
-
-/**
- * Initialize a shader object, with a specific set of extensions, type+bind,
- * local group size, and subgroup requirements.
- */
-int ff_vk_shader_init(FFVulkanContext *s, FFVulkanShader *shd, const char *name,
-                      VkPipelineStageFlags stage,
-                      const char *extensions[], int nb_extensions,
-                      int lg_x, int lg_y, int lg_z,
-                      uint32_t required_subgroup_size);
-
-/**
- * Output the shader code as logging data, with a specific
- * priority.
- */
-void ff_vk_shader_print(void *ctx, FFVulkanShader *shd, int prio);
-
-/**
- * Link a shader into an executable.
- */
-int ff_vk_shader_link(FFVulkanContext *s, FFVulkanShader *shd,
-                      uint8_t *spirv, size_t spirv_len,
-                      const char *entrypoint);
-
-/**
- * Add/update push constants for execution.
- */
-int ff_vk_shader_add_push_const(FFVulkanShader *shd, int offset, int size,
-                                VkShaderStageFlagBits stage);
-
-/**
- * Add descriptor to a shader. Must be called before shader init.
- */
-int ff_vk_shader_add_descriptor_set(FFVulkanContext *s, FFVulkanShader *shd,
-                                    FFVulkanDescriptorSetBinding *desc, int nb,
-                                    int singular, int print_to_shader_only);
-
-/**
- * Register a shader with an exec pool.
- * Pool may be NULL if all descriptor sets are read-only.
- */
-int ff_vk_shader_register_exec(FFVulkanContext *s, FFVkExecPool *pool,
-                               FFVulkanShader *shd);
-
-/**
- * Bind a shader.
- */
-void ff_vk_exec_bind_shader(FFVulkanContext *s, FFVkExecContext *e,
-                            FFVulkanShader *shd);
-
-/**
- * Update push constant in a shader.
- * Must be called before binding the shader.
- */
-void ff_vk_shader_update_push_const(FFVulkanContext *s, FFVkExecContext *e,
-                                    FFVulkanShader *shd,
-                                    VkShaderStageFlagBits stage,
-                                    int offset, size_t size, void *src);
-
-/**
- * Update a descriptor in a buffer with a buffer.
- * Must be called before binding the shader.
- */
-int ff_vk_shader_update_desc_buffer(FFVulkanContext *s, FFVkExecContext *e,
-                                    FFVulkanShader *shd,
-                                    int set, int bind, int elem,
-                                    FFVkBuffer *buf, VkDeviceSize offset, VkDeviceSize len,
-                                    VkFormat fmt);
-
-/**
- * Sets an image descriptor for specified shader and binding.
- */
-int ff_vk_shader_update_img(FFVulkanContext *s, FFVkExecContext *e,
-                            FFVulkanShader *shd, int set, int bind, int offs,
-                            VkImageView view, VkImageLayout layout,
-                            VkSampler sampler);
-
-/**
- * Update a descriptor in a buffer with an image array..
- * Must be called before binding the shader.
- */
-void ff_vk_shader_update_img_array(FFVulkanContext *s, FFVkExecContext *e,
-                                   FFVulkanShader *shd, AVFrame *f,
-                                   VkImageView *views, int set, int binding,
-                                   VkImageLayout layout, VkSampler sampler);
-
-/**
- * Free a shader.
- */
-void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd);
-
-/**
- * Frees main context.
- */
-void ff_vk_uninit(FFVulkanContext *s);
-
-#endif /* AVUTIL_VULKAN_H */
-- 
2.49.1


From de4430792c625521171e760e1664969858a10838 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:18:41 +0000
Subject: [PATCH 046/118] Changing vulkan file directory

---
 libavutil/vulkan/vulkan.h | 665 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 665 insertions(+)
 create mode 100644 libavutil/vulkan/vulkan.h

diff --git a/libavutil/vulkan/vulkan.h b/libavutil/vulkan/vulkan.h
new file mode 100644
index 0000000000..84f78a6485
--- /dev/null
+++ b/libavutil/vulkan/vulkan.h
@@ -0,0 +1,665 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_VULKAN_H
+#define AVUTIL_VULKAN_H
+
+#define VK_NO_PROTOTYPES
+
+#include <stdatomic.h>
+
+#include "libavutil/pixdesc.h"
+#include "libavutil/bprint.h"
+#include "libavutil/hwcontext.h"
+#include "vulkan_functions.h"
+#include "hwcontext_vulkan.h"
+
+/* GLSL management macros */
+#define INDENT(N) INDENT_##N
+#define INDENT_0
+#define INDENT_1 INDENT_0 "    "
+#define INDENT_2 INDENT_1 INDENT_1
+#define INDENT_3 INDENT_2 INDENT_1
+#define INDENT_4 INDENT_3 INDENT_1
+#define INDENT_5 INDENT_4 INDENT_1
+#define INDENT_6 INDENT_5 INDENT_1
+#define C(N, S)          INDENT(N) #S "\n"
+
+#define GLSLC(N, S)                     \
+    do {                                \
+        av_bprintf(&shd->src, C(N, S)); \
+    } while (0)
+
+#define GLSLA(...)                          \
+    do {                                    \
+        av_bprintf(&shd->src, __VA_ARGS__); \
+    } while (0)
+
+#define GLSLF(N, S, ...)                             \
+    do {                                             \
+        av_bprintf(&shd->src, C(N, S), __VA_ARGS__); \
+    } while (0)
+
+#define GLSLD(D)                                        \
+    do {                                                \
+        av_bprintf(&shd->src, "\n");                    \
+        av_bprint_append_data(&shd->src, D, strlen(D)); \
+        av_bprintf(&shd->src, "\n");                    \
+    } while (0)
+
+/* Helper, pretty much every Vulkan return value needs to be checked */
+#define RET(x)                                                                 \
+    do {                                                                       \
+        if ((err = (x)) < 0)                                                   \
+            goto fail;                                                         \
+    } while (0)
+
+#define DUP_SAMPLER(x) { x, x, x, x }
+
+typedef struct FFVulkanDescriptorSetBinding {
+    const char         *name;
+    VkDescriptorType    type;
+    const char         *mem_layout;  /* Storage images (rgba8, etc.) and buffers (std430, etc.) */
+    const char         *mem_quali;   /* readonly, writeonly, etc. */
+    const char         *buf_content; /* For buffers */
+    uint32_t            dimensions;  /* Needed for e.g. sampler%iD */
+    uint32_t            elems;       /* 0 - scalar, 1 or more - vector */
+    VkShaderStageFlags  stages;
+    uint32_t            buf_elems;   /* Appends [buf_elems] to the contents. Avoids manually printing to a string. */
+    VkSampler           samplers[4]; /* Sampler to use for all elems */
+} FFVulkanDescriptorSetBinding;
+
+typedef struct FFVkBuffer {
+    VkBuffer buf;
+    VkDeviceMemory mem;
+    VkMemoryPropertyFlagBits flags;
+    size_t size;
+    VkDeviceAddress address;
+
+    /* Local use only */
+    VkPipelineStageFlags2 stage;
+    VkAccessFlags2 access;
+
+    /* Only valid when allocated via ff_vk_get_pooled_buffer with HOST_VISIBLE or
+     * via ff_vk_host_map_buffer */
+    uint8_t *mapped_mem;
+
+    /* Set by ff_vk_host_map_buffer. This is the offset at which the buffer data
+     * actually begins at.
+     * The address and mapped_mem fields will be offset by this amount. */
+    size_t virtual_offset;
+
+    /* If host mapping, reference to the backing host memory buffer */
+    AVBufferRef *host_ref;
+} FFVkBuffer;
+
+typedef struct FFVkExecContext {
+    uint32_t idx;
+    const struct FFVkExecPool *parent;
+    int had_submission;
+
+    /* Queue for the execution context */
+    VkQueue queue;
+    int qf;
+    int qi;
+
+    /* Command buffer for the context */
+    VkCommandBuffer buf;
+
+    /* Fence for the command buffer */
+    VkFence fence;
+
+    /* Opaque data, untouched, free to use by users */
+    void *opaque;
+
+    void *query_data;
+    int query_idx;
+
+    /* Buffer dependencies */
+    AVBufferRef **buf_deps;
+    int nb_buf_deps;
+    unsigned int buf_deps_alloc_size;
+
+    /* Frame dependencies */
+    AVFrame **frame_deps;
+    unsigned int frame_deps_alloc_size;
+    int nb_frame_deps;
+
+    /* Software frame dependencies */
+    AVFrame **sw_frame_deps;
+    unsigned int sw_frame_deps_alloc_size;
+    int nb_sw_frame_deps;
+
+    VkSemaphoreSubmitInfo *sem_wait;
+    unsigned int sem_wait_alloc;
+    int sem_wait_cnt;
+
+    VkSemaphoreSubmitInfo *sem_sig;
+    unsigned int sem_sig_alloc;
+    int sem_sig_cnt;
+
+    uint64_t **sem_sig_val_dst;
+    unsigned int sem_sig_val_dst_alloc;
+    int sem_sig_val_dst_cnt;
+
+    uint8_t *frame_locked;
+    unsigned int frame_locked_alloc_size;
+
+    VkAccessFlagBits *access_dst;
+    unsigned int access_dst_alloc;
+
+    VkImageLayout *layout_dst;
+    unsigned int layout_dst_alloc;
+
+    uint32_t *queue_family_dst;
+    unsigned int queue_family_dst_alloc;
+
+    uint8_t *frame_update;
+    unsigned int frame_update_alloc_size;
+} FFVkExecContext;
+
+typedef struct FFVulkanDescriptorSet {
+    /* Descriptor buffer */
+    VkDeviceSize layout_size;
+    VkDeviceSize aligned_size; /* descriptorBufferOffsetAlignment */
+    VkBufferUsageFlags usage;
+
+    VkDescriptorSetLayoutBinding *binding;
+    VkDeviceSize *binding_offset;
+    int nb_bindings;
+
+    /* Descriptor set is shared between all submissions */
+    int singular;
+} FFVulkanDescriptorSet;
+
+typedef struct FFVulkanShader {
+    /* Name for id/debugging purposes */
+    const char *name;
+
+    /* Shader text */
+    AVBPrint src;
+
+    /* Compute shader local group sizes */
+    int lg_size[3];
+
+    /* Shader bind point/type */
+    VkPipelineStageFlags stage;
+    VkPipelineBindPoint bind_point;
+
+    /* Creation info */
+    VkPipelineShaderStageRequiredSubgroupSizeCreateInfo subgroup_info;
+
+    /* Base shader object */
+    VkShaderEXT object;
+    VkPipeline pipeline;
+
+    /* Pipeline layout */
+    VkPipelineLayout pipeline_layout;
+
+    /* Push consts */
+    VkPushConstantRange *push_consts;
+    int push_consts_num;
+
+    /* Descriptor sets */
+    FFVulkanDescriptorSet *desc_set;
+    int nb_descriptor_sets;
+
+    /* Descriptor buffer */
+    VkDescriptorSetLayout *desc_layout;
+    uint32_t *bound_buffer_indices;
+
+    /* Descriptor pool */
+    int use_push;
+    VkDescriptorPoolSize *desc_pool_size;
+    int nb_desc_pool_size;
+} FFVulkanShader;
+
+typedef struct FFVulkanDescriptorSetData {
+    /* Descriptor buffer */
+    FFVkBuffer buf;
+    uint8_t *desc_mem;
+} FFVulkanDescriptorSetData;
+
+typedef struct FFVulkanShaderData {
+    /* Shader to which this data belongs to */
+    FFVulkanShader *shd;
+    int nb_descriptor_sets;
+
+    /* Descriptor buffer */
+    FFVulkanDescriptorSetData *desc_set_buf;
+    VkDescriptorBufferBindingInfoEXT *desc_bind;
+
+    /* Descriptor pools */
+    VkDescriptorSet *desc_sets;
+    VkDescriptorPool desc_pool;
+} FFVulkanShaderData;
+
+typedef struct FFVkExecPool {
+    FFVkExecContext *contexts;
+    atomic_uint_least64_t idx;
+
+    VkCommandPool *cmd_buf_pools;
+    VkCommandBuffer *cmd_bufs;
+    int pool_size;
+
+    VkQueryPool query_pool;
+    void *query_data;
+    int query_results;
+    int query_statuses;
+    int query_64bit;
+    int query_status_stride;
+    int nb_queries;
+    size_t qd_size;
+
+    /* Registered shaders' data */
+    FFVulkanShaderData *reg_shd;
+    int nb_reg_shd;
+} FFVkExecPool;
+
+typedef struct FFVulkanContext {
+    const AVClass *class;
+    void *log_parent;
+
+    FFVulkanFunctions     vkfn;
+    FFVulkanExtensions    extensions;
+    VkPhysicalDeviceProperties2 props;
+    VkPhysicalDeviceVulkan11Properties props_11;
+    VkPhysicalDeviceDriverProperties driver_props;
+    VkPhysicalDeviceMemoryProperties mprops;
+    VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops;
+    VkPhysicalDeviceDescriptorBufferPropertiesEXT desc_buf_props;
+    VkPhysicalDeviceSubgroupSizeControlProperties subgroup_props;
+    VkPhysicalDeviceCooperativeMatrixPropertiesKHR coop_matrix_props;
+    VkPhysicalDevicePushDescriptorPropertiesKHR push_desc_props;
+    VkPhysicalDeviceOpticalFlowPropertiesNV optical_flow_props;
+    VkQueueFamilyQueryResultStatusPropertiesKHR *query_props;
+    VkQueueFamilyVideoPropertiesKHR *video_props;
+    VkQueueFamilyProperties2 *qf_props;
+    int tot_nb_qfs;
+    VkPhysicalDeviceHostImageCopyPropertiesEXT host_image_props;
+    VkImageLayout *host_image_copy_layouts;
+
+    VkCooperativeMatrixPropertiesKHR *coop_mat_props;
+    uint32_t coop_mat_props_nb;
+
+    VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float_feats;
+    VkPhysicalDeviceVulkan12Features feats_12;
+    VkPhysicalDeviceFeatures2 feats;
+
+    AVBufferRef           *device_ref;
+    AVHWDeviceContext     *device;
+    AVVulkanDeviceContext *hwctx;
+
+    AVBufferRef           *input_frames_ref;
+    AVBufferRef           *frames_ref;
+    AVHWFramesContext     *frames;
+    AVVulkanFramesContext *hwfc;
+
+    uint32_t               qfs[64];
+    int                    nb_qfs;
+
+    /* Properties */
+    int                 output_width;
+    int                output_height;
+    enum AVPixelFormat output_format;
+    enum AVPixelFormat  input_format;
+} FFVulkanContext;
+
+static inline int ff_vk_count_images(AVVkFrame *f)
+{
+    int cnt = 0;
+    while (cnt < FF_ARRAY_ELEMS(f->img) && f->img[cnt])
+        cnt++;
+
+    return cnt;
+}
+
+static inline const void *ff_vk_find_struct(const void *chain, VkStructureType stype)
+{
+    const VkBaseInStructure *in = chain;
+    while (in) {
+        if (in->sType == stype)
+            return in;
+
+        in = in->pNext;
+    }
+
+    return NULL;
+}
+
+static inline void ff_vk_link_struct(void *chain, const void *in)
+{
+    VkBaseOutStructure *out = chain;
+    while (out->pNext)
+        out = out->pNext;
+
+    out->pNext = (void *)in;
+}
+
+#define FF_VK_STRUCT_EXT(CTX, BASE, STRUCT_P, EXT_FLAG, TYPE) \
+    do {                                                      \
+        if ((EXT_FLAG == FF_VK_EXT_NO_FLAG) ||                \
+            ((CTX)->extensions & EXT_FLAG)) {                 \
+            (STRUCT_P)->sType = TYPE;                         \
+            ff_vk_link_struct(BASE, STRUCT_P);                \
+        }                                                     \
+    } while (0)
+
+/* Identity mapping - r = r, b = b, g = g, a = a */
+extern const VkComponentMapping ff_comp_identity_map;
+
+/**
+ * Initializes the AVClass, in case this context is not used
+ * as the main user's context.
+ * May use either a frames context reference, or a device context reference.
+ */
+int ff_vk_init(FFVulkanContext *s, void *log_parent,
+               AVBufferRef *device_ref, AVBufferRef *frames_ref);
+
+/**
+ * Converts Vulkan return values to strings
+ */
+const char *ff_vk_ret2str(VkResult res);
+
+/**
+ * Map between usage and features.
+ */
+VkImageUsageFlags ff_vk_map_feats_to_usage(VkFormatFeatureFlagBits2 feats);
+VkFormatFeatureFlagBits2 ff_vk_map_usage_to_feats(VkImageUsageFlags usage);
+
+/**
+ * Returns 1 if pixfmt is a usable RGB format.
+ */
+int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt);
+
+/**
+ * Since storage images may not be swizzled, we have to do this in the
+ * shader itself. This fills in a lookup table to do it.
+ */
+void ff_vk_set_perm(enum AVPixelFormat pix_fmt, int lut[4], int inv);
+
+/**
+ * Get the aspect flag for a plane from an image.
+ */
+VkImageAspectFlags ff_vk_aspect_flag(AVFrame *f, int p);
+
+/**
+ * Returns the format to use for images in shaders.
+ */
+enum FFVkShaderRepFormat {
+    /* Native format with no conversion. May require casting. */
+    FF_VK_REP_NATIVE = 0,
+    /* Float conversion of the native format. */
+    FF_VK_REP_FLOAT,
+    /* Signed integer version of the native format */
+    FF_VK_REP_INT,
+    /* Unsigned integer version of the native format */
+    FF_VK_REP_UINT,
+};
+const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pix_fmt,
+                                 enum FFVkShaderRepFormat rep_fmt);
+
+/**
+ * Loads props/mprops/driver_props
+ */
+int ff_vk_load_props(FFVulkanContext *s);
+
+/**
+ * Chooses an appropriate QF.
+ */
+AVVulkanDeviceQueueFamily *ff_vk_qf_find(FFVulkanContext *s,
+                                         VkQueueFlagBits dev_family,
+                                         VkVideoCodecOperationFlagBitsKHR vid_ops);
+
+/**
+ * Allocates/frees an execution pool.
+ * If used in a multi-threaded context, there must be at least as many contexts
+ * as there are threads.
+ * ff_vk_exec_pool_init_desc() MUST be called if ff_vk_exec_descriptor_set_add()
+ * has been called.
+ */
+int ff_vk_exec_pool_init(FFVulkanContext *s, AVVulkanDeviceQueueFamily *qf,
+                         FFVkExecPool *pool, int nb_contexts,
+                         int nb_queries, VkQueryType query_type, int query_64bit,
+                         const void *query_create_pnext);
+void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool);
+
+/**
+ * Retrieve an execution pool. Threadsafe.
+ */
+FFVkExecContext *ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool);
+
+/**
+ * Performs nb_queries queries and returns their results and statuses.
+ * 64_BIT and WITH_STATUS flags are ignored as 64_BIT must be specified via
+ * query_64bit in ff_vk_exec_pool_init() and WITH_STATUS is always enabled.
+ */
+VkResult ff_vk_exec_get_query(FFVulkanContext *s, FFVkExecContext *e,
+                              void **data, VkQueryResultFlagBits flags);
+
+/**
+ * Start/submit/wait an execution.
+ * ff_vk_exec_start() always waits on a submission, so using ff_vk_exec_wait()
+ * is not necessary (unless using it is just better).
+ */
+int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e);
+int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e);
+void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e);
+
+/**
+ * Execution dependency management.
+ * Can attach buffers to executions that will only be unref'd once the
+ * buffer has finished executing.
+ * Adding a frame dep will *lock the frame*, until either the dependencies
+ * are discarded, the execution is submitted, or a failure happens.
+ * update_frame will update the frame's properties before it is unlocked,
+ * only if submission was successful.
+ */
+int ff_vk_exec_add_dep_buf(FFVulkanContext *s, FFVkExecContext *e,
+                           AVBufferRef **deps, int nb_deps, int ref);
+int ff_vk_exec_add_dep_wait_sem(FFVulkanContext *s, FFVkExecContext *e,
+                                VkSemaphore sem, uint64_t val,
+                                VkPipelineStageFlagBits2 stage);
+int ff_vk_exec_add_dep_bool_sem(FFVulkanContext *s, FFVkExecContext *e,
+                                VkSemaphore *sem, int nb,
+                                VkPipelineStageFlagBits2 stage,
+                                int wait); /* Ownership transferred if !wait */
+int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f,
+                             VkPipelineStageFlagBits2 wait_stage,
+                             VkPipelineStageFlagBits2 signal_stage);
+int ff_vk_exec_add_dep_sw_frame(FFVulkanContext *s, FFVkExecContext *e,
+                                AVFrame *f);
+void ff_vk_exec_update_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f,
+                             VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar);
+int ff_vk_exec_mirror_sem_value(FFVulkanContext *s, FFVkExecContext *e,
+                                VkSemaphore *dst, uint64_t *dst_val,
+                                AVFrame *f);
+void ff_vk_exec_discard_deps(FFVulkanContext *s, FFVkExecContext *e);
+
+/**
+ * Create a single imageview for a given plane.
+ */
+int ff_vk_create_imageview(FFVulkanContext *s,
+                           VkImageView *img_view, VkImageAspectFlags *aspect,
+                           AVFrame *f, int plane, enum FFVkShaderRepFormat rep_fmt);
+
+/**
+ * Create an imageview and add it as a dependency to an execution.
+ */
+int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e,
+                            VkImageView views[AV_NUM_DATA_POINTERS],
+                            AVFrame *f, enum FFVkShaderRepFormat rep_fmt);
+
+void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e,
+                         AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar,
+                         VkPipelineStageFlags src_stage,
+                         VkPipelineStageFlags dst_stage,
+                         VkAccessFlagBits     new_access,
+                         VkImageLayout        new_layout,
+                         uint32_t             new_qf);
+
+/**
+ * Memory/buffer/image allocation helpers.
+ */
+int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req,
+                    VkMemoryPropertyFlagBits req_flags, void *alloc_extension,
+                    VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem);
+int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size,
+                     void *pNext, void *alloc_pNext,
+                     VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags);
+
+/**
+ * Buffer management code.
+ */
+int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer **buf, uint8_t *mem[],
+                      int nb_buffers, int invalidate);
+int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers,
+                        int flush);
+
+static inline int ff_vk_map_buffer(FFVulkanContext *s, FFVkBuffer *buf, uint8_t **mem,
+                                   int invalidate)
+{
+    return ff_vk_map_buffers(s, (FFVkBuffer *[]){ buf }, mem,
+                             1, invalidate);
+}
+
+static inline int ff_vk_unmap_buffer(FFVulkanContext *s, FFVkBuffer *buf, int flush)
+{
+    return ff_vk_unmap_buffers(s, (FFVkBuffer *[]){ buf }, 1, flush);
+}
+
+void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf);
+
+/** Initialize a pool and create AVBufferRefs containing FFVkBuffer.
+ * Threadsafe to use. Buffers are automatically mapped on creation if
+ * VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT is set in mem_props. Users should
+ * synchronize access themselvesd. Mainly meant for device-local buffers. */
+int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVBufferPool **buf_pool,
+                            AVBufferRef **buf, VkBufferUsageFlags usage,
+                            void *create_pNext, size_t size,
+                            VkMemoryPropertyFlagBits mem_props);
+
+/** Maps a system RAM buffer into a Vulkan buffer.
+ * References the source buffer.
+ */
+int ff_vk_host_map_buffer(FFVulkanContext *s, AVBufferRef **dst,
+                          uint8_t *src_data, const AVBufferRef *src_buf,
+                          VkBufferUsageFlags usage);
+
+/**
+ * Create a sampler.
+ */
+int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler,
+                       int unnorm_coords, VkFilter filt);
+
+/**
+ * Initialize a shader object, with a specific set of extensions, type+bind,
+ * local group size, and subgroup requirements.
+ */
+int ff_vk_shader_init(FFVulkanContext *s, FFVulkanShader *shd, const char *name,
+                      VkPipelineStageFlags stage,
+                      const char *extensions[], int nb_extensions,
+                      int lg_x, int lg_y, int lg_z,
+                      uint32_t required_subgroup_size);
+
+/**
+ * Output the shader code as logging data, with a specific
+ * priority.
+ */
+void ff_vk_shader_print(void *ctx, FFVulkanShader *shd, int prio);
+
+/**
+ * Link a shader into an executable.
+ */
+int ff_vk_shader_link(FFVulkanContext *s, FFVulkanShader *shd,
+                      uint8_t *spirv, size_t spirv_len,
+                      const char *entrypoint);
+
+/**
+ * Add/update push constants for execution.
+ */
+int ff_vk_shader_add_push_const(FFVulkanShader *shd, int offset, int size,
+                                VkShaderStageFlagBits stage);
+
+/**
+ * Add descriptor to a shader. Must be called before shader init.
+ */
+int ff_vk_shader_add_descriptor_set(FFVulkanContext *s, FFVulkanShader *shd,
+                                    FFVulkanDescriptorSetBinding *desc, int nb,
+                                    int singular, int print_to_shader_only);
+
+/**
+ * Register a shader with an exec pool.
+ * Pool may be NULL if all descriptor sets are read-only.
+ */
+int ff_vk_shader_register_exec(FFVulkanContext *s, FFVkExecPool *pool,
+                               FFVulkanShader *shd);
+
+/**
+ * Bind a shader.
+ */
+void ff_vk_exec_bind_shader(FFVulkanContext *s, FFVkExecContext *e,
+                            FFVulkanShader *shd);
+
+/**
+ * Update push constant in a shader.
+ * Must be called before binding the shader.
+ */
+void ff_vk_shader_update_push_const(FFVulkanContext *s, FFVkExecContext *e,
+                                    FFVulkanShader *shd,
+                                    VkShaderStageFlagBits stage,
+                                    int offset, size_t size, void *src);
+
+/**
+ * Update a descriptor in a buffer with a buffer.
+ * Must be called before binding the shader.
+ */
+int ff_vk_shader_update_desc_buffer(FFVulkanContext *s, FFVkExecContext *e,
+                                    FFVulkanShader *shd,
+                                    int set, int bind, int elem,
+                                    FFVkBuffer *buf, VkDeviceSize offset, VkDeviceSize len,
+                                    VkFormat fmt);
+
+/**
+ * Sets an image descriptor for specified shader and binding.
+ */
+int ff_vk_shader_update_img(FFVulkanContext *s, FFVkExecContext *e,
+                            FFVulkanShader *shd, int set, int bind, int offs,
+                            VkImageView view, VkImageLayout layout,
+                            VkSampler sampler);
+
+/**
+ * Update a descriptor in a buffer with an image array..
+ * Must be called before binding the shader.
+ */
+void ff_vk_shader_update_img_array(FFVulkanContext *s, FFVkExecContext *e,
+                                   FFVulkanShader *shd, AVFrame *f,
+                                   VkImageView *views, int set, int binding,
+                                   VkImageLayout layout, VkSampler sampler);
+
+/**
+ * Free a shader.
+ */
+void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd);
+
+/**
+ * Frees main context.
+ */
+void ff_vk_uninit(FFVulkanContext *s);
+
+#endif /* AVUTIL_VULKAN_H */
-- 
2.49.1


From 012604071c97e873dec9a6548e271a6f07dbd73c Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:19:19 +0000
Subject: [PATCH 047/118] Changing vulkan file directory

---
 libavutil/vulkan_glslang.c | 308 -------------------------------------
 1 file changed, 308 deletions(-)
 delete mode 100644 libavutil/vulkan_glslang.c

diff --git a/libavutil/vulkan_glslang.c b/libavutil/vulkan_glslang.c
deleted file mode 100644
index 4cf54de854..0000000000
--- a/libavutil/vulkan_glslang.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <pthread.h>
-
-#include <glslang/build_info.h>
-#include <glslang/Include/glslang_c_interface.h>
-
-#include "vulkan_spirv.h"
-#include "libavutil/mem.h"
-#include "libavutil/avassert.h"
-
-static pthread_mutex_t glslc_mutex = PTHREAD_MUTEX_INITIALIZER;
-static int glslc_refcount = 0;
-
-static const glslang_resource_t glslc_resource_limits = {
-    .max_lights = 32,
-    .max_clip_planes = 6,
-    .max_texture_units = 32,
-    .max_texture_coords = 32,
-    .max_vertex_attribs = 64,
-    .max_vertex_uniform_components = 4096,
-    .max_varying_floats = 64,
-    .max_vertex_texture_image_units = 32,
-    .max_combined_texture_image_units = 80,
-    .max_texture_image_units = 32,
-    .max_fragment_uniform_components = 4096,
-    .max_draw_buffers = 32,
-    .max_vertex_uniform_vectors = 128,
-    .max_varying_vectors = 8,
-    .max_fragment_uniform_vectors = 16,
-    .max_vertex_output_vectors = 16,
-    .max_fragment_input_vectors = 15,
-    .min_program_texel_offset = -8,
-    .max_program_texel_offset = 7,
-    .max_clip_distances = 8,
-    .max_compute_work_group_count_x = 65535,
-    .max_compute_work_group_count_y = 65535,
-    .max_compute_work_group_count_z = 65535,
-    .max_compute_work_group_size_x = 1024,
-    .max_compute_work_group_size_y = 1024,
-    .max_compute_work_group_size_z = 64,
-    .max_compute_uniform_components = 1024,
-    .max_compute_texture_image_units = 16,
-    .max_compute_image_uniforms = 8,
-    .max_compute_atomic_counters = 8,
-    .max_compute_atomic_counter_buffers = 1,
-    .max_varying_components = 60,
-    .max_vertex_output_components = 64,
-    .max_geometry_input_components = 64,
-    .max_geometry_output_components = 128,
-    .max_fragment_input_components = 128,
-    .max_image_units = 8,
-    .max_combined_image_units_and_fragment_outputs = 8,
-    .max_combined_shader_output_resources = 8,
-    .max_image_samples = 0,
-    .max_vertex_image_uniforms = 0,
-    .max_tess_control_image_uniforms = 0,
-    .max_tess_evaluation_image_uniforms = 0,
-    .max_geometry_image_uniforms = 0,
-    .max_fragment_image_uniforms = 8,
-    .max_combined_image_uniforms = 8,
-    .max_geometry_texture_image_units = 16,
-    .max_geometry_output_vertices = 256,
-    .max_geometry_total_output_components = 1024,
-    .max_geometry_uniform_components = 1024,
-    .max_geometry_varying_components = 64,
-    .max_tess_control_input_components = 128,
-    .max_tess_control_output_components = 128,
-    .max_tess_control_texture_image_units = 16,
-    .max_tess_control_uniform_components = 1024,
-    .max_tess_control_total_output_components = 4096,
-    .max_tess_evaluation_input_components = 128,
-    .max_tess_evaluation_output_components = 128,
-    .max_tess_evaluation_texture_image_units = 16,
-    .max_tess_evaluation_uniform_components = 1024,
-    .max_tess_patch_components = 120,
-    .max_patch_vertices = 32,
-    .max_tess_gen_level = 64,
-    .max_viewports = 16,
-    .max_vertex_atomic_counters = 0,
-    .max_tess_control_atomic_counters = 0,
-    .max_tess_evaluation_atomic_counters = 0,
-    .max_geometry_atomic_counters = 0,
-    .max_fragment_atomic_counters = 8,
-    .max_combined_atomic_counters = 8,
-    .max_atomic_counter_bindings = 1,
-    .max_vertex_atomic_counter_buffers = 0,
-    .max_tess_control_atomic_counter_buffers = 0,
-    .max_tess_evaluation_atomic_counter_buffers = 0,
-    .max_geometry_atomic_counter_buffers = 0,
-    .max_fragment_atomic_counter_buffers = 1,
-    .max_combined_atomic_counter_buffers = 1,
-    .max_atomic_counter_buffer_size = 16384,
-    .max_transform_feedback_buffers = 4,
-    .max_transform_feedback_interleaved_components = 64,
-    .max_cull_distances = 8,
-    .max_combined_clip_and_cull_distances = 8,
-    .max_samples = 4,
-    .max_mesh_output_vertices_nv = 256,
-    .max_mesh_output_primitives_nv = 512,
-    .max_mesh_work_group_size_x_nv = 32,
-    .max_mesh_work_group_size_y_nv = 1,
-    .max_mesh_work_group_size_z_nv = 1,
-    .max_task_work_group_size_x_nv = 32,
-    .max_task_work_group_size_y_nv = 1,
-    .max_task_work_group_size_z_nv = 1,
-    .max_mesh_view_count_nv = 4,
-    .maxDualSourceDrawBuffersEXT = 1,
-
-    .limits = {
-        .non_inductive_for_loops = 1,
-        .while_loops = 1,
-        .do_while_loops = 1,
-        .general_uniform_indexing = 1,
-        .general_attribute_matrix_vector_indexing = 1,
-        .general_varying_indexing = 1,
-        .general_sampler_indexing = 1,
-        .general_variable_indexing = 1,
-        .general_constant_matrix_vector_indexing = 1,
-    }
-};
-
-static int glslc_shader_compile(FFVulkanContext *s, FFVkSPIRVCompiler *ctx,
-                                FFVulkanShader *shd, uint8_t **data,
-                                size_t *size, const char *entrypoint,
-                                void **opaque)
-{
-    const char *messages;
-    glslang_shader_t *glslc_shader;
-    glslang_program_t *glslc_program;
-
-    static const glslang_stage_t glslc_stage[] = {
-        [VK_SHADER_STAGE_VERTEX_BIT]   = GLSLANG_STAGE_VERTEX,
-        [VK_SHADER_STAGE_FRAGMENT_BIT] = GLSLANG_STAGE_FRAGMENT,
-        [VK_SHADER_STAGE_COMPUTE_BIT]  = GLSLANG_STAGE_COMPUTE,
-#if ((GLSLANG_VERSION_MAJOR) > 12)
-        [VK_SHADER_STAGE_TASK_BIT_EXT] = GLSLANG_STAGE_TASK,
-        [VK_SHADER_STAGE_MESH_BIT_EXT] = GLSLANG_STAGE_MESH,
-        [VK_SHADER_STAGE_RAYGEN_BIT_KHR] = GLSLANG_STAGE_RAYGEN,
-        [VK_SHADER_STAGE_INTERSECTION_BIT_KHR] = GLSLANG_STAGE_INTERSECT,
-        [VK_SHADER_STAGE_ANY_HIT_BIT_KHR] = GLSLANG_STAGE_ANYHIT,
-        [VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR] = GLSLANG_STAGE_CLOSESTHIT,
-        [VK_SHADER_STAGE_MISS_BIT_KHR] = GLSLANG_STAGE_MISS,
-        [VK_SHADER_STAGE_CALLABLE_BIT_KHR] = GLSLANG_STAGE_CALLABLE,
-#endif
-    };
-
-    const glslang_input_t glslc_input = {
-        .language                          = GLSLANG_SOURCE_GLSL,
-        .stage                             = glslc_stage[shd->stage],
-        .client                            = GLSLANG_CLIENT_VULKAN,
-#if ((GLSLANG_VERSION_MAJOR) >= 12)
-        .client_version                    = GLSLANG_TARGET_VULKAN_1_3,
-        .target_language_version           = GLSLANG_TARGET_SPV_1_6,
-#else
-        .client_version                    = GLSLANG_TARGET_VULKAN_1_2,
-        .target_language_version           = GLSLANG_TARGET_SPV_1_5,
-#endif
-        .target_language                   = GLSLANG_TARGET_SPV,
-        .code                              = shd->src.str,
-        .default_version                   = 460,
-        .default_profile                   = GLSLANG_NO_PROFILE,
-        .force_default_version_and_profile = false,
-        .forward_compatible                = false,
-        .messages                          = GLSLANG_MSG_DEFAULT_BIT,
-        .resource                          = &glslc_resource_limits,
-    };
-
-#if ((GLSLANG_VERSION_MAJOR) >= 12)
-    glslang_spv_options_t glslc_opts = {
-        .generate_debug_info = !!(s->extensions & (FF_VK_EXT_DEBUG_UTILS | FF_VK_EXT_RELAXED_EXTENDED_INSTR)),
-        .emit_nonsemantic_shader_debug_info = !!(s->extensions & FF_VK_EXT_RELAXED_EXTENDED_INSTR),
-        .emit_nonsemantic_shader_debug_source = !!(s->extensions & FF_VK_EXT_RELAXED_EXTENDED_INSTR),
-        .disable_optimizer = !!(s->extensions & FF_VK_EXT_DEBUG_UTILS),
-        .strip_debug_info = !(s->extensions & (FF_VK_EXT_DEBUG_UTILS | FF_VK_EXT_RELAXED_EXTENDED_INSTR)),
-        .optimize_size = 0,
-        .disassemble = 0,
-        .validate = 1,
-        /* .compile_only = 0, */
-    };
-#endif
-
-    av_assert0(glslc_refcount);
-
-    *opaque = NULL;
-
-    if (!(glslc_shader = glslang_shader_create(&glslc_input)))
-        return AVERROR(ENOMEM);
-
-    if (!glslang_shader_preprocess(glslc_shader, &glslc_input)) {
-        ff_vk_shader_print(s, shd, AV_LOG_WARNING);
-        av_log(s, AV_LOG_ERROR, "Unable to preprocess shader: %s (%s)!\n",
-               glslang_shader_get_info_log(glslc_shader),
-               glslang_shader_get_info_debug_log(glslc_shader));
-        glslang_shader_delete(glslc_shader);
-        return AVERROR(EINVAL);
-    }
-
-    if (!glslang_shader_parse(glslc_shader, &glslc_input)) {
-        ff_vk_shader_print(s, shd, AV_LOG_WARNING);
-        av_log(s, AV_LOG_ERROR, "Unable to parse shader: %s (%s)!\n",
-               glslang_shader_get_info_log(glslc_shader),
-               glslang_shader_get_info_debug_log(glslc_shader));
-        glslang_shader_delete(glslc_shader);
-        return AVERROR(EINVAL);
-    }
-
-    if (!(glslc_program = glslang_program_create())) {
-        glslang_shader_delete(glslc_shader);
-        return AVERROR(EINVAL);
-    }
-
-    glslang_program_add_shader(glslc_program, glslc_shader);
-
-    if (!glslang_program_link(glslc_program, GLSLANG_MSG_SPV_RULES_BIT |
-                                             GLSLANG_MSG_VULKAN_RULES_BIT)) {
-        ff_vk_shader_print(s, shd, AV_LOG_WARNING);
-        av_log(s, AV_LOG_ERROR, "Unable to link shader: %s (%s)!\n",
-               glslang_program_get_info_log(glslc_program),
-               glslang_program_get_info_debug_log(glslc_program));
-        glslang_program_delete(glslc_program);
-        glslang_shader_delete(glslc_shader);
-        return AVERROR(EINVAL);
-    }
-
-#if ((GLSLANG_VERSION_MAJOR) >= 12)
-    glslang_program_SPIRV_generate_with_options(glslc_program, glslc_input.stage, &glslc_opts);
-#else
-    glslang_program_SPIRV_generate(glslc_program, glslc_input.stage);
-#endif
-
-    messages = glslang_program_SPIRV_get_messages(glslc_program);
-    if (messages) {
-        ff_vk_shader_print(s, shd, AV_LOG_WARNING);
-        av_log(s, AV_LOG_WARNING, "%s\n", messages);
-    } else {
-        ff_vk_shader_print(s, shd, AV_LOG_TRACE);
-    }
-
-    glslang_shader_delete(glslc_shader);
-
-    *size = glslang_program_SPIRV_get_size(glslc_program) * sizeof(unsigned int);
-    *data = (void *)glslang_program_SPIRV_get_ptr(glslc_program);
-    *opaque = glslc_program;
-
-    return 0;
-}
-
-static void glslc_shader_free(FFVkSPIRVCompiler *ctx, void **opaque)
-{
-    if (!opaque || !*opaque)
-        return;
-
-    av_assert0(glslc_refcount);
-    glslang_program_delete(*opaque);
-    *opaque = NULL;
-}
-
-static void glslc_uninit(FFVkSPIRVCompiler **ctx)
-{
-    if (!ctx || !*ctx)
-        return;
-
-    pthread_mutex_lock(&glslc_mutex);
-    if (glslc_refcount && (--glslc_refcount == 0))
-        glslang_finalize_process();
-    pthread_mutex_unlock(&glslc_mutex);
-
-    av_freep(ctx);
-}
-
-FFVkSPIRVCompiler *ff_vk_glslang_init(void)
-{
-    FFVkSPIRVCompiler *ret = av_mallocz(sizeof(*ret));
-    if (!ret)
-        return NULL;
-
-    ret->compile_shader = glslc_shader_compile;
-    ret->free_shader    = glslc_shader_free;
-    ret->uninit         = glslc_uninit;
-
-    pthread_mutex_lock(&glslc_mutex);
-    if (!glslc_refcount++) {
-        if (!glslang_initialize_process()) {
-            av_freep(&ret);
-            glslc_refcount--;
-        }
-    }
-    pthread_mutex_unlock(&glslc_mutex);
-
-    return ret;
-}
-- 
2.49.1


From 191253f3cfe9e5bc7bb35b6a7eff0ce1a753d81d Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:19:43 +0000
Subject: [PATCH 048/118] Changing vulkan file directory

---
 libavutil/vulkan/vulkan_glslang.c | 308 ++++++++++++++++++++++++++++++
 1 file changed, 308 insertions(+)
 create mode 100644 libavutil/vulkan/vulkan_glslang.c

diff --git a/libavutil/vulkan/vulkan_glslang.c b/libavutil/vulkan/vulkan_glslang.c
new file mode 100644
index 0000000000..4cf54de854
--- /dev/null
+++ b/libavutil/vulkan/vulkan_glslang.c
@@ -0,0 +1,308 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <pthread.h>
+
+#include <glslang/build_info.h>
+#include <glslang/Include/glslang_c_interface.h>
+
+#include "vulkan_spirv.h"
+#include "libavutil/mem.h"
+#include "libavutil/avassert.h"
+
+static pthread_mutex_t glslc_mutex = PTHREAD_MUTEX_INITIALIZER;
+static int glslc_refcount = 0;
+
+static const glslang_resource_t glslc_resource_limits = {
+    .max_lights = 32,
+    .max_clip_planes = 6,
+    .max_texture_units = 32,
+    .max_texture_coords = 32,
+    .max_vertex_attribs = 64,
+    .max_vertex_uniform_components = 4096,
+    .max_varying_floats = 64,
+    .max_vertex_texture_image_units = 32,
+    .max_combined_texture_image_units = 80,
+    .max_texture_image_units = 32,
+    .max_fragment_uniform_components = 4096,
+    .max_draw_buffers = 32,
+    .max_vertex_uniform_vectors = 128,
+    .max_varying_vectors = 8,
+    .max_fragment_uniform_vectors = 16,
+    .max_vertex_output_vectors = 16,
+    .max_fragment_input_vectors = 15,
+    .min_program_texel_offset = -8,
+    .max_program_texel_offset = 7,
+    .max_clip_distances = 8,
+    .max_compute_work_group_count_x = 65535,
+    .max_compute_work_group_count_y = 65535,
+    .max_compute_work_group_count_z = 65535,
+    .max_compute_work_group_size_x = 1024,
+    .max_compute_work_group_size_y = 1024,
+    .max_compute_work_group_size_z = 64,
+    .max_compute_uniform_components = 1024,
+    .max_compute_texture_image_units = 16,
+    .max_compute_image_uniforms = 8,
+    .max_compute_atomic_counters = 8,
+    .max_compute_atomic_counter_buffers = 1,
+    .max_varying_components = 60,
+    .max_vertex_output_components = 64,
+    .max_geometry_input_components = 64,
+    .max_geometry_output_components = 128,
+    .max_fragment_input_components = 128,
+    .max_image_units = 8,
+    .max_combined_image_units_and_fragment_outputs = 8,
+    .max_combined_shader_output_resources = 8,
+    .max_image_samples = 0,
+    .max_vertex_image_uniforms = 0,
+    .max_tess_control_image_uniforms = 0,
+    .max_tess_evaluation_image_uniforms = 0,
+    .max_geometry_image_uniforms = 0,
+    .max_fragment_image_uniforms = 8,
+    .max_combined_image_uniforms = 8,
+    .max_geometry_texture_image_units = 16,
+    .max_geometry_output_vertices = 256,
+    .max_geometry_total_output_components = 1024,
+    .max_geometry_uniform_components = 1024,
+    .max_geometry_varying_components = 64,
+    .max_tess_control_input_components = 128,
+    .max_tess_control_output_components = 128,
+    .max_tess_control_texture_image_units = 16,
+    .max_tess_control_uniform_components = 1024,
+    .max_tess_control_total_output_components = 4096,
+    .max_tess_evaluation_input_components = 128,
+    .max_tess_evaluation_output_components = 128,
+    .max_tess_evaluation_texture_image_units = 16,
+    .max_tess_evaluation_uniform_components = 1024,
+    .max_tess_patch_components = 120,
+    .max_patch_vertices = 32,
+    .max_tess_gen_level = 64,
+    .max_viewports = 16,
+    .max_vertex_atomic_counters = 0,
+    .max_tess_control_atomic_counters = 0,
+    .max_tess_evaluation_atomic_counters = 0,
+    .max_geometry_atomic_counters = 0,
+    .max_fragment_atomic_counters = 8,
+    .max_combined_atomic_counters = 8,
+    .max_atomic_counter_bindings = 1,
+    .max_vertex_atomic_counter_buffers = 0,
+    .max_tess_control_atomic_counter_buffers = 0,
+    .max_tess_evaluation_atomic_counter_buffers = 0,
+    .max_geometry_atomic_counter_buffers = 0,
+    .max_fragment_atomic_counter_buffers = 1,
+    .max_combined_atomic_counter_buffers = 1,
+    .max_atomic_counter_buffer_size = 16384,
+    .max_transform_feedback_buffers = 4,
+    .max_transform_feedback_interleaved_components = 64,
+    .max_cull_distances = 8,
+    .max_combined_clip_and_cull_distances = 8,
+    .max_samples = 4,
+    .max_mesh_output_vertices_nv = 256,
+    .max_mesh_output_primitives_nv = 512,
+    .max_mesh_work_group_size_x_nv = 32,
+    .max_mesh_work_group_size_y_nv = 1,
+    .max_mesh_work_group_size_z_nv = 1,
+    .max_task_work_group_size_x_nv = 32,
+    .max_task_work_group_size_y_nv = 1,
+    .max_task_work_group_size_z_nv = 1,
+    .max_mesh_view_count_nv = 4,
+    .maxDualSourceDrawBuffersEXT = 1,
+
+    .limits = {
+        .non_inductive_for_loops = 1,
+        .while_loops = 1,
+        .do_while_loops = 1,
+        .general_uniform_indexing = 1,
+        .general_attribute_matrix_vector_indexing = 1,
+        .general_varying_indexing = 1,
+        .general_sampler_indexing = 1,
+        .general_variable_indexing = 1,
+        .general_constant_matrix_vector_indexing = 1,
+    }
+};
+
+static int glslc_shader_compile(FFVulkanContext *s, FFVkSPIRVCompiler *ctx,
+                                FFVulkanShader *shd, uint8_t **data,
+                                size_t *size, const char *entrypoint,
+                                void **opaque)
+{
+    const char *messages;
+    glslang_shader_t *glslc_shader;
+    glslang_program_t *glslc_program;
+
+    static const glslang_stage_t glslc_stage[] = {
+        [VK_SHADER_STAGE_VERTEX_BIT]   = GLSLANG_STAGE_VERTEX,
+        [VK_SHADER_STAGE_FRAGMENT_BIT] = GLSLANG_STAGE_FRAGMENT,
+        [VK_SHADER_STAGE_COMPUTE_BIT]  = GLSLANG_STAGE_COMPUTE,
+#if ((GLSLANG_VERSION_MAJOR) > 12)
+        [VK_SHADER_STAGE_TASK_BIT_EXT] = GLSLANG_STAGE_TASK,
+        [VK_SHADER_STAGE_MESH_BIT_EXT] = GLSLANG_STAGE_MESH,
+        [VK_SHADER_STAGE_RAYGEN_BIT_KHR] = GLSLANG_STAGE_RAYGEN,
+        [VK_SHADER_STAGE_INTERSECTION_BIT_KHR] = GLSLANG_STAGE_INTERSECT,
+        [VK_SHADER_STAGE_ANY_HIT_BIT_KHR] = GLSLANG_STAGE_ANYHIT,
+        [VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR] = GLSLANG_STAGE_CLOSESTHIT,
+        [VK_SHADER_STAGE_MISS_BIT_KHR] = GLSLANG_STAGE_MISS,
+        [VK_SHADER_STAGE_CALLABLE_BIT_KHR] = GLSLANG_STAGE_CALLABLE,
+#endif
+    };
+
+    const glslang_input_t glslc_input = {
+        .language                          = GLSLANG_SOURCE_GLSL,
+        .stage                             = glslc_stage[shd->stage],
+        .client                            = GLSLANG_CLIENT_VULKAN,
+#if ((GLSLANG_VERSION_MAJOR) >= 12)
+        .client_version                    = GLSLANG_TARGET_VULKAN_1_3,
+        .target_language_version           = GLSLANG_TARGET_SPV_1_6,
+#else
+        .client_version                    = GLSLANG_TARGET_VULKAN_1_2,
+        .target_language_version           = GLSLANG_TARGET_SPV_1_5,
+#endif
+        .target_language                   = GLSLANG_TARGET_SPV,
+        .code                              = shd->src.str,
+        .default_version                   = 460,
+        .default_profile                   = GLSLANG_NO_PROFILE,
+        .force_default_version_and_profile = false,
+        .forward_compatible                = false,
+        .messages                          = GLSLANG_MSG_DEFAULT_BIT,
+        .resource                          = &glslc_resource_limits,
+    };
+
+#if ((GLSLANG_VERSION_MAJOR) >= 12)
+    glslang_spv_options_t glslc_opts = {
+        .generate_debug_info = !!(s->extensions & (FF_VK_EXT_DEBUG_UTILS | FF_VK_EXT_RELAXED_EXTENDED_INSTR)),
+        .emit_nonsemantic_shader_debug_info = !!(s->extensions & FF_VK_EXT_RELAXED_EXTENDED_INSTR),
+        .emit_nonsemantic_shader_debug_source = !!(s->extensions & FF_VK_EXT_RELAXED_EXTENDED_INSTR),
+        .disable_optimizer = !!(s->extensions & FF_VK_EXT_DEBUG_UTILS),
+        .strip_debug_info = !(s->extensions & (FF_VK_EXT_DEBUG_UTILS | FF_VK_EXT_RELAXED_EXTENDED_INSTR)),
+        .optimize_size = 0,
+        .disassemble = 0,
+        .validate = 1,
+        /* .compile_only = 0, */
+    };
+#endif
+
+    av_assert0(glslc_refcount);
+
+    *opaque = NULL;
+
+    if (!(glslc_shader = glslang_shader_create(&glslc_input)))
+        return AVERROR(ENOMEM);
+
+    if (!glslang_shader_preprocess(glslc_shader, &glslc_input)) {
+        ff_vk_shader_print(s, shd, AV_LOG_WARNING);
+        av_log(s, AV_LOG_ERROR, "Unable to preprocess shader: %s (%s)!\n",
+               glslang_shader_get_info_log(glslc_shader),
+               glslang_shader_get_info_debug_log(glslc_shader));
+        glslang_shader_delete(glslc_shader);
+        return AVERROR(EINVAL);
+    }
+
+    if (!glslang_shader_parse(glslc_shader, &glslc_input)) {
+        ff_vk_shader_print(s, shd, AV_LOG_WARNING);
+        av_log(s, AV_LOG_ERROR, "Unable to parse shader: %s (%s)!\n",
+               glslang_shader_get_info_log(glslc_shader),
+               glslang_shader_get_info_debug_log(glslc_shader));
+        glslang_shader_delete(glslc_shader);
+        return AVERROR(EINVAL);
+    }
+
+    if (!(glslc_program = glslang_program_create())) {
+        glslang_shader_delete(glslc_shader);
+        return AVERROR(EINVAL);
+    }
+
+    glslang_program_add_shader(glslc_program, glslc_shader);
+
+    if (!glslang_program_link(glslc_program, GLSLANG_MSG_SPV_RULES_BIT |
+                                             GLSLANG_MSG_VULKAN_RULES_BIT)) {
+        ff_vk_shader_print(s, shd, AV_LOG_WARNING);
+        av_log(s, AV_LOG_ERROR, "Unable to link shader: %s (%s)!\n",
+               glslang_program_get_info_log(glslc_program),
+               glslang_program_get_info_debug_log(glslc_program));
+        glslang_program_delete(glslc_program);
+        glslang_shader_delete(glslc_shader);
+        return AVERROR(EINVAL);
+    }
+
+#if ((GLSLANG_VERSION_MAJOR) >= 12)
+    glslang_program_SPIRV_generate_with_options(glslc_program, glslc_input.stage, &glslc_opts);
+#else
+    glslang_program_SPIRV_generate(glslc_program, glslc_input.stage);
+#endif
+
+    messages = glslang_program_SPIRV_get_messages(glslc_program);
+    if (messages) {
+        ff_vk_shader_print(s, shd, AV_LOG_WARNING);
+        av_log(s, AV_LOG_WARNING, "%s\n", messages);
+    } else {
+        ff_vk_shader_print(s, shd, AV_LOG_TRACE);
+    }
+
+    glslang_shader_delete(glslc_shader);
+
+    *size = glslang_program_SPIRV_get_size(glslc_program) * sizeof(unsigned int);
+    *data = (void *)glslang_program_SPIRV_get_ptr(glslc_program);
+    *opaque = glslc_program;
+
+    return 0;
+}
+
+static void glslc_shader_free(FFVkSPIRVCompiler *ctx, void **opaque)
+{
+    if (!opaque || !*opaque)
+        return;
+
+    av_assert0(glslc_refcount);
+    glslang_program_delete(*opaque);
+    *opaque = NULL;
+}
+
+static void glslc_uninit(FFVkSPIRVCompiler **ctx)
+{
+    if (!ctx || !*ctx)
+        return;
+
+    pthread_mutex_lock(&glslc_mutex);
+    if (glslc_refcount && (--glslc_refcount == 0))
+        glslang_finalize_process();
+    pthread_mutex_unlock(&glslc_mutex);
+
+    av_freep(ctx);
+}
+
+FFVkSPIRVCompiler *ff_vk_glslang_init(void)
+{
+    FFVkSPIRVCompiler *ret = av_mallocz(sizeof(*ret));
+    if (!ret)
+        return NULL;
+
+    ret->compile_shader = glslc_shader_compile;
+    ret->free_shader    = glslc_shader_free;
+    ret->uninit         = glslc_uninit;
+
+    pthread_mutex_lock(&glslc_mutex);
+    if (!glslc_refcount++) {
+        if (!glslang_initialize_process()) {
+            av_freep(&ret);
+            glslc_refcount--;
+        }
+    }
+    pthread_mutex_unlock(&glslc_mutex);
+
+    return ret;
+}
-- 
2.49.1


From 26619748f956a43131838999423772a32ce290a6 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:20:09 +0000
Subject: [PATCH 049/118] Changing vulkan file directory

---
 libavutil/vulkan_functions.h | 283 -----------------------------------
 1 file changed, 283 deletions(-)
 delete mode 100644 libavutil/vulkan_functions.h

diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h
deleted file mode 100644
index 4d20b7d806..0000000000
--- a/libavutil/vulkan_functions.h
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVUTIL_VULKAN_FUNCTIONS_H
-#define AVUTIL_VULKAN_FUNCTIONS_H
-
-#define VK_NO_PROTOTYPES
-#define VK_ENABLE_BETA_EXTENSIONS
-
-#include "hwcontext.h"
-#include "hwcontext_vulkan.h"
-
-/* An enum of bitflags for every optional extension we need */
-typedef uint64_t FFVulkanExtensions;
-
-/* NOTE: when adding new entries, make sure to update ff_vk_extensions_to_mask */
-#define FF_VK_EXT_EXTERNAL_DMABUF_MEMORY (1ULL <<  0) /* VK_EXT_external_memory_dma_buf */
-#define FF_VK_EXT_DRM_MODIFIER_FLAGS     (1ULL <<  1) /* VK_EXT_image_drm_format_modifier */
-#define FF_VK_EXT_EXTERNAL_FD_MEMORY     (1ULL <<  2) /* VK_KHR_external_memory_fd */
-#define FF_VK_EXT_EXTERNAL_FD_SEM        (1ULL <<  3) /* VK_KHR_external_semaphore_fd */
-#define FF_VK_EXT_EXTERNAL_HOST_MEMORY   (1ULL <<  4) /* VK_EXT_external_memory_host */
-#define FF_VK_EXT_DEBUG_UTILS            (1ULL <<  5) /* VK_EXT_debug_utils */
-
-#define FF_VK_EXT_EXTERNAL_WIN32_MEMORY  (1ULL <<  6) /* VK_KHR_external_memory_win32 */
-#define FF_VK_EXT_EXTERNAL_WIN32_SEM     (1ULL <<  7) /* VK_KHR_external_semaphore_win32 */
-
-#define FF_VK_EXT_DESCRIPTOR_BUFFER      (1ULL <<  8) /* VK_EXT_descriptor_buffer */
-#define FF_VK_EXT_DEVICE_DRM             (1ULL <<  9) /* VK_EXT_physical_device_drm */
-#define FF_VK_EXT_ATOMIC_FLOAT           (1ULL << 10) /* VK_EXT_shader_atomic_float */
-#define FF_VK_EXT_COOP_MATRIX            (1ULL << 11) /* VK_KHR_cooperative_matrix */
-#define FF_VK_EXT_OPTICAL_FLOW           (1ULL << 12) /* VK_NV_optical_flow */
-#define FF_VK_EXT_SHADER_OBJECT          (1ULL << 13) /* VK_EXT_shader_object */
-#define FF_VK_EXT_PUSH_DESCRIPTOR        (1ULL << 14) /* VK_KHR_push_descriptor */
-#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_host_image_copy */
-
-/* Video extensions */
-#define FF_VK_EXT_VIDEO_QUEUE            (1ULL << 36) /* VK_KHR_video_queue */
-#define FF_VK_EXT_VIDEO_MAINTENANCE_1    (1ULL << 37) /* VK_KHR_video_maintenance1 */
-#define FF_VK_EXT_VIDEO_MAINTENANCE_2    (1ULL << 38) /* VK_KHR_video_maintenance2 */
-
-#define FF_VK_EXT_VIDEO_DECODE_QUEUE     (1ULL << 40) /* VK_KHR_video_decode_queue */
-#define FF_VK_EXT_VIDEO_DECODE_H264      (1ULL << 41) /* VK_KHR_video_decode_h264 */
-#define FF_VK_EXT_VIDEO_DECODE_H265      (1ULL << 42) /* VK_KHR_video_decode_h265 */
-#define FF_VK_EXT_VIDEO_DECODE_VP9       (1ULL << 43) /* VK_KHR_video_decode_vp9 */
-#define FF_VK_EXT_VIDEO_DECODE_AV1       (1ULL << 44) /* VK_KHR_video_decode_av1 */
-
-#define FF_VK_EXT_VIDEO_ENCODE_QUEUE     (1ULL << 50) /* VK_KHR_video_encode_queue */
-#define FF_VK_EXT_VIDEO_ENCODE_H264      (1ULL << 51) /* VK_KHR_video_encode_h264 */
-#define FF_VK_EXT_VIDEO_ENCODE_H265      (1ULL << 52) /* VK_KHR_video_encode_h265 */
-#define FF_VK_EXT_VIDEO_ENCODE_AV1       (1ULL << 53) /* VK_KHR_video_encode_av1 */
-
-#define FF_VK_EXT_PORTABILITY_SUBSET     (1ULL << 62)
-#define FF_VK_EXT_NO_FLAG                (1ULL << 63)
-
-/* Macro containing every function that we utilize in our codebase */
-#define FN_LIST(MACRO)                                                                   \
-    /* Instance */                                                                       \
-    MACRO(0, 0, FF_VK_EXT_NO_FLAG,              EnumerateInstanceExtensionProperties)    \
-    MACRO(0, 0, FF_VK_EXT_NO_FLAG,              EnumerateInstanceLayerProperties)        \
-    MACRO(0, 0, FF_VK_EXT_NO_FLAG,              CreateInstance)                          \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              DestroyInstance)                         \
-                                                                                         \
-    /* Debug */                                                                          \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              CreateDebugUtilsMessengerEXT)            \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              DestroyDebugUtilsMessengerEXT)           \
-                                                                                         \
-    /* Device */                                                                         \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetDeviceProcAddr)                       \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              CreateDevice)                            \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceFeatures2)              \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceProperties)             \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceExternalSemaphoreProperties)          \
-    MACRO(1, 0, FF_VK_EXT_VIDEO_QUEUE,          GetPhysicalDeviceVideoCapabilitiesKHR)     \
-    MACRO(1, 0, FF_VK_EXT_VIDEO_QUEUE,          GetPhysicalDeviceVideoFormatPropertiesKHR) \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              DeviceWaitIdle)                          \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              DestroyDevice)                           \
-                                                                                         \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              EnumeratePhysicalDevices)                \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              EnumerateDeviceExtensionProperties)      \
-                                                                                         \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceProperties2)            \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceMemoryProperties)       \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceFormatProperties2)      \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceImageFormatProperties2) \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceQueueFamilyProperties)  \
-    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceQueueFamilyProperties2) \
-    MACRO(1, 0, FF_VK_EXT_COOP_MATRIX,          GetPhysicalDeviceCooperativeMatrixPropertiesKHR) \
-                                                                                         \
-    /* Command pool */                                                                   \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateCommandPool)                       \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyCommandPool)                      \
-                                                                                         \
-    /* Command buffer */                                                                 \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              AllocateCommandBuffers)                  \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              BeginCommandBuffer)                      \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              EndCommandBuffer)                        \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              FreeCommandBuffers)                      \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdDispatch)                             \
-                                                                                         \
-    /* Queue */                                                                          \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetDeviceQueue)                          \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              QueueSubmit)                             \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              QueueSubmit2)                              \
-                                                                                         \
-    /* Fences */                                                                         \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateFence)                             \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              WaitForFences)                           \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetFenceStatus)                                        \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              ResetFences)                             \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyFence)                            \
-                                                                                         \
-    /* Semaphores */                                                                     \
-    MACRO(1, 1, FF_VK_EXT_EXTERNAL_FD_SEM,      GetSemaphoreFdKHR)                       \
-    MACRO(1, 1, FF_VK_EXT_EXTERNAL_FD_SEM,      ImportSemaphoreFdKHR)                                  \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateSemaphore)                         \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              WaitSemaphores)                          \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroySemaphore)                        \
-                                                                                         \
-    /* Memory */                                                                         \
-    MACRO(1, 1, FF_VK_EXT_EXTERNAL_FD_MEMORY,   GetMemoryFdKHR)                          \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetMemoryFdPropertiesKHR)                \
-    MACRO(1, 1, FF_VK_EXT_EXTERNAL_HOST_MEMORY, GetMemoryHostPointerPropertiesEXT)       \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              AllocateMemory)                          \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              MapMemory)                               \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              FlushMappedMemoryRanges)                 \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              InvalidateMappedMemoryRanges)            \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              UnmapMemory)                             \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              FreeMemory)                              \
-                                                                                         \
-    /* Commands */                                                                       \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdBindDescriptorSets)                   \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdPushConstants)                        \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdBindPipeline)                         \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdPipelineBarrier)                      \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdCopyBufferToImage)                    \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdCopyImageToBuffer)                    \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdClearColorImage)                                    \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdCopyBuffer)                                         \
-                                                                                         \
-    /* Buffer */                                                                         \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetBufferMemoryRequirements2)            \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateBuffer)                            \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              BindBufferMemory)                        \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetBufferDeviceAddress)                    \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdFillBuffer)                             \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyBuffer)                           \
-                                                                                         \
-    /* Image */                                                                          \
-    MACRO(1, 1, FF_VK_EXT_DRM_MODIFIER_FLAGS,   GetImageDrmFormatModifierPropertiesEXT)  \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetImageMemoryRequirements2)             \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateImage)                             \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              BindImageMemory2)                        \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetImageSubresourceLayout)               \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyImage)                            \
-                                                                                         \
-    /* ImageView */                                                                      \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateImageView)                         \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyImageView)                        \
-                                                                                         \
-    /* DescriptorSet */                                                                  \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateDescriptorSetLayout)               \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              AllocateDescriptorSets)                  \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateDescriptorPool)                    \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyDescriptorPool)                   \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyDescriptorSetLayout)              \
-                                                                                         \
-    /* Descriptor buffers */                                                               \
-    MACRO(1, 1, FF_VK_EXT_DESCRIPTOR_BUFFER,    GetDescriptorSetLayoutSizeEXT)             \
-    MACRO(1, 1, FF_VK_EXT_DESCRIPTOR_BUFFER,    GetDescriptorSetLayoutBindingOffsetEXT)    \
-    MACRO(1, 1, FF_VK_EXT_DESCRIPTOR_BUFFER,    GetDescriptorEXT)                          \
-    MACRO(1, 1, FF_VK_EXT_DESCRIPTOR_BUFFER,    CmdBindDescriptorBuffersEXT)               \
-    MACRO(1, 1, FF_VK_EXT_DESCRIPTOR_BUFFER,    CmdSetDescriptorBufferOffsetsEXT)          \
-                                                                                           \
-    /* DescriptorUpdateTemplate */                                                       \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              UpdateDescriptorSetWithTemplate)         \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateDescriptorUpdateTemplate)          \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyDescriptorUpdateTemplate)         \
-                                                                                                       \
-    /* Descriptors */                                                                                  \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              UpdateDescriptorSets)                                  \
-    MACRO(1, 1, FF_VK_EXT_PUSH_DESCRIPTOR,      CmdPushDescriptorSetKHR)                               \
-                                                                                           \
-    /* Queries */                                                                          \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateQueryPool)                           \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetQueryPoolResults)                       \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              ResetQueryPool)                            \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdBeginQuery)                             \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdEndQuery)                               \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdResetQueryPool)                         \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyQueryPool)                          \
-                                                                                           \
-    /* 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)           \
-    MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE,          GetVideoSessionMemoryRequirementsKHR)      \
-    MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE,          BindVideoSessionMemoryKHR)                 \
-    MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE,          CmdBeginVideoCodingKHR)                    \
-    MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE,          CmdControlVideoCodingKHR)                  \
-    MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE,          CmdEndVideoCodingKHR)                      \
-    MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE,          DestroyVideoSessionParametersKHR)          \
-    MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE,          DestroyVideoSessionKHR)                    \
-                                                                                           \
-    /* Video decoding */                                                                   \
-    MACRO(1, 1, FF_VK_EXT_VIDEO_DECODE_QUEUE,   CmdDecodeVideoKHR)                         \
-                                                                                           \
-    /* Video encoding */                                                                   \
-    MACRO(1, 1, FF_VK_EXT_VIDEO_ENCODE_QUEUE,   CmdEncodeVideoKHR)                         \
-    MACRO(1, 1, FF_VK_EXT_VIDEO_ENCODE_QUEUE,   GetEncodedVideoSessionParametersKHR)       \
-    MACRO(1, 0, FF_VK_EXT_VIDEO_ENCODE_QUEUE,   GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR) \
-                                                                                         \
-    /* Pipeline */                                                                       \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreatePipelineLayout)                    \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyPipelineLayout)                   \
-                                                                                         \
-    /* PipelineLayout */                                                                 \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateComputePipelines)                  \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyPipeline)                         \
-                                                                                         \
-    /* Sampler */                                                                        \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateSamplerYcbcrConversion)              \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroySamplerYcbcrConversion)             \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateSampler)                           \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroySampler)                          \
-                                                                                           \
-    /* Optical flow */                                                                     \
-    MACRO(1, 1, FF_VK_EXT_OPTICAL_FLOW,         BindOpticalFlowSessionImageNV)             \
-    MACRO(1, 1, FF_VK_EXT_OPTICAL_FLOW,         CmdOpticalFlowExecuteNV)                   \
-    MACRO(1, 1, FF_VK_EXT_OPTICAL_FLOW,         CreateOpticalFlowSessionNV)                \
-    MACRO(1, 1, FF_VK_EXT_OPTICAL_FLOW,         DestroyOpticalFlowSessionNV)               \
-    MACRO(1, 0, FF_VK_EXT_OPTICAL_FLOW,         GetPhysicalDeviceOpticalFlowImageFormatsNV)\
-                                                                                         \
-    /* Shaders */                                                                        \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateShaderModule)                      \
-    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyShaderModule)                       \
-    MACRO(1, 1, FF_VK_EXT_SHADER_OBJECT,        CmdBindShadersEXT)                         \
-    MACRO(1, 1, FF_VK_EXT_SHADER_OBJECT,        CreateShadersEXT)                          \
-    MACRO(1, 1, FF_VK_EXT_SHADER_OBJECT,        DestroyShaderEXT)                          \
-    MACRO(1, 1, FF_VK_EXT_SHADER_OBJECT,        GetShaderBinaryDataEXT)
-
-/* Macro containing every win32 specific function that we utilize in our codebase */
-#define FN_LIST_WIN32(MACRO)                                                             \
-    MACRO(1, 1, FF_VK_EXT_EXTERNAL_WIN32_SEM,    GetSemaphoreWin32HandleKHR)             \
-    MACRO(1, 1, FF_VK_EXT_EXTERNAL_WIN32_MEMORY, GetMemoryWin32HandleKHR)
-
-/* Macro to turn a function name into a definition */
-#define PFN_DEF(req_inst, req_dev, ext_flag, name) \
-    PFN_vk##name name;
-
-/* Structure with the definition of all listed functions */
-typedef struct FFVulkanFunctions {
-    FN_LIST(PFN_DEF)
-#ifdef _WIN32
-    FN_LIST_WIN32(PFN_DEF)
-#endif
-} FFVulkanFunctions;
-
-#endif /* AVUTIL_VULKAN_FUNCTIONS_H */
-- 
2.49.1


From f59ede45385c6e962bb2eb42271160c38c033593 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:20:32 +0000
Subject: [PATCH 050/118] Changing vulkan file directory

---
 libavutil/vulkan/vulkan_functions.h | 283 ++++++++++++++++++++++++++++
 1 file changed, 283 insertions(+)
 create mode 100644 libavutil/vulkan/vulkan_functions.h

diff --git a/libavutil/vulkan/vulkan_functions.h b/libavutil/vulkan/vulkan_functions.h
new file mode 100644
index 0000000000..2872e813e3
--- /dev/null
+++ b/libavutil/vulkan/vulkan_functions.h
@@ -0,0 +1,283 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_VULKAN_FUNCTIONS_H
+#define AVUTIL_VULKAN_FUNCTIONS_H
+
+#define VK_NO_PROTOTYPES
+#define VK_ENABLE_BETA_EXTENSIONS
+
+#include "libavutil/hwcontext.h"
+#include "hwcontext_vulkan.h"
+
+/* An enum of bitflags for every optional extension we need */
+typedef uint64_t FFVulkanExtensions;
+
+/* NOTE: when adding new entries, make sure to update ff_vk_extensions_to_mask */
+#define FF_VK_EXT_EXTERNAL_DMABUF_MEMORY (1ULL <<  0) /* VK_EXT_external_memory_dma_buf */
+#define FF_VK_EXT_DRM_MODIFIER_FLAGS     (1ULL <<  1) /* VK_EXT_image_drm_format_modifier */
+#define FF_VK_EXT_EXTERNAL_FD_MEMORY     (1ULL <<  2) /* VK_KHR_external_memory_fd */
+#define FF_VK_EXT_EXTERNAL_FD_SEM        (1ULL <<  3) /* VK_KHR_external_semaphore_fd */
+#define FF_VK_EXT_EXTERNAL_HOST_MEMORY   (1ULL <<  4) /* VK_EXT_external_memory_host */
+#define FF_VK_EXT_DEBUG_UTILS            (1ULL <<  5) /* VK_EXT_debug_utils */
+
+#define FF_VK_EXT_EXTERNAL_WIN32_MEMORY  (1ULL <<  6) /* VK_KHR_external_memory_win32 */
+#define FF_VK_EXT_EXTERNAL_WIN32_SEM     (1ULL <<  7) /* VK_KHR_external_semaphore_win32 */
+
+#define FF_VK_EXT_DESCRIPTOR_BUFFER      (1ULL <<  8) /* VK_EXT_descriptor_buffer */
+#define FF_VK_EXT_DEVICE_DRM             (1ULL <<  9) /* VK_EXT_physical_device_drm */
+#define FF_VK_EXT_ATOMIC_FLOAT           (1ULL << 10) /* VK_EXT_shader_atomic_float */
+#define FF_VK_EXT_COOP_MATRIX            (1ULL << 11) /* VK_KHR_cooperative_matrix */
+#define FF_VK_EXT_OPTICAL_FLOW           (1ULL << 12) /* VK_NV_optical_flow */
+#define FF_VK_EXT_SHADER_OBJECT          (1ULL << 13) /* VK_EXT_shader_object */
+#define FF_VK_EXT_PUSH_DESCRIPTOR        (1ULL << 14) /* VK_KHR_push_descriptor */
+#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_host_image_copy */
+
+/* Video extensions */
+#define FF_VK_EXT_VIDEO_QUEUE            (1ULL << 36) /* VK_KHR_video_queue */
+#define FF_VK_EXT_VIDEO_MAINTENANCE_1    (1ULL << 37) /* VK_KHR_video_maintenance1 */
+#define FF_VK_EXT_VIDEO_MAINTENANCE_2    (1ULL << 38) /* VK_KHR_video_maintenance2 */
+
+#define FF_VK_EXT_VIDEO_DECODE_QUEUE     (1ULL << 40) /* VK_KHR_video_decode_queue */
+#define FF_VK_EXT_VIDEO_DECODE_H264      (1ULL << 41) /* VK_KHR_video_decode_h264 */
+#define FF_VK_EXT_VIDEO_DECODE_H265      (1ULL << 42) /* VK_KHR_video_decode_h265 */
+#define FF_VK_EXT_VIDEO_DECODE_VP9       (1ULL << 43) /* VK_KHR_video_decode_vp9 */
+#define FF_VK_EXT_VIDEO_DECODE_AV1       (1ULL << 44) /* VK_KHR_video_decode_av1 */
+
+#define FF_VK_EXT_VIDEO_ENCODE_QUEUE     (1ULL << 50) /* VK_KHR_video_encode_queue */
+#define FF_VK_EXT_VIDEO_ENCODE_H264      (1ULL << 51) /* VK_KHR_video_encode_h264 */
+#define FF_VK_EXT_VIDEO_ENCODE_H265      (1ULL << 52) /* VK_KHR_video_encode_h265 */
+#define FF_VK_EXT_VIDEO_ENCODE_AV1       (1ULL << 53) /* VK_KHR_video_encode_av1 */
+
+#define FF_VK_EXT_PORTABILITY_SUBSET     (1ULL << 62)
+#define FF_VK_EXT_NO_FLAG                (1ULL << 63)
+
+/* Macro containing every function that we utilize in our codebase */
+#define FN_LIST(MACRO)                                                                   \
+    /* Instance */                                                                       \
+    MACRO(0, 0, FF_VK_EXT_NO_FLAG,              EnumerateInstanceExtensionProperties)    \
+    MACRO(0, 0, FF_VK_EXT_NO_FLAG,              EnumerateInstanceLayerProperties)        \
+    MACRO(0, 0, FF_VK_EXT_NO_FLAG,              CreateInstance)                          \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              DestroyInstance)                         \
+                                                                                         \
+    /* Debug */                                                                          \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              CreateDebugUtilsMessengerEXT)            \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              DestroyDebugUtilsMessengerEXT)           \
+                                                                                         \
+    /* Device */                                                                         \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetDeviceProcAddr)                       \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              CreateDevice)                            \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceFeatures2)              \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceProperties)             \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceExternalSemaphoreProperties)          \
+    MACRO(1, 0, FF_VK_EXT_VIDEO_QUEUE,          GetPhysicalDeviceVideoCapabilitiesKHR)     \
+    MACRO(1, 0, FF_VK_EXT_VIDEO_QUEUE,          GetPhysicalDeviceVideoFormatPropertiesKHR) \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              DeviceWaitIdle)                          \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              DestroyDevice)                           \
+                                                                                         \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              EnumeratePhysicalDevices)                \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              EnumerateDeviceExtensionProperties)      \
+                                                                                         \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceProperties2)            \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceMemoryProperties)       \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceFormatProperties2)      \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceImageFormatProperties2) \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceQueueFamilyProperties)  \
+    MACRO(1, 0, FF_VK_EXT_NO_FLAG,              GetPhysicalDeviceQueueFamilyProperties2) \
+    MACRO(1, 0, FF_VK_EXT_COOP_MATRIX,          GetPhysicalDeviceCooperativeMatrixPropertiesKHR) \
+                                                                                         \
+    /* Command pool */                                                                   \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateCommandPool)                       \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyCommandPool)                      \
+                                                                                         \
+    /* Command buffer */                                                                 \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              AllocateCommandBuffers)                  \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              BeginCommandBuffer)                      \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              EndCommandBuffer)                        \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              FreeCommandBuffers)                      \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdDispatch)                             \
+                                                                                         \
+    /* Queue */                                                                          \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetDeviceQueue)                          \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              QueueSubmit)                             \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              QueueSubmit2)                              \
+                                                                                         \
+    /* Fences */                                                                         \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateFence)                             \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              WaitForFences)                           \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetFenceStatus)                                        \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              ResetFences)                             \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyFence)                            \
+                                                                                         \
+    /* Semaphores */                                                                     \
+    MACRO(1, 1, FF_VK_EXT_EXTERNAL_FD_SEM,      GetSemaphoreFdKHR)                       \
+    MACRO(1, 1, FF_VK_EXT_EXTERNAL_FD_SEM,      ImportSemaphoreFdKHR)                                  \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateSemaphore)                         \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              WaitSemaphores)                          \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroySemaphore)                        \
+                                                                                         \
+    /* Memory */                                                                         \
+    MACRO(1, 1, FF_VK_EXT_EXTERNAL_FD_MEMORY,   GetMemoryFdKHR)                          \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetMemoryFdPropertiesKHR)                \
+    MACRO(1, 1, FF_VK_EXT_EXTERNAL_HOST_MEMORY, GetMemoryHostPointerPropertiesEXT)       \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              AllocateMemory)                          \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              MapMemory)                               \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              FlushMappedMemoryRanges)                 \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              InvalidateMappedMemoryRanges)            \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              UnmapMemory)                             \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              FreeMemory)                              \
+                                                                                         \
+    /* Commands */                                                                       \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdBindDescriptorSets)                   \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdPushConstants)                        \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdBindPipeline)                         \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdPipelineBarrier)                      \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdCopyBufferToImage)                    \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdCopyImageToBuffer)                    \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdClearColorImage)                                    \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdCopyBuffer)                                         \
+                                                                                         \
+    /* Buffer */                                                                         \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetBufferMemoryRequirements2)            \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateBuffer)                            \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              BindBufferMemory)                        \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetBufferDeviceAddress)                    \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdFillBuffer)                             \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyBuffer)                           \
+                                                                                         \
+    /* Image */                                                                          \
+    MACRO(1, 1, FF_VK_EXT_DRM_MODIFIER_FLAGS,   GetImageDrmFormatModifierPropertiesEXT)  \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetImageMemoryRequirements2)             \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateImage)                             \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              BindImageMemory2)                        \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetImageSubresourceLayout)               \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyImage)                            \
+                                                                                         \
+    /* ImageView */                                                                      \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateImageView)                         \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyImageView)                        \
+                                                                                         \
+    /* DescriptorSet */                                                                  \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateDescriptorSetLayout)               \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              AllocateDescriptorSets)                  \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateDescriptorPool)                    \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyDescriptorPool)                   \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyDescriptorSetLayout)              \
+                                                                                         \
+    /* Descriptor buffers */                                                               \
+    MACRO(1, 1, FF_VK_EXT_DESCRIPTOR_BUFFER,    GetDescriptorSetLayoutSizeEXT)             \
+    MACRO(1, 1, FF_VK_EXT_DESCRIPTOR_BUFFER,    GetDescriptorSetLayoutBindingOffsetEXT)    \
+    MACRO(1, 1, FF_VK_EXT_DESCRIPTOR_BUFFER,    GetDescriptorEXT)                          \
+    MACRO(1, 1, FF_VK_EXT_DESCRIPTOR_BUFFER,    CmdBindDescriptorBuffersEXT)               \
+    MACRO(1, 1, FF_VK_EXT_DESCRIPTOR_BUFFER,    CmdSetDescriptorBufferOffsetsEXT)          \
+                                                                                           \
+    /* DescriptorUpdateTemplate */                                                       \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              UpdateDescriptorSetWithTemplate)         \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateDescriptorUpdateTemplate)          \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyDescriptorUpdateTemplate)         \
+                                                                                                       \
+    /* Descriptors */                                                                                  \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              UpdateDescriptorSets)                                  \
+    MACRO(1, 1, FF_VK_EXT_PUSH_DESCRIPTOR,      CmdPushDescriptorSetKHR)                               \
+                                                                                           \
+    /* Queries */                                                                          \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateQueryPool)                           \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              GetQueryPoolResults)                       \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              ResetQueryPool)                            \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdBeginQuery)                             \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdEndQuery)                               \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CmdResetQueryPool)                         \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyQueryPool)                          \
+                                                                                           \
+    /* 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)           \
+    MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE,          GetVideoSessionMemoryRequirementsKHR)      \
+    MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE,          BindVideoSessionMemoryKHR)                 \
+    MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE,          CmdBeginVideoCodingKHR)                    \
+    MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE,          CmdControlVideoCodingKHR)                  \
+    MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE,          CmdEndVideoCodingKHR)                      \
+    MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE,          DestroyVideoSessionParametersKHR)          \
+    MACRO(1, 1, FF_VK_EXT_VIDEO_QUEUE,          DestroyVideoSessionKHR)                    \
+                                                                                           \
+    /* Video decoding */                                                                   \
+    MACRO(1, 1, FF_VK_EXT_VIDEO_DECODE_QUEUE,   CmdDecodeVideoKHR)                         \
+                                                                                           \
+    /* Video encoding */                                                                   \
+    MACRO(1, 1, FF_VK_EXT_VIDEO_ENCODE_QUEUE,   CmdEncodeVideoKHR)                         \
+    MACRO(1, 1, FF_VK_EXT_VIDEO_ENCODE_QUEUE,   GetEncodedVideoSessionParametersKHR)       \
+    MACRO(1, 0, FF_VK_EXT_VIDEO_ENCODE_QUEUE,   GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR) \
+                                                                                         \
+    /* Pipeline */                                                                       \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreatePipelineLayout)                    \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyPipelineLayout)                   \
+                                                                                         \
+    /* PipelineLayout */                                                                 \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateComputePipelines)                  \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyPipeline)                         \
+                                                                                         \
+    /* Sampler */                                                                        \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateSamplerYcbcrConversion)              \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroySamplerYcbcrConversion)             \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateSampler)                           \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroySampler)                          \
+                                                                                           \
+    /* Optical flow */                                                                     \
+    MACRO(1, 1, FF_VK_EXT_OPTICAL_FLOW,         BindOpticalFlowSessionImageNV)             \
+    MACRO(1, 1, FF_VK_EXT_OPTICAL_FLOW,         CmdOpticalFlowExecuteNV)                   \
+    MACRO(1, 1, FF_VK_EXT_OPTICAL_FLOW,         CreateOpticalFlowSessionNV)                \
+    MACRO(1, 1, FF_VK_EXT_OPTICAL_FLOW,         DestroyOpticalFlowSessionNV)               \
+    MACRO(1, 0, FF_VK_EXT_OPTICAL_FLOW,         GetPhysicalDeviceOpticalFlowImageFormatsNV)\
+                                                                                         \
+    /* Shaders */                                                                        \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              CreateShaderModule)                      \
+    MACRO(1, 1, FF_VK_EXT_NO_FLAG,              DestroyShaderModule)                       \
+    MACRO(1, 1, FF_VK_EXT_SHADER_OBJECT,        CmdBindShadersEXT)                         \
+    MACRO(1, 1, FF_VK_EXT_SHADER_OBJECT,        CreateShadersEXT)                          \
+    MACRO(1, 1, FF_VK_EXT_SHADER_OBJECT,        DestroyShaderEXT)                          \
+    MACRO(1, 1, FF_VK_EXT_SHADER_OBJECT,        GetShaderBinaryDataEXT)
+
+/* Macro containing every win32 specific function that we utilize in our codebase */
+#define FN_LIST_WIN32(MACRO)                                                             \
+    MACRO(1, 1, FF_VK_EXT_EXTERNAL_WIN32_SEM,    GetSemaphoreWin32HandleKHR)             \
+    MACRO(1, 1, FF_VK_EXT_EXTERNAL_WIN32_MEMORY, GetMemoryWin32HandleKHR)
+
+/* Macro to turn a function name into a definition */
+#define PFN_DEF(req_inst, req_dev, ext_flag, name) \
+    PFN_vk##name name;
+
+/* Structure with the definition of all listed functions */
+typedef struct FFVulkanFunctions {
+    FN_LIST(PFN_DEF)
+#ifdef _WIN32
+    FN_LIST_WIN32(PFN_DEF)
+#endif
+} FFVulkanFunctions;
+
+#endif /* AVUTIL_VULKAN_FUNCTIONS_H */
-- 
2.49.1


From e94ad64fe640af98f32aebc1ebf9a84d997a8b78 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:20:52 +0000
Subject: [PATCH 051/118] Changing vulkan file directory

---
 libavutil/vulkan_shaderc.c | 144 -------------------------------------
 1 file changed, 144 deletions(-)
 delete mode 100644 libavutil/vulkan_shaderc.c

diff --git a/libavutil/vulkan_shaderc.c b/libavutil/vulkan_shaderc.c
deleted file mode 100644
index e563b642df..0000000000
--- a/libavutil/vulkan_shaderc.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <shaderc/shaderc.h>
-
-#include "libavutil/mem.h"
-#include "vulkan_spirv.h"
-
-static int shdc_shader_compile(FFVulkanContext *s, FFVkSPIRVCompiler *ctx,
-                               FFVulkanShader *shd, uint8_t **data,
-                               size_t *size, const char *entrypoint,
-                               void **opaque)
-{
-    int loglevel, err, warn, ret;
-    const char *status, *message;
-    shaderc_compilation_result_t res;
-    static const char *shdc_result[] = {
-        [shaderc_compilation_status_success]            = "success",
-        [shaderc_compilation_status_invalid_stage]      = "invalid stage",
-        [shaderc_compilation_status_compilation_error]  = "error",
-        [shaderc_compilation_status_internal_error]     = "internal error",
-        [shaderc_compilation_status_null_result_object] = "no result",
-        [shaderc_compilation_status_invalid_assembly]   = "invalid assembly",
-    };
-    static const shaderc_shader_kind shdc_kind[] = {
-        [VK_SHADER_STAGE_VERTEX_BIT]   = shaderc_glsl_vertex_shader,
-        [VK_SHADER_STAGE_FRAGMENT_BIT] = shaderc_glsl_fragment_shader,
-        [VK_SHADER_STAGE_COMPUTE_BIT]  = shaderc_glsl_compute_shader,
-        [VK_SHADER_STAGE_MESH_BIT_EXT] = shaderc_mesh_shader,
-        [VK_SHADER_STAGE_TASK_BIT_EXT] = shaderc_task_shader,
-        [VK_SHADER_STAGE_RAYGEN_BIT_KHR] = shaderc_raygen_shader,
-        [VK_SHADER_STAGE_ANY_HIT_BIT_KHR] = shaderc_anyhit_shader,
-        [VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR] = shaderc_closesthit_shader,
-        [VK_SHADER_STAGE_MISS_BIT_KHR] = shaderc_miss_shader,
-        [VK_SHADER_STAGE_INTERSECTION_BIT_KHR] = shaderc_intersection_shader,
-        [VK_SHADER_STAGE_CALLABLE_BIT_KHR] = shaderc_callable_shader,
-    };
-
-    shaderc_compile_options_t opts = shaderc_compile_options_initialize();
-    *opaque = NULL;
-    if (!opts)
-        return AVERROR(ENOMEM);
-
-    shaderc_compile_options_set_target_env(opts, shaderc_target_env_vulkan,
-                                           shaderc_env_version_vulkan_1_3);
-    shaderc_compile_options_set_target_spirv(opts, shaderc_spirv_version_1_6);
-
-    /* If either extension is set, turn on debug info */
-    if (s->extensions & (FF_VK_EXT_DEBUG_UTILS | FF_VK_EXT_RELAXED_EXTENDED_INSTR))
-        shaderc_compile_options_set_generate_debug_info(opts);
-
-    if (s->extensions & FF_VK_EXT_DEBUG_UTILS)
-        shaderc_compile_options_set_optimization_level(opts,
-                                                       shaderc_optimization_level_zero);
-    else
-        shaderc_compile_options_set_optimization_level(opts,
-                                                       shaderc_optimization_level_performance);
-
-    res = shaderc_compile_into_spv((shaderc_compiler_t)ctx->priv,
-                                   shd->src.str, strlen(shd->src.str),
-                                   shdc_kind[shd->stage],
-                                   shd->name, entrypoint, opts);
-    shaderc_compile_options_release(opts);
-
-    ret = shaderc_result_get_compilation_status(res);
-    err = shaderc_result_get_num_errors(res);
-    warn = shaderc_result_get_num_warnings(res);
-    message = shaderc_result_get_error_message(res);
-
-    if (ret != shaderc_compilation_status_success && !err)
-        err = 1;
-
-    loglevel = err ? AV_LOG_ERROR : warn ? AV_LOG_WARNING : AV_LOG_TRACE;
-
-    ff_vk_shader_print(s, shd, loglevel);
-    if (message && (err || warn))
-        av_log(s, loglevel, "%s\n", message);
-    status = ret < FF_ARRAY_ELEMS(shdc_result) ? shdc_result[ret] : "unknown";
-    av_log(s, loglevel, "shaderc compile status '%s' (%d errors, %d warnings)\n",
-           status, err, warn);
-
-    if (err > 0)
-        return AVERROR(EINVAL);
-
-    *data = (uint8_t *)shaderc_result_get_bytes(res);
-    *size = shaderc_result_get_length(res);
-    *opaque = res;
-
-    return 0;
-}
-
-static void shdc_shader_free(FFVkSPIRVCompiler *ctx, void **opaque)
-{
-    if (!opaque || !*opaque)
-        return;
-
-    shaderc_result_release((shaderc_compilation_result_t)*opaque);
-    *opaque = NULL;
-}
-
-static void shdc_uninit(FFVkSPIRVCompiler **ctx)
-{
-    FFVkSPIRVCompiler *s;
-
-    if (!ctx || !*ctx)
-        return;
-
-    s = *ctx;
-
-    shaderc_compiler_release((shaderc_compiler_t)s->priv);
-    av_freep(ctx);
-}
-
-FFVkSPIRVCompiler *ff_vk_shaderc_init(void)
-{
-    FFVkSPIRVCompiler *ret = av_mallocz(sizeof(*ret));
-    if (!ret)
-        return NULL;
-
-    ret->compile_shader = shdc_shader_compile;
-    ret->free_shader    = shdc_shader_free;
-    ret->uninit         = shdc_uninit;
-
-    ret->priv           = (void *)shaderc_compiler_initialize();
-    if (!ret->priv)
-        av_freep(&ret);
-
-    return ret;
-}
-- 
2.49.1


From 6db4f480449a581d1cb03fe6e37f6e84f9f39b91 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:21:17 +0000
Subject: [PATCH 052/118] Changing vulkan file directory

---
 libavutil/vulkan/vulkan_shaderc.c | 144 ++++++++++++++++++++++++++++++
 1 file changed, 144 insertions(+)
 create mode 100644 libavutil/vulkan/vulkan_shaderc.c

diff --git a/libavutil/vulkan/vulkan_shaderc.c b/libavutil/vulkan/vulkan_shaderc.c
new file mode 100644
index 0000000000..e563b642df
--- /dev/null
+++ b/libavutil/vulkan/vulkan_shaderc.c
@@ -0,0 +1,144 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <shaderc/shaderc.h>
+
+#include "libavutil/mem.h"
+#include "vulkan_spirv.h"
+
+static int shdc_shader_compile(FFVulkanContext *s, FFVkSPIRVCompiler *ctx,
+                               FFVulkanShader *shd, uint8_t **data,
+                               size_t *size, const char *entrypoint,
+                               void **opaque)
+{
+    int loglevel, err, warn, ret;
+    const char *status, *message;
+    shaderc_compilation_result_t res;
+    static const char *shdc_result[] = {
+        [shaderc_compilation_status_success]            = "success",
+        [shaderc_compilation_status_invalid_stage]      = "invalid stage",
+        [shaderc_compilation_status_compilation_error]  = "error",
+        [shaderc_compilation_status_internal_error]     = "internal error",
+        [shaderc_compilation_status_null_result_object] = "no result",
+        [shaderc_compilation_status_invalid_assembly]   = "invalid assembly",
+    };
+    static const shaderc_shader_kind shdc_kind[] = {
+        [VK_SHADER_STAGE_VERTEX_BIT]   = shaderc_glsl_vertex_shader,
+        [VK_SHADER_STAGE_FRAGMENT_BIT] = shaderc_glsl_fragment_shader,
+        [VK_SHADER_STAGE_COMPUTE_BIT]  = shaderc_glsl_compute_shader,
+        [VK_SHADER_STAGE_MESH_BIT_EXT] = shaderc_mesh_shader,
+        [VK_SHADER_STAGE_TASK_BIT_EXT] = shaderc_task_shader,
+        [VK_SHADER_STAGE_RAYGEN_BIT_KHR] = shaderc_raygen_shader,
+        [VK_SHADER_STAGE_ANY_HIT_BIT_KHR] = shaderc_anyhit_shader,
+        [VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR] = shaderc_closesthit_shader,
+        [VK_SHADER_STAGE_MISS_BIT_KHR] = shaderc_miss_shader,
+        [VK_SHADER_STAGE_INTERSECTION_BIT_KHR] = shaderc_intersection_shader,
+        [VK_SHADER_STAGE_CALLABLE_BIT_KHR] = shaderc_callable_shader,
+    };
+
+    shaderc_compile_options_t opts = shaderc_compile_options_initialize();
+    *opaque = NULL;
+    if (!opts)
+        return AVERROR(ENOMEM);
+
+    shaderc_compile_options_set_target_env(opts, shaderc_target_env_vulkan,
+                                           shaderc_env_version_vulkan_1_3);
+    shaderc_compile_options_set_target_spirv(opts, shaderc_spirv_version_1_6);
+
+    /* If either extension is set, turn on debug info */
+    if (s->extensions & (FF_VK_EXT_DEBUG_UTILS | FF_VK_EXT_RELAXED_EXTENDED_INSTR))
+        shaderc_compile_options_set_generate_debug_info(opts);
+
+    if (s->extensions & FF_VK_EXT_DEBUG_UTILS)
+        shaderc_compile_options_set_optimization_level(opts,
+                                                       shaderc_optimization_level_zero);
+    else
+        shaderc_compile_options_set_optimization_level(opts,
+                                                       shaderc_optimization_level_performance);
+
+    res = shaderc_compile_into_spv((shaderc_compiler_t)ctx->priv,
+                                   shd->src.str, strlen(shd->src.str),
+                                   shdc_kind[shd->stage],
+                                   shd->name, entrypoint, opts);
+    shaderc_compile_options_release(opts);
+
+    ret = shaderc_result_get_compilation_status(res);
+    err = shaderc_result_get_num_errors(res);
+    warn = shaderc_result_get_num_warnings(res);
+    message = shaderc_result_get_error_message(res);
+
+    if (ret != shaderc_compilation_status_success && !err)
+        err = 1;
+
+    loglevel = err ? AV_LOG_ERROR : warn ? AV_LOG_WARNING : AV_LOG_TRACE;
+
+    ff_vk_shader_print(s, shd, loglevel);
+    if (message && (err || warn))
+        av_log(s, loglevel, "%s\n", message);
+    status = ret < FF_ARRAY_ELEMS(shdc_result) ? shdc_result[ret] : "unknown";
+    av_log(s, loglevel, "shaderc compile status '%s' (%d errors, %d warnings)\n",
+           status, err, warn);
+
+    if (err > 0)
+        return AVERROR(EINVAL);
+
+    *data = (uint8_t *)shaderc_result_get_bytes(res);
+    *size = shaderc_result_get_length(res);
+    *opaque = res;
+
+    return 0;
+}
+
+static void shdc_shader_free(FFVkSPIRVCompiler *ctx, void **opaque)
+{
+    if (!opaque || !*opaque)
+        return;
+
+    shaderc_result_release((shaderc_compilation_result_t)*opaque);
+    *opaque = NULL;
+}
+
+static void shdc_uninit(FFVkSPIRVCompiler **ctx)
+{
+    FFVkSPIRVCompiler *s;
+
+    if (!ctx || !*ctx)
+        return;
+
+    s = *ctx;
+
+    shaderc_compiler_release((shaderc_compiler_t)s->priv);
+    av_freep(ctx);
+}
+
+FFVkSPIRVCompiler *ff_vk_shaderc_init(void)
+{
+    FFVkSPIRVCompiler *ret = av_mallocz(sizeof(*ret));
+    if (!ret)
+        return NULL;
+
+    ret->compile_shader = shdc_shader_compile;
+    ret->free_shader    = shdc_shader_free;
+    ret->uninit         = shdc_uninit;
+
+    ret->priv           = (void *)shaderc_compiler_initialize();
+    if (!ret->priv)
+        av_freep(&ret);
+
+    return ret;
+}
-- 
2.49.1


From e3bd7cc4a2f9b58a29f110664ff178a820879fac Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:21:39 +0000
Subject: [PATCH 053/118] Changing vulkan file directory

---
 libavutil/vulkan_loader.h | 189 --------------------------------------
 1 file changed, 189 deletions(-)
 delete mode 100644 libavutil/vulkan_loader.h

diff --git a/libavutil/vulkan_loader.h b/libavutil/vulkan_loader.h
deleted file mode 100644
index 3207511663..0000000000
--- a/libavutil/vulkan_loader.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVUTIL_VULKAN_LOADER_H
-#define AVUTIL_VULKAN_LOADER_H
-
-#include <stdio.h>
-
-#include "avassert.h"
-#include "vulkan_functions.h"
-
-/* Macro to turn a function name into a loader struct */
-#define PFN_LOAD_INFO(req_inst, req_dev, ext_flag, name) \
-    {                                                    \
-        req_inst,                                        \
-        req_dev,                                         \
-        offsetof(FFVulkanFunctions, name),               \
-        ext_flag,                                        \
-    },
-
-static inline uint64_t ff_vk_extensions_to_mask(const char * const *extensions,
-                                                int nb_extensions)
-{
-    static const struct ExtensionMap {
-        const char *name;
-        FFVulkanExtensions flag;
-    } extension_map[] = {
-        /* Instance extensions */
-        { VK_EXT_DEBUG_UTILS_EXTENSION_NAME,                         FF_VK_EXT_DEBUG_UTILS            },
-
-        /* Device extensions */
-#ifdef VK_KHR_shader_relaxed_extended_instruction
-        { VK_KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION_EXTENSION_NAME, FF_VK_EXT_RELAXED_EXTENDED_INSTR },
-#endif
-        { VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME,   FF_VK_EXT_EXTERNAL_DMABUF_MEMORY },
-        { VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, FF_VK_EXT_DRM_MODIFIER_FLAGS     },
-        { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,        FF_VK_EXT_EXTERNAL_FD_MEMORY     },
-        { VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,     FF_VK_EXT_EXTERNAL_FD_SEM        },
-        { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME,      FF_VK_EXT_EXTERNAL_HOST_MEMORY   },
-        { VK_EXT_DEBUG_UTILS_EXTENSION_NAME,               FF_VK_EXT_DEBUG_UTILS            },
-        { VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME,       FF_VK_EXT_DEVICE_DRM             },
-        { VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME,       FF_VK_EXT_ATOMIC_FLOAT           },
-        { VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME,        FF_VK_EXT_COOP_MATRIX            },
-        { 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    },
-#endif
-#ifdef _WIN32
-        { VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,     FF_VK_EXT_EXTERNAL_WIN32_MEMORY  },
-        { VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME,  FF_VK_EXT_EXTERNAL_WIN32_SEM     },
-#endif
-        { VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME,         FF_VK_EXT_DESCRIPTOR_BUFFER,     },
-        { VK_KHR_VIDEO_QUEUE_EXTENSION_NAME,               FF_VK_EXT_VIDEO_QUEUE            },
-        { VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME,        FF_VK_EXT_VIDEO_ENCODE_QUEUE     },
-        { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME,        FF_VK_EXT_VIDEO_DECODE_QUEUE     },
-        { VK_KHR_VIDEO_ENCODE_H264_EXTENSION_NAME,         FF_VK_EXT_VIDEO_ENCODE_H264      },
-        { VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME,         FF_VK_EXT_VIDEO_DECODE_H264      },
-        { VK_KHR_VIDEO_ENCODE_H265_EXTENSION_NAME,         FF_VK_EXT_VIDEO_ENCODE_H265      },
-        { VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME,         FF_VK_EXT_VIDEO_DECODE_H265      },
-#ifdef VK_KHR_video_decode_vp9
-        { VK_KHR_VIDEO_DECODE_VP9_EXTENSION_NAME,          FF_VK_EXT_VIDEO_DECODE_VP9       },
-#endif
-        { VK_KHR_VIDEO_DECODE_AV1_EXTENSION_NAME,          FF_VK_EXT_VIDEO_DECODE_AV1       },
-        { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME,           FF_VK_EXT_PUSH_DESCRIPTOR        },
-#ifdef VK_KHR_shader_expect_assume
-        { VK_KHR_SHADER_EXPECT_ASSUME_EXTENSION_NAME,      FF_VK_EXT_EXPECT_ASSUME          },
-#endif
-#ifdef VK_KHR_video_encode_av1
-        { VK_KHR_VIDEO_ENCODE_AV1_EXTENSION_NAME,          FF_VK_EXT_VIDEO_ENCODE_AV1       },
-#endif
-    };
-
-    FFVulkanExtensions mask = 0x0;
-
-    for (int i = 0; i < nb_extensions; i++) {
-        for (int j = 0; j < FF_ARRAY_ELEMS(extension_map); j++) {
-            if (!strcmp(extensions[i], extension_map[j].name)) {
-                mask |= extension_map[j].flag;
-                continue;
-            }
-        }
-    }
-
-    return mask;
-}
-
-/**
- * Function loader.
- * Vulkan function from scratch loading happens in 3 stages - the first one
- * is before any initialization has happened, and you have neither an instance
- * structure nor a device structure. At this stage, you can only get the bare
- * minimals to initialize an instance.
- * The second stage is when you have an instance. At this stage, you can
- * initialize a VkDevice, and have an idea of what extensions each device
- * supports.
- * Finally, in the third stage, you can proceed and load all core functions,
- * plus you can be sure that any extensions you've enabled during device
- * initialization will be available.
- */
-static inline int ff_vk_load_functions(AVHWDeviceContext *ctx,
-                                       FFVulkanFunctions *vk,
-                                       uint64_t extensions_mask,
-                                       int has_inst, int has_dev)
-{
-    AVVulkanDeviceContext *hwctx = ctx->hwctx;
-
-    static const struct FunctionLoadInfo {
-        char req_inst;
-        char req_dev;
-        uint16_t struct_offset;
-        FFVulkanExtensions ext_flag;
-    } vk_load_info[] = {
-        FN_LIST(PFN_LOAD_INFO)
-#ifdef _WIN32
-        FN_LIST_WIN32(PFN_LOAD_INFO)
-#endif
-    };
-    // Concatenate the names to avoid relocations. The resulting string
-    // will end with \0\0
-#define FUNC_NAME(req_inst, req_dev, ext_flag, name) "vk"#name"\0"
-    const char *name =
-        FN_LIST(FUNC_NAME)
-#ifdef _WIN32
-        FN_LIST_WIN32(FUNC_NAME)
-#endif
-    ;
-#undef FUNC_NAME
-
-    for (int i = 0; i < FF_ARRAY_ELEMS(vk_load_info); name += strlen(name) + 1, i++) {
-        const struct FunctionLoadInfo *load = &vk_load_info[i];
-        static const char extensions[][4] = { "", "EXT", "KHR" };
-        PFN_vkVoidFunction fn;
-
-        if (load->req_dev  && !has_dev)
-            continue;
-        if (load->req_inst && !has_inst)
-            continue;
-
-        for (int j = 0; j < FF_ARRAY_ELEMS(extensions); j++) {
-            char ext_name[128];
-            av_unused int n;
-
-            n = snprintf(ext_name, sizeof(ext_name), "%s%s", name, extensions[j]);
-            av_assert1(n < sizeof(ext_name));
-
-            if (load->req_dev)
-                fn = vk->GetDeviceProcAddr(hwctx->act_dev, ext_name);
-            else if (load->req_inst)
-                fn = hwctx->get_proc_addr(hwctx->inst, ext_name);
-            else
-                fn = hwctx->get_proc_addr(NULL, ext_name);
-
-            if (fn)
-                break;
-        }
-
-        if (!fn && ((extensions_mask &~ FF_VK_EXT_NO_FLAG) & load->ext_flag)) {
-            av_log(ctx, AV_LOG_ERROR, "Loader error, function \"%s\" indicated "
-                   "as supported, but got NULL function pointer!\n", name);
-            return AVERROR_EXTERNAL;
-        }
-
-        *(PFN_vkVoidFunction *)((uint8_t *)vk + load->struct_offset) = fn;
-    }
-    av_assert1(*name == '\0');
-
-    return 0;
-}
-
-#endif /* AVUTIL_VULKAN_LOADER_H */
-- 
2.49.1


From 65de1208860ccdeb016a365f60942aecb68b272b Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:22:07 +0000
Subject: [PATCH 054/118] Changing vulkan file directory

---
 libavutil/vulkan/vulkan_loader.h | 189 +++++++++++++++++++++++++++++++
 1 file changed, 189 insertions(+)
 create mode 100644 libavutil/vulkan/vulkan_loader.h

diff --git a/libavutil/vulkan/vulkan_loader.h b/libavutil/vulkan/vulkan_loader.h
new file mode 100644
index 0000000000..7d0f4bee3b
--- /dev/null
+++ b/libavutil/vulkan/vulkan_loader.h
@@ -0,0 +1,189 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_VULKAN_LOADER_H
+#define AVUTIL_VULKAN_LOADER_H
+
+#include <stdio.h>
+
+#include "libavutil/avassert.h"
+#include "vulkan_functions.h"
+
+/* Macro to turn a function name into a loader struct */
+#define PFN_LOAD_INFO(req_inst, req_dev, ext_flag, name) \
+    {                                                    \
+        req_inst,                                        \
+        req_dev,                                         \
+        offsetof(FFVulkanFunctions, name),               \
+        ext_flag,                                        \
+    },
+
+static inline uint64_t ff_vk_extensions_to_mask(const char * const *extensions,
+                                                int nb_extensions)
+{
+    static const struct ExtensionMap {
+        const char *name;
+        FFVulkanExtensions flag;
+    } extension_map[] = {
+        /* Instance extensions */
+        { VK_EXT_DEBUG_UTILS_EXTENSION_NAME,                         FF_VK_EXT_DEBUG_UTILS            },
+
+        /* Device extensions */
+#ifdef VK_KHR_shader_relaxed_extended_instruction
+        { VK_KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION_EXTENSION_NAME, FF_VK_EXT_RELAXED_EXTENDED_INSTR },
+#endif
+        { VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME,   FF_VK_EXT_EXTERNAL_DMABUF_MEMORY },
+        { VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, FF_VK_EXT_DRM_MODIFIER_FLAGS     },
+        { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,        FF_VK_EXT_EXTERNAL_FD_MEMORY     },
+        { VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,     FF_VK_EXT_EXTERNAL_FD_SEM        },
+        { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME,      FF_VK_EXT_EXTERNAL_HOST_MEMORY   },
+        { VK_EXT_DEBUG_UTILS_EXTENSION_NAME,               FF_VK_EXT_DEBUG_UTILS            },
+        { VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME,       FF_VK_EXT_DEVICE_DRM             },
+        { VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME,       FF_VK_EXT_ATOMIC_FLOAT           },
+        { VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME,        FF_VK_EXT_COOP_MATRIX            },
+        { 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    },
+#endif
+#ifdef _WIN32
+        { VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,     FF_VK_EXT_EXTERNAL_WIN32_MEMORY  },
+        { VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME,  FF_VK_EXT_EXTERNAL_WIN32_SEM     },
+#endif
+        { VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME,         FF_VK_EXT_DESCRIPTOR_BUFFER,     },
+        { VK_KHR_VIDEO_QUEUE_EXTENSION_NAME,               FF_VK_EXT_VIDEO_QUEUE            },
+        { VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME,        FF_VK_EXT_VIDEO_ENCODE_QUEUE     },
+        { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME,        FF_VK_EXT_VIDEO_DECODE_QUEUE     },
+        { VK_KHR_VIDEO_ENCODE_H264_EXTENSION_NAME,         FF_VK_EXT_VIDEO_ENCODE_H264      },
+        { VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME,         FF_VK_EXT_VIDEO_DECODE_H264      },
+        { VK_KHR_VIDEO_ENCODE_H265_EXTENSION_NAME,         FF_VK_EXT_VIDEO_ENCODE_H265      },
+        { VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME,         FF_VK_EXT_VIDEO_DECODE_H265      },
+#ifdef VK_KHR_video_decode_vp9
+        { VK_KHR_VIDEO_DECODE_VP9_EXTENSION_NAME,          FF_VK_EXT_VIDEO_DECODE_VP9       },
+#endif
+        { VK_KHR_VIDEO_DECODE_AV1_EXTENSION_NAME,          FF_VK_EXT_VIDEO_DECODE_AV1       },
+        { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME,           FF_VK_EXT_PUSH_DESCRIPTOR        },
+#ifdef VK_KHR_shader_expect_assume
+        { VK_KHR_SHADER_EXPECT_ASSUME_EXTENSION_NAME,      FF_VK_EXT_EXPECT_ASSUME          },
+#endif
+#ifdef VK_KHR_video_encode_av1
+        { VK_KHR_VIDEO_ENCODE_AV1_EXTENSION_NAME,          FF_VK_EXT_VIDEO_ENCODE_AV1       },
+#endif
+    };
+
+    FFVulkanExtensions mask = 0x0;
+
+    for (int i = 0; i < nb_extensions; i++) {
+        for (int j = 0; j < FF_ARRAY_ELEMS(extension_map); j++) {
+            if (!strcmp(extensions[i], extension_map[j].name)) {
+                mask |= extension_map[j].flag;
+                continue;
+            }
+        }
+    }
+
+    return mask;
+}
+
+/**
+ * Function loader.
+ * Vulkan function from scratch loading happens in 3 stages - the first one
+ * is before any initialization has happened, and you have neither an instance
+ * structure nor a device structure. At this stage, you can only get the bare
+ * minimals to initialize an instance.
+ * The second stage is when you have an instance. At this stage, you can
+ * initialize a VkDevice, and have an idea of what extensions each device
+ * supports.
+ * Finally, in the third stage, you can proceed and load all core functions,
+ * plus you can be sure that any extensions you've enabled during device
+ * initialization will be available.
+ */
+static inline int ff_vk_load_functions(AVHWDeviceContext *ctx,
+                                       FFVulkanFunctions *vk,
+                                       uint64_t extensions_mask,
+                                       int has_inst, int has_dev)
+{
+    AVVulkanDeviceContext *hwctx = ctx->hwctx;
+
+    static const struct FunctionLoadInfo {
+        char req_inst;
+        char req_dev;
+        uint16_t struct_offset;
+        FFVulkanExtensions ext_flag;
+    } vk_load_info[] = {
+        FN_LIST(PFN_LOAD_INFO)
+#ifdef _WIN32
+        FN_LIST_WIN32(PFN_LOAD_INFO)
+#endif
+    };
+    // Concatenate the names to avoid relocations. The resulting string
+    // will end with \0\0
+#define FUNC_NAME(req_inst, req_dev, ext_flag, name) "vk"#name"\0"
+    const char *name =
+        FN_LIST(FUNC_NAME)
+#ifdef _WIN32
+        FN_LIST_WIN32(FUNC_NAME)
+#endif
+    ;
+#undef FUNC_NAME
+
+    for (int i = 0; i < FF_ARRAY_ELEMS(vk_load_info); name += strlen(name) + 1, i++) {
+        const struct FunctionLoadInfo *load = &vk_load_info[i];
+        static const char extensions[][4] = { "", "EXT", "KHR" };
+        PFN_vkVoidFunction fn;
+
+        if (load->req_dev  && !has_dev)
+            continue;
+        if (load->req_inst && !has_inst)
+            continue;
+
+        for (int j = 0; j < FF_ARRAY_ELEMS(extensions); j++) {
+            char ext_name[128];
+            av_unused int n;
+
+            n = snprintf(ext_name, sizeof(ext_name), "%s%s", name, extensions[j]);
+            av_assert1(n < sizeof(ext_name));
+
+            if (load->req_dev)
+                fn = vk->GetDeviceProcAddr(hwctx->act_dev, ext_name);
+            else if (load->req_inst)
+                fn = hwctx->get_proc_addr(hwctx->inst, ext_name);
+            else
+                fn = hwctx->get_proc_addr(NULL, ext_name);
+
+            if (fn)
+                break;
+        }
+
+        if (!fn && ((extensions_mask &~ FF_VK_EXT_NO_FLAG) & load->ext_flag)) {
+            av_log(ctx, AV_LOG_ERROR, "Loader error, function \"%s\" indicated "
+                   "as supported, but got NULL function pointer!\n", name);
+            return AVERROR_EXTERNAL;
+        }
+
+        *(PFN_vkVoidFunction *)((uint8_t *)vk + load->struct_offset) = fn;
+    }
+    av_assert1(*name == '\0');
+
+    return 0;
+}
+
+#endif /* AVUTIL_VULKAN_LOADER_H */
-- 
2.49.1


From eeeedaf0a99b28f28fe9dc3fcf4d53da2f8a6768 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:22:46 +0000
Subject: [PATCH 055/118] Changing vulkan file directory

---
 libavutil/vulkan_spirv.h | 44 ----------------------------------------
 1 file changed, 44 deletions(-)
 delete mode 100644 libavutil/vulkan_spirv.h

diff --git a/libavutil/vulkan_spirv.h b/libavutil/vulkan_spirv.h
deleted file mode 100644
index c13b50f8e7..0000000000
--- a/libavutil/vulkan_spirv.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVUTIL_VULKAN_SPIRV_H
-#define AVUTIL_VULKAN_SPIRV_H
-
-#include "vulkan.h"
-
-#include "config.h"
-
-typedef struct FFVkSPIRVCompiler {
-    void *priv;
-    int (*compile_shader)(FFVulkanContext *s, struct FFVkSPIRVCompiler *ctx,
-                          FFVulkanShader *shd, uint8_t **data,
-                          size_t *size, const char *entrypoint, void **opaque);
-    void (*free_shader)(struct FFVkSPIRVCompiler *ctx, void **opaque);
-    void (*uninit)(struct FFVkSPIRVCompiler **ctx);
-} FFVkSPIRVCompiler;
-
-#if CONFIG_LIBGLSLANG
-FFVkSPIRVCompiler *ff_vk_glslang_init(void);
-#define ff_vk_spirv_init ff_vk_glslang_init
-#endif
-#if CONFIG_LIBSHADERC
-FFVkSPIRVCompiler *ff_vk_shaderc_init(void);
-#define ff_vk_spirv_init ff_vk_shaderc_init
-#endif
-
-#endif /* AVUTIL_VULKAN_H */
-- 
2.49.1


From 88912f077961397f1795b0204800d1af01c26831 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:23:12 +0000
Subject: [PATCH 056/118] Changing vulkan file directory

---
 libavutil/vulkan/vulkan_spirv.h | 44 +++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)
 create mode 100644 libavutil/vulkan/vulkan_spirv.h

diff --git a/libavutil/vulkan/vulkan_spirv.h b/libavutil/vulkan/vulkan_spirv.h
new file mode 100644
index 0000000000..7797ae4d79
--- /dev/null
+++ b/libavutil/vulkan/vulkan_spirv.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_VULKAN_SPIRV_H
+#define AVUTIL_VULKAN_SPIRV_H
+
+#include "vulkan.h"
+
+#include "libavutil/config.h"
+
+typedef struct FFVkSPIRVCompiler {
+    void *priv;
+    int (*compile_shader)(FFVulkanContext *s, struct FFVkSPIRVCompiler *ctx,
+                          FFVulkanShader *shd, uint8_t **data,
+                          size_t *size, const char *entrypoint, void **opaque);
+    void (*free_shader)(struct FFVkSPIRVCompiler *ctx, void **opaque);
+    void (*uninit)(struct FFVkSPIRVCompiler **ctx);
+} FFVkSPIRVCompiler;
+
+#if CONFIG_LIBGLSLANG
+FFVkSPIRVCompiler *ff_vk_glslang_init(void);
+#define ff_vk_spirv_init ff_vk_glslang_init
+#endif
+#if CONFIG_LIBSHADERC
+FFVkSPIRVCompiler *ff_vk_shaderc_init(void);
+#define ff_vk_spirv_init ff_vk_shaderc_init
+#endif
+
+#endif /* AVUTIL_VULKAN_H */
-- 
2.49.1


From f76c060e15f29cb8f328720ea613e24029f1925a Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:24:25 +0000
Subject: [PATCH 057/118] Changing vulkan file directory

---
 libavcodec/ffv1_vulkan.c | 123 ---------------------------------------
 1 file changed, 123 deletions(-)
 delete mode 100644 libavcodec/ffv1_vulkan.c

diff --git a/libavcodec/ffv1_vulkan.c b/libavcodec/ffv1_vulkan.c
deleted file mode 100644
index 6f49e2ebb1..0000000000
--- a/libavcodec/ffv1_vulkan.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2025 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "ffv1_vulkan.h"
-#include "libavutil/crc.h"
-
-int ff_ffv1_vk_update_state_transition_data(FFVulkanContext *s,
-                                            FFVkBuffer *vkb, FFV1Context *f)
-{
-    int err;
-    uint8_t *buf_mapped;
-
-    RET(ff_vk_map_buffer(s, vkb, &buf_mapped, 0));
-
-    for (int i = 1; i < 256; i++) {
-        buf_mapped[256 + i] = f->state_transition[i];
-        buf_mapped[256 - i] = 256 - (int)f->state_transition[i];
-    }
-
-    RET(ff_vk_unmap_buffer(s, vkb, 1));
-
-fail:
-    return err;
-}
-
-static int init_state_transition_data(FFVulkanContext *s,
-                                      FFVkBuffer *vkb, FFV1Context *f,
-                                      int (*write_data)(FFVulkanContext *s,
-                                                        FFVkBuffer *vkb, FFV1Context *f))
-{
-    int err;
-    size_t buf_len = 512*sizeof(uint8_t);
-
-    RET(ff_vk_create_buf(s, vkb,
-                         buf_len,
-                         NULL, NULL,
-                         VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
-                         VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
-                         VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
-                         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
-
-    write_data(s, vkb, f);
-
-fail:
-    return err;
-}
-
-int ff_ffv1_vk_init_state_transition_data(FFVulkanContext *s,
-                                          FFVkBuffer *vkb, FFV1Context *f)
-{
-    return init_state_transition_data(s, vkb, f,
-                                      ff_ffv1_vk_update_state_transition_data);
-}
-
-int ff_ffv1_vk_init_quant_table_data(FFVulkanContext *s,
-                                     FFVkBuffer *vkb, FFV1Context *f)
-{
-    int err;
-
-    int16_t *buf_mapped;
-    size_t buf_len = MAX_QUANT_TABLES*
-                     MAX_CONTEXT_INPUTS*
-                     MAX_QUANT_TABLE_SIZE*sizeof(int16_t);
-
-    RET(ff_vk_create_buf(s, vkb,
-                         buf_len,
-                         NULL, NULL,
-                         VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
-                         VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
-                         VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
-                         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
-    RET(ff_vk_map_buffer(s, vkb, (void *)&buf_mapped, 0));
-
-    memcpy(buf_mapped, f->quant_tables,
-           sizeof(f->quant_tables));
-
-    RET(ff_vk_unmap_buffer(s, vkb, 1));
-
-fail:
-    return err;
-}
-
-int ff_ffv1_vk_init_crc_table_data(FFVulkanContext *s,
-                                   FFVkBuffer *vkb, FFV1Context *f)
-{
-    int err;
-
-    uint32_t *buf_mapped;
-    size_t buf_len = 256*sizeof(int32_t);
-
-    RET(ff_vk_create_buf(s, vkb,
-                         buf_len,
-                         NULL, NULL,
-                         VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
-                         VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
-                         VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
-                         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
-    RET(ff_vk_map_buffer(s, vkb, (void *)&buf_mapped, 0));
-
-    memcpy(buf_mapped, av_crc_get_table(AV_CRC_32_IEEE), buf_len);
-
-    RET(ff_vk_unmap_buffer(s, vkb, 1));
-
-fail:
-    return err;
-}
-- 
2.49.1


From 57b1aa48e9fe9372b7198102a96ab46e474500ee Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:25:02 +0000
Subject: [PATCH 058/118] Changing vulkan file directory

---
 libavcodec/vulkan/ffv1_vulkan.c | 123 ++++++++++++++++++++++++++++++++
 1 file changed, 123 insertions(+)
 create mode 100644 libavcodec/vulkan/ffv1_vulkan.c

diff --git a/libavcodec/vulkan/ffv1_vulkan.c b/libavcodec/vulkan/ffv1_vulkan.c
new file mode 100644
index 0000000000..6f49e2ebb1
--- /dev/null
+++ b/libavcodec/vulkan/ffv1_vulkan.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2025 Lynne <dev@lynne.ee>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "ffv1_vulkan.h"
+#include "libavutil/crc.h"
+
+int ff_ffv1_vk_update_state_transition_data(FFVulkanContext *s,
+                                            FFVkBuffer *vkb, FFV1Context *f)
+{
+    int err;
+    uint8_t *buf_mapped;
+
+    RET(ff_vk_map_buffer(s, vkb, &buf_mapped, 0));
+
+    for (int i = 1; i < 256; i++) {
+        buf_mapped[256 + i] = f->state_transition[i];
+        buf_mapped[256 - i] = 256 - (int)f->state_transition[i];
+    }
+
+    RET(ff_vk_unmap_buffer(s, vkb, 1));
+
+fail:
+    return err;
+}
+
+static int init_state_transition_data(FFVulkanContext *s,
+                                      FFVkBuffer *vkb, FFV1Context *f,
+                                      int (*write_data)(FFVulkanContext *s,
+                                                        FFVkBuffer *vkb, FFV1Context *f))
+{
+    int err;
+    size_t buf_len = 512*sizeof(uint8_t);
+
+    RET(ff_vk_create_buf(s, vkb,
+                         buf_len,
+                         NULL, NULL,
+                         VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
+                         VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+                         VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+                         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
+
+    write_data(s, vkb, f);
+
+fail:
+    return err;
+}
+
+int ff_ffv1_vk_init_state_transition_data(FFVulkanContext *s,
+                                          FFVkBuffer *vkb, FFV1Context *f)
+{
+    return init_state_transition_data(s, vkb, f,
+                                      ff_ffv1_vk_update_state_transition_data);
+}
+
+int ff_ffv1_vk_init_quant_table_data(FFVulkanContext *s,
+                                     FFVkBuffer *vkb, FFV1Context *f)
+{
+    int err;
+
+    int16_t *buf_mapped;
+    size_t buf_len = MAX_QUANT_TABLES*
+                     MAX_CONTEXT_INPUTS*
+                     MAX_QUANT_TABLE_SIZE*sizeof(int16_t);
+
+    RET(ff_vk_create_buf(s, vkb,
+                         buf_len,
+                         NULL, NULL,
+                         VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
+                         VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+                         VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+                         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
+    RET(ff_vk_map_buffer(s, vkb, (void *)&buf_mapped, 0));
+
+    memcpy(buf_mapped, f->quant_tables,
+           sizeof(f->quant_tables));
+
+    RET(ff_vk_unmap_buffer(s, vkb, 1));
+
+fail:
+    return err;
+}
+
+int ff_ffv1_vk_init_crc_table_data(FFVulkanContext *s,
+                                   FFVkBuffer *vkb, FFV1Context *f)
+{
+    int err;
+
+    uint32_t *buf_mapped;
+    size_t buf_len = 256*sizeof(int32_t);
+
+    RET(ff_vk_create_buf(s, vkb,
+                         buf_len,
+                         NULL, NULL,
+                         VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
+                         VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+                         VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+                         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
+    RET(ff_vk_map_buffer(s, vkb, (void *)&buf_mapped, 0));
+
+    memcpy(buf_mapped, av_crc_get_table(AV_CRC_32_IEEE), buf_len);
+
+    RET(ff_vk_unmap_buffer(s, vkb, 1));
+
+fail:
+    return err;
+}
-- 
2.49.1


From b1f6c33c3e839daa20b777282a8502b660f61c12 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:25:28 +0000
Subject: [PATCH 059/118] Changing vulkan file directory

---
 libavcodec/ffv1enc_vulkan.c | 1848 -----------------------------------
 1 file changed, 1848 deletions(-)
 delete mode 100644 libavcodec/ffv1enc_vulkan.c

diff --git a/libavcodec/ffv1enc_vulkan.c b/libavcodec/ffv1enc_vulkan.c
deleted file mode 100644
index 259bc75d4c..0000000000
--- a/libavcodec/ffv1enc_vulkan.c
+++ /dev/null
@@ -1,1848 +0,0 @@
-/*
- * Copyright (c) 2024 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/mem.h"
-#include "libavutil/vulkan.h"
-#include "libavutil/vulkan_spirv.h"
-
-#include "avcodec.h"
-#include "internal.h"
-#include "hwconfig.h"
-#include "encode.h"
-#include "libavutil/opt.h"
-#include "codec_internal.h"
-
-#include "ffv1.h"
-#include "ffv1enc.h"
-#include "ffv1_vulkan.h"
-
-/* Parallel Golomb alignment */
-#define LG_ALIGN_W 32
-#define LG_ALIGN_H 32
-
-/* Unlike the decoder, we need 4 lines (but really only 3) */
-#define RGB_LINECACHE 4
-
-typedef struct VulkanEncodeFFv1FrameData {
-    /* Output data */
-    AVBufferRef *out_data_ref;
-
-    /* Results data */
-    AVBufferRef *results_data_ref;
-
-    /* Copied from the source */
-    int64_t pts;
-    int64_t duration;
-    void        *frame_opaque;
-    AVBufferRef *frame_opaque_ref;
-
-    int key_frame;
-} VulkanEncodeFFv1FrameData;
-
-typedef struct VulkanEncodeFFv1Context {
-    FFV1Context ctx;
-    AVFrame *frame;
-
-    FFVulkanContext s;
-    AVVulkanDeviceQueueFamily *qf;
-    FFVkExecPool exec_pool;
-
-    AVVulkanDeviceQueueFamily *transfer_qf;
-    FFVkExecPool transfer_exec_pool;
-
-    VkBufferCopy *buf_regions;
-    VulkanEncodeFFv1FrameData *exec_ctx_info;
-    int in_flight;
-    int async_depth;
-    size_t max_heap_size;
-
-    FFVulkanShader setup;
-    FFVulkanShader rct_search;
-    FFVulkanShader reset;
-    FFVulkanShader enc;
-
-    /* Constant read-only buffers */
-    FFVkBuffer quant_buf;
-    FFVkBuffer rangecoder_static_buf;
-    FFVkBuffer crc_tab_buf;
-
-    /* Slice data buffer pool */
-    AVBufferPool *slice_data_pool;
-    AVBufferRef *keyframe_slice_data_ref;
-
-    /* Output data buffer */
-    AVBufferPool *out_data_pool;
-
-    /* Slice results buffer */
-    AVBufferPool *results_data_pool;
-
-    /* Intermediate frame pool */
-    AVBufferRef *intermediate_frames_ref;
-
-    /* Representation mode */
-    enum FFVkShaderRepFormat rep_fmt;
-
-    int num_h_slices;
-    int num_v_slices;
-    int force_pcm;
-    int optimize_rct;
-
-    int is_rgb;
-    int ppi;
-    int chunks;
-} VulkanEncodeFFv1Context;
-
-extern const char *ff_source_common_comp;
-extern const char *ff_source_rangecoder_comp;
-extern const char *ff_source_ffv1_vlc_comp;
-extern const char *ff_source_ffv1_common_comp;
-extern const char *ff_source_ffv1_reset_comp;
-extern const char *ff_source_ffv1_rct_search_comp;
-extern const char *ff_source_ffv1_enc_setup_comp;
-extern const char *ff_source_ffv1_enc_comp;
-
-typedef struct FFv1VkParameters {
-    VkDeviceAddress slice_state;
-    VkDeviceAddress scratch_data;
-    VkDeviceAddress out_data;
-
-    int32_t fmt_lut[4];
-    int32_t sar[2];
-    uint32_t chroma_shift[2];
-
-    uint32_t plane_state_size;
-    uint32_t context_count;
-    uint32_t crcref;
-    uint32_t slice_size_max;
-    int      rct_offset;
-
-    uint8_t extend_lookup[8];
-    uint8_t bits_per_raw_sample;
-    uint8_t context_model;
-    uint8_t version;
-    uint8_t micro_version;
-    uint8_t force_pcm;
-    uint8_t key_frame;
-    uint8_t components;
-    uint8_t planes;
-    uint8_t codec_planes;
-    uint8_t planar_rgb;
-    uint8_t transparency;
-    uint8_t colorspace;
-    uint8_t pic_mode;
-    uint8_t ec;
-    uint8_t ppi;
-    uint8_t chunks;
-    uint8_t rct_search;
-    uint8_t padding[3];
-} FFv1VkParameters;
-
-static void add_push_data(FFVulkanShader *shd)
-{
-    GLSLC(0, layout(push_constant, scalar) uniform pushConstants {            );
-    GLSLC(1,    u8buf slice_state;                                            );
-    GLSLC(1,    u8buf scratch_data;                                           );
-    GLSLC(1,    u8buf out_data;                                               );
-    GLSLC(0,                                                                  );
-    GLSLC(1,    ivec4 fmt_lut;                                                );
-    GLSLC(1,    ivec2 sar;                                                    );
-    GLSLC(1,    uvec2 chroma_shift;                                           );
-    GLSLC(0,                                                                  );
-    GLSLC(1,    uint plane_state_size;                                        );
-    GLSLC(1,    uint context_count;                                           );
-    GLSLC(1,    uint32_t crcref;                                              );
-    GLSLC(1,    uint32_t slice_size_max;                                      );
-    GLSLC(1,    int rct_offset;                                               );
-    GLSLC(0,                                                                  );
-    GLSLC(1,    uint8_t extend_lookup[8];                                     );
-    GLSLC(1,    uint8_t bits_per_raw_sample;                                  );
-    GLSLC(1,    uint8_t context_model;                                        );
-    GLSLC(1,    uint8_t version;                                              );
-    GLSLC(1,    uint8_t micro_version;                                        );
-    GLSLC(1,    uint8_t force_pcm;                                            );
-    GLSLC(1,    uint8_t key_frame;                                            );
-    GLSLC(1,    uint8_t components;                                           );
-    GLSLC(1,    uint8_t planes;                                               );
-    GLSLC(1,    uint8_t codec_planes;                                         );
-    GLSLC(1,    uint8_t planar_rgb;                                           );
-    GLSLC(1,    uint8_t transparency;                                         );
-    GLSLC(1,    uint8_t colorspace;                                           );
-    GLSLC(1,    uint8_t pic_mode;                                             );
-    GLSLC(1,    uint8_t ec;                                                   );
-    GLSLC(1,    uint8_t ppi;                                                  );
-    GLSLC(1,    uint8_t chunks;                                               );
-    GLSLC(1,    uint8_t rct_search;                                           );
-    GLSLC(1,    uint8_t padding[3];                                           );
-    GLSLC(0, };                                                               );
-    ff_vk_shader_add_push_const(shd, 0, sizeof(FFv1VkParameters),
-                                VK_SHADER_STAGE_COMPUTE_BIT);
-}
-
-typedef struct FFv1VkRCTSearchParameters {
-    int fmt_lut[4];
-    int rct_offset;
-    uint8_t planar_rgb;
-    uint8_t transparency;
-    uint8_t key_frame;
-    uint8_t force_pcm;
-    uint8_t version;
-    uint8_t micro_version;
-    uint8_t padding[2];
-} FFv1VkRCTSearchParameters;
-
-static int run_rct_search(AVCodecContext *avctx, FFVkExecContext *exec,
-                          AVFrame *enc_in, VkImageView *enc_in_views,
-                          FFVkBuffer *slice_data_buf, uint32_t slice_data_size)
-{
-    VulkanEncodeFFv1Context *fv = avctx->priv_data;
-    FFV1Context *f = &fv->ctx;
-    FFVulkanFunctions *vk = &fv->s.vkfn;
-    AVHWFramesContext *src_hwfc = (AVHWFramesContext *)enc_in->hw_frames_ctx->data;
-    FFv1VkRCTSearchParameters pd;
-
-    /* Update descriptors */
-    ff_vk_shader_update_desc_buffer(&fv->s, exec, &fv->rct_search,
-                                    0, 0, 0,
-                                    slice_data_buf,
-                                    0, slice_data_size*f->slice_count,
-                                    VK_FORMAT_UNDEFINED);
-    ff_vk_shader_update_img_array(&fv->s, exec, &fv->rct_search,
-                                  enc_in, enc_in_views,
-                                  0, 1,
-                                  VK_IMAGE_LAYOUT_GENERAL,
-                                  VK_NULL_HANDLE);
-
-    ff_vk_exec_bind_shader(&fv->s, exec, &fv->rct_search);
-
-    pd = (FFv1VkRCTSearchParameters) {
-        .rct_offset = 1 << f->bits_per_raw_sample,
-        .planar_rgb = ff_vk_mt_is_np_rgb(src_hwfc->sw_format) &&
-                      (ff_vk_count_images((AVVkFrame *)enc_in->data[0]) > 1),
-        .transparency = f->transparency,
-        .key_frame = f->key_frame,
-        .force_pcm = fv->force_pcm,
-        .version = f->version,
-        .micro_version = f->micro_version,
-    };
-
-    if (avctx->sw_pix_fmt == AV_PIX_FMT_GBRP10 ||
-        avctx->sw_pix_fmt == AV_PIX_FMT_GBRP12 ||
-        avctx->sw_pix_fmt == AV_PIX_FMT_GBRP14)
-        memcpy(pd.fmt_lut, (int [4]) { 2, 1, 0, 3 }, 4*sizeof(int));
-    else
-        ff_vk_set_perm(avctx->sw_pix_fmt, pd.fmt_lut, 1);
-
-    ff_vk_shader_update_push_const(&fv->s, exec, &fv->rct_search,
-                                   VK_SHADER_STAGE_COMPUTE_BIT,
-                                   0, sizeof(pd), &pd);
-
-    vk->CmdDispatch(exec->buf, fv->ctx.num_h_slices, fv->ctx.num_v_slices, 1);
-
-    return 0;
-}
-
-static int vulkan_encode_ffv1_submit_frame(AVCodecContext *avctx,
-                                           FFVkExecContext *exec,
-                                           const AVFrame *pict)
-{
-    int err;
-    VulkanEncodeFFv1Context *fv = avctx->priv_data;
-    FFV1Context *f = &fv->ctx;
-    FFVulkanFunctions *vk = &fv->s.vkfn;
-
-    VulkanEncodeFFv1FrameData *fd = exec->opaque;
-    FFv1VkParameters pd;
-
-    /* Slice data */
-    AVBufferRef *slice_data_ref;
-    FFVkBuffer *slice_data_buf;
-    uint32_t plane_state_size;
-    uint32_t slice_state_size;
-    uint32_t slice_data_size;
-
-    /* Output data */
-    size_t maxsize;
-    FFVkBuffer *out_data_buf;
-
-    /* Results data */
-    FFVkBuffer *results_data_buf;
-
-    int has_inter = avctx->gop_size > 1;
-    uint32_t context_count = f->context_count[f->context_model];
-    const AVPixFmtDescriptor *fmt_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt);
-
-    AVFrame *src = (AVFrame *)pict;
-    VkImageView src_views[AV_NUM_DATA_POINTERS];
-
-    AVFrame *tmp = NULL;
-    VkImageView tmp_views[AV_NUM_DATA_POINTERS];
-
-    VkImageMemoryBarrier2 img_bar[37];
-    int nb_img_bar = 0;
-    VkBufferMemoryBarrier2 buf_bar[8];
-    int nb_buf_bar = 0;
-
-    /* Start recording */
-    ff_vk_exec_start(&fv->s, exec);
-
-    /* Frame state */
-    f->cur_enc_frame = pict;
-    if (avctx->gop_size == 0 || f->picture_number % avctx->gop_size == 0) {
-        av_buffer_unref(&fv->keyframe_slice_data_ref);
-        f->key_frame = fd->key_frame = 1;
-        f->gob_count++;
-    } else {
-        f->key_frame = fd->key_frame = 0;
-    }
-
-    f->slice_count = f->max_slice_count;
-
-    /* Allocate slice buffer data */
-    if (f->ac == AC_GOLOMB_RICE)
-        plane_state_size = 8;
-    else
-        plane_state_size = CONTEXT_SIZE;
-
-    plane_state_size *= context_count;
-    slice_state_size = plane_state_size*f->plane_count;
-
-    slice_data_size = 256; /* Overestimation for the SliceContext struct */
-    slice_state_size += slice_data_size;
-    slice_state_size = FFALIGN(slice_state_size, 8);
-
-    /* Allocate slice data buffer */
-    slice_data_ref = fv->keyframe_slice_data_ref;
-    if (!slice_data_ref) {
-        RET(ff_vk_get_pooled_buffer(&fv->s, &fv->slice_data_pool,
-                                    &slice_data_ref,
-                                    VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
-                                    VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
-                                    NULL, slice_state_size*f->slice_count,
-                                    VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
-
-        /* Only save it if we're going to use it again */
-        if (has_inter)
-            fv->keyframe_slice_data_ref = slice_data_ref;
-    }
-    slice_data_buf = (FFVkBuffer *)slice_data_ref->data;
-    ff_vk_exec_add_dep_buf(&fv->s, exec, &slice_data_ref, 1, has_inter);
-
-    /* Allocate results buffer */
-    RET(ff_vk_get_pooled_buffer(&fv->s, &fv->results_data_pool,
-                                &fd->results_data_ref,
-                                VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
-                                VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
-                                NULL, 2*f->slice_count*sizeof(uint64_t),
-                                VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
-                                VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
-    results_data_buf = (FFVkBuffer *)fd->results_data_ref->data;
-    ff_vk_exec_add_dep_buf(&fv->s, exec, &fd->results_data_ref, 1, 1);
-
-    /* Output buffer size */
-    maxsize = ff_ffv1_encode_buffer_size(avctx);
-    maxsize = FFMIN(maxsize, fv->s.props_11.maxMemoryAllocationSize);
-
-    /* Allocate output buffer */
-    RET(ff_vk_get_pooled_buffer(&fv->s, &fv->out_data_pool,
-                                &fd->out_data_ref,
-                                VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
-                                VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
-                                VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
-                                NULL, maxsize,
-                                VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
-                                (maxsize < fv->max_heap_size ?
-                                 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT : 0x0) |
-                                (!(fv->s.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY) ?
-                                 VK_MEMORY_PROPERTY_HOST_CACHED_BIT : 0x0)));
-    out_data_buf = (FFVkBuffer *)fd->out_data_ref->data;
-    ff_vk_exec_add_dep_buf(&fv->s, exec, &fd->out_data_ref, 1, 1);
-
-    /* Prepare input frame */
-    RET(ff_vk_exec_add_dep_frame(&fv->s, exec, src,
-                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
-
-    RET(ff_vk_create_imageviews(&fv->s, exec, src_views, src,
-                                fv->rep_fmt));
-    ff_vk_frame_barrier(&fv->s, exec, src, img_bar, &nb_img_bar,
-                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                        VK_ACCESS_SHADER_READ_BIT,
-                        VK_IMAGE_LAYOUT_GENERAL,
-                        VK_QUEUE_FAMILY_IGNORED);
-
-    if (fv->is_rgb) {
-        /* Create a temporaty frame */
-        tmp = av_frame_alloc();
-        if (!(tmp))
-            return AVERROR(ENOMEM);
-
-        RET(av_hwframe_get_buffer(fv->intermediate_frames_ref,
-                                  tmp, 0));
-
-        RET(ff_vk_exec_add_dep_frame(&fv->s, exec, tmp,
-                                     VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                     VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
-        RET(ff_vk_create_imageviews(&fv->s, exec, tmp_views,
-                                    tmp,
-                                    fv->rep_fmt));
-    }
-
-    /* Setup shader */
-    ff_vk_shader_update_desc_buffer(&fv->s, exec, &fv->setup,
-                                    1, 0, 0,
-                                    slice_data_buf,
-                                    0, slice_data_size*f->slice_count,
-                                    VK_FORMAT_UNDEFINED);
-    ff_vk_shader_update_img_array(&fv->s, exec, &fv->setup,
-                                  src, src_views,
-                                  1, 1,
-                                  VK_IMAGE_LAYOUT_GENERAL,
-                                  VK_NULL_HANDLE);
-
-    /* Add a buffer barrier between previous and current frame */
-    if (!f->key_frame) {
-        buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
-            .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-            .srcStageMask = slice_data_buf->stage,
-            .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-            .srcAccessMask = slice_data_buf->access,
-            .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
-                             VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
-            .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-            .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-            .buffer = slice_data_buf->buf,
-            .size = VK_WHOLE_SIZE,
-            .offset = 0,
-        };
-    }
-
-    if (fv->optimize_rct) {
-        RET(run_rct_search(avctx, exec,
-                           src, src_views,
-                           slice_data_buf, slice_data_size));
-
-        buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
-            .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-            .srcStageMask = slice_data_buf->stage,
-            .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-            .srcAccessMask = slice_data_buf->access,
-            .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
-            .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-            .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-            .buffer = slice_data_buf->buf,
-            .size = slice_data_size*f->slice_count,
-            .offset = 0,
-        };
-    }
-
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-        .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-        .pImageMemoryBarriers = img_bar,
-        .imageMemoryBarrierCount = nb_img_bar,
-        .pBufferMemoryBarriers = buf_bar,
-        .bufferMemoryBarrierCount = nb_buf_bar,
-    });
-    nb_img_bar = 0;
-    if (nb_buf_bar) {
-        slice_data_buf->stage = buf_bar[0].dstStageMask;
-        slice_data_buf->access = buf_bar[0].dstAccessMask;
-        nb_buf_bar = 0;
-    }
-
-    /* Run setup shader */
-    ff_vk_exec_bind_shader(&fv->s, exec, &fv->setup);
-    pd = (FFv1VkParameters) {
-        .slice_state = slice_data_buf->address + f->slice_count*256,
-        .out_data = out_data_buf->address,
-        .bits_per_raw_sample = f->bits_per_raw_sample,
-        .sar[0] = pict->sample_aspect_ratio.num,
-        .sar[1] = pict->sample_aspect_ratio.den,
-        .chroma_shift[0] = f->chroma_h_shift,
-        .chroma_shift[1] = f->chroma_v_shift,
-        .plane_state_size = plane_state_size,
-        .context_count = context_count,
-        .crcref = f->crcref,
-        .rct_offset = 1 << f->bits_per_raw_sample,
-        .slice_size_max = out_data_buf->size / f->slice_count,
-        .context_model = fv->ctx.context_model,
-        .version = f->version,
-        .micro_version = f->micro_version,
-        .force_pcm = fv->force_pcm,
-        .key_frame = f->key_frame,
-        .components = fmt_desc->nb_components,
-        .planes = av_pix_fmt_count_planes(avctx->sw_pix_fmt),
-        .codec_planes = f->plane_count,
-        .planar_rgb = ff_vk_mt_is_np_rgb(avctx->sw_pix_fmt) &&
-                      (ff_vk_count_images((AVVkFrame *)src->data[0]) > 1),
-        .transparency = f->transparency,
-        .colorspace = f->colorspace,
-        .pic_mode = !(pict->flags & AV_FRAME_FLAG_INTERLACED) ? 3 :
-                    !(pict->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? 2 : 1,
-        .ec = f->ec,
-        .ppi = fv->ppi,
-        .chunks = fv->chunks,
-        .rct_search = fv->optimize_rct,
-    };
-
-    /* For some reason the C FFv1 encoder/decoder treats these differently */
-    if (avctx->sw_pix_fmt == AV_PIX_FMT_GBRP10 ||
-        avctx->sw_pix_fmt == AV_PIX_FMT_GBRP12 ||
-        avctx->sw_pix_fmt == AV_PIX_FMT_GBRP14)
-        memcpy(pd.fmt_lut, (int [4]) { 2, 1, 0, 3 }, 4*sizeof(int));
-    else
-        ff_vk_set_perm(avctx->sw_pix_fmt, pd.fmt_lut, 1);
-
-    for (int i = 0; i < f->quant_table_count; i++)
-        pd.extend_lookup[i] = (f->quant_tables[i][3][127] != 0) ||
-                              (f->quant_tables[i][4][127] != 0);
-    ff_vk_shader_update_push_const(&fv->s, exec, &fv->setup,
-                                   VK_SHADER_STAGE_COMPUTE_BIT,
-                                   0, sizeof(pd), &pd);
-    vk->CmdDispatch(exec->buf, fv->ctx.num_h_slices, fv->ctx.num_v_slices, 1);
-
-    /* Clean up temporary image */
-    if (fv->is_rgb) {
-        AVVkFrame *vkf = (AVVkFrame *)tmp->data[0];
-        vk->CmdClearColorImage(exec->buf, vkf->img[0], VK_IMAGE_LAYOUT_GENERAL,
-                               &((VkClearColorValue) { 0 }),
-                               1, &((VkImageSubresourceRange) {
-                                   .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
-                                   .levelCount = 1,
-                                   .layerCount = 1,
-                               }));
-    }
-
-    /* Setup shader modified the slice data buffer */
-    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
-        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-        .srcStageMask = slice_data_buf->stage,
-        .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-        .srcAccessMask = slice_data_buf->access,
-        .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
-                         VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
-        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .buffer = slice_data_buf->buf,
-        .size = slice_data_size*f->slice_count,
-        .offset = 0,
-    };
-
-    if (f->key_frame || f->version > 3) {
-        FFv1VkResetParameters pd_reset;
-
-        ff_vk_shader_update_desc_buffer(&fv->s, exec, &fv->reset,
-                                        1, 0, 0,
-                                        slice_data_buf,
-                                        0, slice_data_size*f->slice_count,
-                                        VK_FORMAT_UNDEFINED);
-
-        /* Run setup shader */
-        ff_vk_exec_bind_shader(&fv->s, exec, &fv->reset);
-        pd_reset = (FFv1VkResetParameters) {
-            .slice_state = slice_data_buf->address + f->slice_count*256,
-            .plane_state_size = plane_state_size,
-            .codec_planes = f->plane_count,
-            .key_frame = f->key_frame,
-        };
-        for (int i = 0; i < f->quant_table_count; i++)
-            pd_reset.context_count[i] = f->context_count[i];
-
-        ff_vk_shader_update_push_const(&fv->s, exec, &fv->reset,
-                                       VK_SHADER_STAGE_COMPUTE_BIT,
-                                       0, sizeof(pd_reset), &pd_reset);
-
-        /* Sync between setup and reset shaders */
-        vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-            .pBufferMemoryBarriers = buf_bar,
-            .bufferMemoryBarrierCount = nb_buf_bar,
-        });
-        slice_data_buf->stage = buf_bar[0].dstStageMask;
-        slice_data_buf->access = buf_bar[0].dstAccessMask;
-        nb_buf_bar = 0;
-
-        vk->CmdDispatch(exec->buf, fv->ctx.num_h_slices, fv->ctx.num_v_slices,
-                        f->plane_count);
-    }
-
-    /* If the reset shader ran, insert a barrier now. */
-    if (f->key_frame || f->version > 3) {
-        /* Reset shader modified the slice data buffer */
-        buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
-            .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-            .srcStageMask = slice_data_buf->stage,
-            .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-            .srcAccessMask = slice_data_buf->access,
-            .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
-                             VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
-            .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-            .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-            .buffer = slice_data_buf->buf,
-            .size = slice_data_buf->size - slice_data_size*f->slice_count,
-            .offset = slice_data_size*f->slice_count,
-        };
-    }
-
-    if (fv->is_rgb) {
-        ff_vk_frame_barrier(&fv->s, exec, tmp, img_bar, &nb_img_bar,
-                            VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                            VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                            VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
-                            VK_IMAGE_LAYOUT_GENERAL,
-                            VK_QUEUE_FAMILY_IGNORED);
-    }
-
-    /* Final barrier before encoding */
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-        .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-        .pImageMemoryBarriers = img_bar,
-        .imageMemoryBarrierCount = nb_img_bar,
-        .pBufferMemoryBarriers = buf_bar,
-        .bufferMemoryBarrierCount = nb_buf_bar,
-    });
-    nb_img_bar = 0;
-    if (nb_buf_bar) {
-        slice_data_buf->stage = buf_bar[0].dstStageMask;
-        slice_data_buf->access = buf_bar[0].dstAccessMask;
-        nb_buf_bar = 0;
-    }
-
-    /* Main encode shader */
-    ff_vk_shader_update_desc_buffer(&fv->s, exec, &fv->enc,
-                                    1, 0, 0,
-                                    slice_data_buf,
-                                    0, slice_data_size*f->slice_count,
-                                    VK_FORMAT_UNDEFINED);
-    ff_vk_shader_update_img_array(&fv->s, exec, &fv->enc,
-                                  src, src_views,
-                                  1, 1,
-                                  VK_IMAGE_LAYOUT_GENERAL,
-                                  VK_NULL_HANDLE);
-    ff_vk_shader_update_desc_buffer(&fv->s, exec,
-                                    &fv->enc, 1, 2, 0,
-                                    results_data_buf,
-                                    0, results_data_buf->size,
-                                    VK_FORMAT_UNDEFINED);
-    if (fv->is_rgb)
-        ff_vk_shader_update_img_array(&fv->s, exec, &fv->enc,
-                                      tmp, tmp_views,
-                                      1, 3,
-                                      VK_IMAGE_LAYOUT_GENERAL,
-                                      VK_NULL_HANDLE);
-
-    ff_vk_exec_bind_shader(&fv->s, exec, &fv->enc);
-    ff_vk_shader_update_push_const(&fv->s, exec, &fv->enc,
-                                   VK_SHADER_STAGE_COMPUTE_BIT,
-                                   0, sizeof(pd), &pd);
-    vk->CmdDispatch(exec->buf, fv->ctx.num_h_slices, fv->ctx.num_v_slices, 1);
-
-    /* Submit */
-    err = ff_vk_exec_submit(&fv->s, exec);
-    if (err < 0)
-        return err;
-
-    f->picture_number++;
-
-    /* This, if needed, was referenced by the execution context
-     * as it was declared as a dependency. */
-    av_frame_free(&tmp);
-    return 0;
-
-fail:
-    av_frame_free(&tmp);
-    ff_vk_exec_discard_deps(&fv->s, exec);
-
-    return err;
-}
-
-static int transfer_slices(AVCodecContext *avctx,
-                           VkBufferCopy *buf_regions, int nb_regions,
-                           VulkanEncodeFFv1FrameData *fd,
-                           uint8_t *dst, AVBufferRef *dst_ref)
-{
-    int err;
-    VulkanEncodeFFv1Context *fv = avctx->priv_data;
-    FFVulkanFunctions *vk = &fv->s.vkfn;
-    FFVkExecContext *exec;
-
-    FFVkBuffer *out_data_buf = (FFVkBuffer *)fd->out_data_ref->data;
-
-    AVBufferRef *mapped_ref;
-    FFVkBuffer *mapped_buf;
-
-    VkBufferMemoryBarrier2 buf_bar[8];
-    int nb_buf_bar = 0;
-
-    err = ff_vk_host_map_buffer(&fv->s, &mapped_ref, dst, dst_ref,
-                                VK_BUFFER_USAGE_TRANSFER_DST_BIT);
-    if (err < 0)
-        return err;
-
-    mapped_buf = (FFVkBuffer *)mapped_ref->data;
-
-    /* Transfer the slices */
-    exec = ff_vk_exec_get(&fv->s, &fv->transfer_exec_pool);
-    ff_vk_exec_start(&fv->s, exec);
-
-    ff_vk_exec_add_dep_buf(&fv->s, exec, &fd->out_data_ref, 1, 0);
-    fd->out_data_ref = NULL; /* Ownership passed */
-
-    ff_vk_exec_add_dep_buf(&fv->s, exec, &mapped_ref, 1, 0);
-    mapped_ref = NULL; /* Ownership passed */
-
-    /* Ensure the output buffer is finished */
-    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
-        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-        .srcStageMask = out_data_buf->stage,
-        .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
-        .srcAccessMask = out_data_buf->access,
-        .dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT,
-        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .buffer = out_data_buf->buf,
-        .size = VK_WHOLE_SIZE,
-        .offset = 0,
-    };
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-        .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-        .pBufferMemoryBarriers = buf_bar,
-        .bufferMemoryBarrierCount = nb_buf_bar,
-    });
-    out_data_buf->stage = buf_bar[0].dstStageMask;
-    out_data_buf->access = buf_bar[0].dstAccessMask;
-    nb_buf_bar = 0;
-
-    for (int i = 0; i < nb_regions; i++)
-        buf_regions[i].dstOffset += mapped_buf->virtual_offset;
-
-    vk->CmdCopyBuffer(exec->buf,
-                      out_data_buf->buf, mapped_buf->buf,
-                      nb_regions, buf_regions);
-
-    /* Submit */
-    err = ff_vk_exec_submit(&fv->s, exec);
-    if (err < 0)
-        return err;
-
-    /* We need the encoded data immediately */
-    ff_vk_exec_wait(&fv->s, exec);
-
-    return 0;
-}
-
-static int get_packet(AVCodecContext *avctx, FFVkExecContext *exec,
-                      AVPacket *pkt)
-{
-    int err;
-    VulkanEncodeFFv1Context *fv = avctx->priv_data;
-    FFV1Context *f = &fv->ctx;
-    FFVulkanFunctions *vk = &fv->s.vkfn;
-    VulkanEncodeFFv1FrameData *fd = exec->opaque;
-
-    FFVkBuffer *out_data_buf = (FFVkBuffer *)fd->out_data_ref->data;
-    FFVkBuffer *results_data_buf = (FFVkBuffer *)fd->results_data_ref->data;
-    uint64_t *sc;
-
-    /* Make sure encoding's done */
-    ff_vk_exec_wait(&fv->s, exec);
-
-    /* Invalidate slice/output data if needed */
-    if (!(results_data_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
-        VkMappedMemoryRange invalidate_data = {
-            .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
-            .memory = results_data_buf->mem,
-            .offset = 0,
-            .size = VK_WHOLE_SIZE,
-        };
-        vk->InvalidateMappedMemoryRanges(fv->s.hwctx->act_dev,
-                                         1, &invalidate_data);
-    }
-
-    /* Calculate final size */
-    pkt->size = 0;
-    for (int i = 0; i < f->slice_count; i++) {
-        sc = &((uint64_t *)results_data_buf->mapped_mem)[i*2];
-        av_log(avctx, AV_LOG_DEBUG, "Slice %i size = %"PRIu64", "
-                                    "src offset = %"PRIu64"\n",
-               i, sc[0], sc[1]);
-
-        fv->buf_regions[i] = (VkBufferCopy) {
-            .srcOffset = sc[1],
-            .dstOffset = pkt->size,
-            .size = sc[0],
-        };
-        pkt->size += sc[0];
-    }
-    av_log(avctx, AV_LOG_VERBOSE, "Encoded data: %iMiB\n", pkt->size / (1024*1024));
-    av_buffer_unref(&fd->results_data_ref); /* No need for this buffer anymore */
-
-    /* Allocate packet */
-    if ((err = ff_get_encode_buffer(avctx, pkt, pkt->size, 0)) < 0)
-        return err;
-
-    pkt->pts      = fd->pts;
-    pkt->dts      = fd->pts;
-    pkt->duration = fd->duration;
-    pkt->flags   |= AV_PKT_FLAG_KEY * fd->key_frame;
-
-    if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
-        pkt->opaque          = fd->frame_opaque;
-        pkt->opaque_ref      = fd->frame_opaque_ref;
-        fd->frame_opaque_ref = NULL;
-    }
-
-    /* Try using host mapped memory transfers first */
-    if (fv->s.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY) {
-        err = transfer_slices(avctx, fv->buf_regions, f->slice_count, fd,
-                              pkt->data, pkt->buf);
-        if (err >= 0)
-            return err;
-    }
-
-    /* Invalidate slice/output data if needed */
-    if (!(out_data_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
-        VkMappedMemoryRange invalidate_data = {
-            .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
-            .memory = out_data_buf->mem,
-            .offset = 0,
-            .size = VK_WHOLE_SIZE,
-        };
-        vk->InvalidateMappedMemoryRanges(fv->s.hwctx->act_dev,
-                                         1, &invalidate_data);
-    }
-
-    /* Copy each slice */
-    for (int i = 0; i < f->slice_count; i++) {
-        VkBufferCopy *region = &fv->buf_regions[i];
-        memcpy(pkt->data + region->dstOffset,
-               out_data_buf->mapped_mem + region->srcOffset,
-               region->size);
-    }
-
-    av_buffer_unref(&fd->out_data_ref);
-
-    return 0;
-}
-
-static int vulkan_encode_ffv1_receive_packet(AVCodecContext *avctx,
-                                             AVPacket *pkt)
-{
-    int err;
-    VulkanEncodeFFv1Context *fv = avctx->priv_data;
-    VulkanEncodeFFv1FrameData *fd;
-    FFVkExecContext *exec;
-    AVFrame *frame;
-
-    while (1) {
-        /* Roll an execution context */
-        exec = ff_vk_exec_get(&fv->s, &fv->exec_pool);
-
-        /* If it had a frame, immediately output it */
-        if (exec->had_submission) {
-            exec->had_submission = 0;
-            fv->in_flight--;
-            return get_packet(avctx, exec, pkt);
-        }
-
-        /* Get next frame to encode */
-        frame = fv->frame;
-        err = ff_encode_get_frame(avctx, frame);
-        if (err < 0 && err != AVERROR_EOF) {
-            return err;
-        } else if (err == AVERROR_EOF) {
-            if (!fv->in_flight)
-                return err;
-            continue;
-        }
-
-        /* Encode frame */
-        fd = exec->opaque;
-        fd->pts = frame->pts;
-        fd->duration = frame->duration;
-        if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
-            fd->frame_opaque     = frame->opaque;
-            fd->frame_opaque_ref = frame->opaque_ref;
-            frame->opaque_ref    = NULL;
-        }
-
-        err = vulkan_encode_ffv1_submit_frame(avctx, exec, frame);
-        av_frame_unref(frame);
-        if (err < 0)
-            return err;
-
-        fv->in_flight++;
-        if (fv->in_flight < fv->async_depth)
-            return AVERROR(EAGAIN);
-    }
-
-    return 0;
-}
-
-static int init_indirect(AVCodecContext *avctx, enum AVPixelFormat sw_format)
-{
-    int err;
-    VulkanEncodeFFv1Context *fv = avctx->priv_data;
-    FFV1Context *f = &fv->ctx;
-    AVHWFramesContext *frames_ctx;
-    AVVulkanFramesContext *vk_frames;
-
-    fv->intermediate_frames_ref = av_hwframe_ctx_alloc(fv->s.device_ref);
-    if (!fv->intermediate_frames_ref)
-        return AVERROR(ENOMEM);
-
-    frames_ctx = (AVHWFramesContext *)fv->intermediate_frames_ref->data;
-    frames_ctx->format    = AV_PIX_FMT_VULKAN;
-    frames_ctx->sw_format = sw_format;
-    frames_ctx->width     = fv->s.frames->width;
-    frames_ctx->height    = f->num_v_slices*RGB_LINECACHE;
-
-    vk_frames = frames_ctx->hwctx;
-    vk_frames->tiling    = VK_IMAGE_TILING_OPTIMAL;
-    vk_frames->usage     = VK_IMAGE_USAGE_STORAGE_BIT |
-                           VK_IMAGE_USAGE_TRANSFER_DST_BIT;
-    vk_frames->img_flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
-
-    err = av_hwframe_ctx_init(fv->intermediate_frames_ref);
-    if (err < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to initialize frame pool with format %s: %s\n",
-               av_get_pix_fmt_name(sw_format), av_err2str(err));
-        av_buffer_unref(&fv->intermediate_frames_ref);
-        return err;
-    }
-
-    return 0;
-}
-
-static int check_support(AVHWFramesConstraints *constraints,
-                         enum AVPixelFormat fmt)
-{
-    for (int i = 0; constraints->valid_sw_formats[i]; i++) {
-        if (constraints->valid_sw_formats[i] == fmt)
-            return 1;
-    }
-    return 0;
-}
-
-static enum AVPixelFormat get_supported_rgb_buffer_fmt(AVCodecContext *avctx)
-{
-    VulkanEncodeFFv1Context *fv = avctx->priv_data;
-
-    enum AVPixelFormat fmt;
-    AVHWFramesConstraints *constraints;
-    constraints = av_hwdevice_get_hwframe_constraints(fv->s.device_ref,
-                                                      NULL);
-
-    /* What we'd like to optimally have */
-    fmt = fv->ctx.use32bit ?
-          (fv->ctx.transparency ? AV_PIX_FMT_RGBA128 : AV_PIX_FMT_RGB96) :
-          (fv->ctx.transparency ? AV_PIX_FMT_RGBA64  : AV_PIX_FMT_RGB48);
-    if (check_support(constraints, fmt))
-        goto end;
-
-    if (fv->ctx.use32bit) {
-        if (check_support(constraints, (fmt = AV_PIX_FMT_RGBA128)))
-            goto end;
-    } else {
-        if (check_support(constraints, (fmt = AV_PIX_FMT_RGBA64)))
-            goto end;
-
-        if (!fv->ctx.transparency &&
-            check_support(constraints, (fmt = AV_PIX_FMT_RGB96)))
-                goto end;
-
-        if (check_support(constraints, (fmt = AV_PIX_FMT_RGBA128)))
-            goto end;
-    }
-
-    fmt = AV_PIX_FMT_NONE;
-
-end:
-    av_hwframe_constraints_free(&constraints);
-    return fmt;
-}
-
-static void define_shared_code(AVCodecContext *avctx, FFVulkanShader *shd)
-{
-    VulkanEncodeFFv1Context *fv = avctx->priv_data;
-    FFV1Context *f = &fv->ctx;
-    int smp_bits = fv->ctx.use32bit ? 32 : 16;
-
-    av_bprintf(&shd->src, "#define RGB_LINECACHE %i\n"                   ,RGB_LINECACHE);
-    av_bprintf(&shd->src, "#define CONTEXT_SIZE %i\n"                    ,CONTEXT_SIZE);
-    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_MASK 0x%x\n"          ,MAX_QUANT_TABLE_MASK);
-
-    if (f->ac == AC_GOLOMB_RICE) {
-        av_bprintf(&shd->src, "#define PB_UNALIGNED\n"                   );
-        av_bprintf(&shd->src, "#define GOLOMB\n"                         );
-    }
-
-    if (fv->is_rgb)
-        av_bprintf(&shd->src, "#define RGB\n");
-
-    GLSLF(0, #define TYPE int%i_t                                        ,smp_bits);
-    GLSLF(0, #define VTYPE2 i%ivec2                                      ,smp_bits);
-    GLSLF(0, #define VTYPE3 i%ivec3                                      ,smp_bits);
-    GLSLD(ff_source_rangecoder_comp);
-
-    if (f->ac == AC_GOLOMB_RICE)
-        GLSLD(ff_source_ffv1_vlc_comp);
-
-    GLSLD(ff_source_ffv1_common_comp);
-}
-
-static int init_rct_search_shader(AVCodecContext *avctx, FFVkSPIRVCompiler *spv)
-{
-    int err;
-    VulkanEncodeFFv1Context *fv = avctx->priv_data;
-    FFV1Context *f = &fv->ctx;
-    FFVulkanShader *shd = &fv->rct_search;
-    FFVulkanDescriptorSetBinding *desc_set;
-
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-
-    RET(ff_vk_shader_init(&fv->s, shd, "ffv1_rct_search",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          (const char *[]) { "GL_EXT_buffer_reference",
-                                             "GL_EXT_buffer_reference2",
-                                             "GL_EXT_null_initializer" }, 3,
-                          32, 32, 1,
-                          0));
-
-    /* Common codec header */
-    GLSLD(ff_source_common_comp);
-
-    GLSLC(0, layout(push_constant, scalar) uniform pushConstants {             );
-    GLSLC(1,    ivec4 fmt_lut;                                                 );
-    GLSLC(1,    int rct_offset;                                                );
-    GLSLC(1,    uint8_t planar_rgb;                                            );
-    GLSLC(1,    uint8_t transparency;                                          );
-    GLSLC(1,    uint8_t key_frame;                                             );
-    GLSLC(1,    uint8_t force_pcm;                                             );
-    GLSLC(1,    uint8_t version;                                               );
-    GLSLC(1,    uint8_t micro_version;                                         );
-    GLSLC(1,    uint8_t padding[3];                                            );
-    GLSLC(0, };                                                                );
-    ff_vk_shader_add_push_const(shd, 0, sizeof(FFv1VkResetParameters),
-                                VK_SHADER_STAGE_COMPUTE_BIT);
-
-    av_bprintf(&shd->src, "#define MAX_QUANT_TABLES %i\n", MAX_QUANT_TABLES);
-    av_bprintf(&shd->src, "#define MAX_CONTEXT_INPUTS %i\n", MAX_CONTEXT_INPUTS);
-    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_SIZE %i\n", MAX_QUANT_TABLE_SIZE);
-
-    /* Never used */
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "rangecoder_static_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "uint8_t zero_one_state[512];",
-        },
-        {
-            .name        = "quant_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "int16_t quant_table[MAX_QUANT_TABLES]"
-                           "[MAX_CONTEXT_INPUTS][MAX_QUANT_TABLE_SIZE];",
-        },
-    };
-    RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 2, 1, 1));
-
-    define_shared_code(avctx, shd);
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "slice_data_buf",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "SliceContext slice_ctx",
-            .buf_elems   = f->max_slice_count,
-        },
-        {
-            .name       = "src",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .dimensions = 2,
-            .mem_layout = ff_vk_shader_rep_fmt(fv->s.frames->sw_format,
-                                               fv->rep_fmt),
-            .elems      = av_pix_fmt_count_planes(fv->s.frames->sw_format),
-            .mem_quali  = "readonly",
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-    };
-    RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 2, 0, 0));
-
-    GLSLD(ff_source_ffv1_rct_search_comp);
-
-    RET(spv->compile_shader(&fv->s, spv, shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(&fv->s, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(&fv->s, &fv->exec_pool, shd));
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-
-    return err;
-}
-
-static int init_setup_shader(AVCodecContext *avctx, FFVkSPIRVCompiler *spv)
-{
-    int err;
-    VulkanEncodeFFv1Context *fv = avctx->priv_data;
-    FFV1Context *f = &fv->ctx;
-    FFVulkanShader *shd = &fv->setup;
-    FFVulkanDescriptorSetBinding *desc_set;
-
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-
-    RET(ff_vk_shader_init(&fv->s, shd, "ffv1_setup",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          (const char *[]) { "GL_EXT_buffer_reference",
-                                             "GL_EXT_buffer_reference2" }, 2,
-                          1, 1, 1,
-                          0));
-
-    /* Common codec header */
-    GLSLD(ff_source_common_comp);
-    add_push_data(shd);
-
-    av_bprintf(&shd->src, "#define MAX_QUANT_TABLES %i\n", MAX_QUANT_TABLES);
-    av_bprintf(&shd->src, "#define MAX_CONTEXT_INPUTS %i\n", MAX_CONTEXT_INPUTS);
-    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_SIZE %i\n", MAX_QUANT_TABLE_SIZE);
-    av_bprintf(&shd->src, "#define FULL_RENORM\n");
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "rangecoder_static_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "uint8_t zero_one_state[512];",
-        },
-        { /* This descriptor is never used */
-            .name        = "quant_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "int16_t quant_table[MAX_QUANT_TABLES]"
-                           "[MAX_CONTEXT_INPUTS][MAX_QUANT_TABLE_SIZE];",
-        },
-    };
-    RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 2, 1, 0));
-
-    define_shared_code(avctx, shd);
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "slice_data_buf",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "SliceContext slice_ctx",
-            .buf_elems   = f->max_slice_count,
-        },
-        {
-            .name       = "src",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .dimensions = 2,
-            .mem_layout = ff_vk_shader_rep_fmt(fv->s.frames->sw_format,
-                                               fv->rep_fmt),
-            .elems      = av_pix_fmt_count_planes(fv->s.frames->sw_format),
-            .mem_quali  = "readonly",
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-    };
-    RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 2, 0, 0));
-
-    GLSLD(ff_source_ffv1_enc_setup_comp);
-
-    RET(spv->compile_shader(&fv->s, spv, shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(&fv->s, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(&fv->s, &fv->exec_pool, shd));
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-
-    return err;
-}
-
-static int init_reset_shader(AVCodecContext *avctx, FFVkSPIRVCompiler *spv)
-{
-    int err;
-    VulkanEncodeFFv1Context *fv = avctx->priv_data;
-    FFV1Context *f = &fv->ctx;
-    FFVulkanShader *shd = &fv->reset;
-    FFVulkanDescriptorSetBinding *desc_set;
-
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    int wg_dim = FFMIN(fv->s.props.properties.limits.maxComputeWorkGroupSize[0], 1024);
-
-    RET(ff_vk_shader_init(&fv->s, shd, "ffv1_reset",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          (const char *[]) { "GL_EXT_buffer_reference",
-                                             "GL_EXT_buffer_reference2" }, 2,
-                          wg_dim, 1, 1,
-                          0));
-
-    /* Common codec header */
-    GLSLD(ff_source_common_comp);
-
-    GLSLC(0, layout(push_constant, scalar) uniform pushConstants {             );
-    GLSLF(1,    uint context_count[%i];                                        ,MAX_QUANT_TABLES);
-    GLSLC(1,    u8buf slice_state;                                             );
-    GLSLC(1,    uint plane_state_size;                                         );
-    GLSLC(1,    uint8_t codec_planes;                                          );
-    GLSLC(1,    uint8_t key_frame;                                             );
-    GLSLC(1,    uint8_t version;                                               );
-    GLSLC(1,    uint8_t micro_version;                                         );
-    GLSLC(1,    uint8_t padding[1];                                            );
-    GLSLC(0, };                                                                );
-    ff_vk_shader_add_push_const(shd, 0, sizeof(FFv1VkResetParameters),
-                                VK_SHADER_STAGE_COMPUTE_BIT);
-
-    av_bprintf(&shd->src, "#define MAX_QUANT_TABLES %i\n", MAX_QUANT_TABLES);
-    av_bprintf(&shd->src, "#define MAX_CONTEXT_INPUTS %i\n", MAX_CONTEXT_INPUTS);
-    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_SIZE %i\n", MAX_QUANT_TABLE_SIZE);
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "rangecoder_static_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "uint8_t zero_one_state[512];",
-        },
-        {
-            .name        = "quant_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "int16_t quant_table[MAX_QUANT_TABLES]"
-                           "[MAX_CONTEXT_INPUTS][MAX_QUANT_TABLE_SIZE];",
-        },
-    };
-    RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 2, 1, 0));
-
-    define_shared_code(avctx, shd);
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "slice_data_buf",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .mem_quali   = "readonly",
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "SliceContext slice_ctx",
-            .buf_elems   = f->max_slice_count,
-        },
-    };
-    RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 1, 0, 0));
-
-    GLSLD(ff_source_ffv1_reset_comp);
-
-    RET(spv->compile_shader(&fv->s, spv, shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(&fv->s, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(&fv->s, &fv->exec_pool, shd));
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-
-    return err;
-}
-
-static int init_encode_shader(AVCodecContext *avctx, FFVkSPIRVCompiler *spv)
-{
-    int err;
-    VulkanEncodeFFv1Context *fv = avctx->priv_data;
-    FFV1Context *f = &fv->ctx;
-    FFVulkanShader *shd = &fv->enc;
-    FFVulkanDescriptorSetBinding *desc_set;
-
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    int use_cached_reader = fv->ctx.ac != AC_GOLOMB_RICE;
-
-    RET(ff_vk_shader_init(&fv->s, shd, "ffv1_enc",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          (const char *[]) { "GL_EXT_buffer_reference",
-                                             "GL_EXT_buffer_reference2" }, 2,
-                          use_cached_reader ? CONTEXT_SIZE : 1, 1, 1,
-                          0));
-
-    /* Common codec header */
-    GLSLD(ff_source_common_comp);
-
-    add_push_data(shd);
-
-    av_bprintf(&shd->src, "#define MAX_QUANT_TABLES %i\n", MAX_QUANT_TABLES);
-    av_bprintf(&shd->src, "#define MAX_CONTEXT_INPUTS %i\n", MAX_CONTEXT_INPUTS);
-    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_SIZE %i\n", MAX_QUANT_TABLE_SIZE);
-
-    if (use_cached_reader)
-        av_bprintf(&shd->src, "#define CACHED_SYMBOL_READER 1\n");
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "rangecoder_static_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "uint8_t zero_one_state[512];",
-        },
-        {
-            .name        = "quant_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "int16_t quant_table[MAX_QUANT_TABLES]"
-                           "[MAX_CONTEXT_INPUTS][MAX_QUANT_TABLE_SIZE];",
-        },
-        {
-            .name        = "crc_ieee_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "uint32_t crc_ieee[256];",
-        },
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 3, 1, 0));
-
-    define_shared_code(avctx, shd);
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "slice_data_buf",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "SliceContext slice_ctx",
-            .buf_elems   = f->max_slice_count,
-        },
-        {
-            .name       = "src",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .dimensions = 2,
-            .mem_layout = ff_vk_shader_rep_fmt(fv->s.frames->sw_format,
-                                               fv->rep_fmt),
-            .elems      = av_pix_fmt_count_planes(fv->s.frames->sw_format),
-            .mem_quali  = "readonly",
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-        {
-            .name        = "results_data_buf",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_quali   = "writeonly",
-            .buf_content = "uint64_t slice_results[2048];",
-        },
-        { /* place holder for desc_set[3] */
-        },
-    };
-    if (fv->is_rgb) {
-        AVHWFramesContext *intermediate_frames_ctx;
-        intermediate_frames_ctx = (AVHWFramesContext *)fv->intermediate_frames_ref->data;
-        desc_set[3] = (FFVulkanDescriptorSetBinding) {
-            .name       = "tmp",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .dimensions = 2,
-            .mem_layout = ff_vk_shader_rep_fmt(intermediate_frames_ctx->sw_format,
-                                               FF_VK_REP_NATIVE),
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        };
-    }
-    RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 3 + fv->is_rgb, 0, 0));
-
-    GLSLD(ff_source_ffv1_enc_comp);
-
-    RET(spv->compile_shader(&fv->s, spv, shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(&fv->s, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(&fv->s, &fv->exec_pool, shd));
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-
-    return err;
-}
-
-static av_cold int vulkan_encode_ffv1_init(AVCodecContext *avctx)
-{
-    int err;
-    size_t maxsize, max_heap_size, max_host_size;
-    VulkanEncodeFFv1Context *fv = avctx->priv_data;
-    FFV1Context *f = &fv->ctx;
-    FFVkSPIRVCompiler *spv;
-
-    if ((err = ff_ffv1_common_init(avctx, f)) < 0)
-        return err;
-
-    if (f->ac == 1)
-        f->ac = AC_RANGE_CUSTOM_TAB;
-
-    err = ff_ffv1_encode_setup_plane_info(avctx, avctx->sw_pix_fmt);
-    if (err < 0)
-        return err;
-
-    /* Target version 3 by default */
-    f->version = 3;
-
-    err = ff_ffv1_encode_init(avctx);
-    if (err < 0)
-        return err;
-
-    /* Rice coding did not support high bit depths */
-    if (f->bits_per_raw_sample > (f->version > 3 ? 16 : 8)) {
-        if (f->ac == AC_GOLOMB_RICE) {
-            av_log(avctx, AV_LOG_WARNING, "bits_per_raw_sample > 8, "
-                                          "forcing range coder\n");
-            f->ac = AC_RANGE_CUSTOM_TAB;
-        }
-    }
-
-    if (f->version < 4 && avctx->gop_size > 1) {
-        av_log(avctx, AV_LOG_ERROR, "Using inter frames requires version 4 (-level 4)\n");
-        return AVERROR_INVALIDDATA;
-    }
-
-    if (f->version == 4 && avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
-        av_log(avctx, AV_LOG_ERROR, "Version 4 is experimental and requires -strict -2\n");
-            return AVERROR_INVALIDDATA;
-    }
-
-    /* We target version 4.3 */
-    if (f->version == 4 && f->micro_version > 4)
-        f->micro_version = 3;
-
-    //if (fv->ctx.ac == AC_GOLOMB_RICE) {
-    if (0) {
-        int w_a = FFALIGN(avctx->width, LG_ALIGN_W);
-        int h_a = FFALIGN(avctx->height, LG_ALIGN_H);
-        int w_sl, h_sl;
-
-        /* Pixels per line an invocation handles */
-        int ppi = 0;
-        /* Chunk size */
-        int chunks = 0;
-
-        do {
-            if (ppi < 2)
-                ppi++;
-            chunks++;
-            w_sl = w_a / (LG_ALIGN_W*ppi);
-            h_sl = h_a / (LG_ALIGN_H*chunks);
-        } while (w_sl > MAX_SLICES / h_sl);
-
-        av_log(avctx, AV_LOG_VERBOSE, "Slice config: %ix%i, %i total\n",
-               LG_ALIGN_W*ppi, LG_ALIGN_H*chunks, w_sl*h_sl);
-        av_log(avctx, AV_LOG_VERBOSE, "Horizontal slices: %i (%i pixels per invoc)\n",
-               w_sl, ppi);
-        av_log(avctx, AV_LOG_VERBOSE, "Vertical slices: %i (%i chunks)\n",
-               h_sl, chunks);
-
-        f->num_h_slices = w_sl;
-        f->num_v_slices = h_sl;
-
-        fv->ppi = ppi;
-        fv->chunks = chunks;
-    } else {
-        f->num_h_slices = fv->num_h_slices;
-        f->num_v_slices = fv->num_v_slices;
-
-        if (f->num_h_slices <= 0 && f->num_v_slices <= 0) {
-            if (avctx->slices) {
-                err = ff_ffv1_encode_determine_slices(avctx);
-                if (err < 0)
-                    return err;
-            } else {
-                f->num_h_slices = 32;
-                f->num_v_slices = 32;
-            }
-        } else if (f->num_h_slices && f->num_v_slices <= 0) {
-            f->num_v_slices = MAX_SLICES / f->num_h_slices;
-        } else if (f->num_v_slices && f->num_h_slices <= 0) {
-            f->num_h_slices = MAX_SLICES / f->num_v_slices;
-        }
-
-        f->num_h_slices = FFMIN(f->num_h_slices, avctx->width);
-        f->num_v_slices = FFMIN(f->num_v_slices, avctx->height);
-
-        if (f->num_h_slices * f->num_v_slices > MAX_SLICES) {
-            av_log(avctx, AV_LOG_ERROR, "Too many slices (%i), maximum supported "
-                                        "by the standard is %i\n",
-                   f->num_h_slices * f->num_v_slices, MAX_SLICES);
-            return AVERROR_PATCHWELCOME;
-        }
-    }
-
-    f->max_slice_count = f->num_h_slices * f->num_v_slices;
-
-    if ((err = ff_ffv1_write_extradata(avctx)) < 0)
-        return err;
-
-    if (f->version < 4) {
-        if (((f->chroma_h_shift > 0) && (avctx->width % (64 << f->chroma_h_shift))) ||
-            ((f->chroma_v_shift > 0) && (avctx->height % (64 << f->chroma_v_shift)))) {
-            av_log(avctx, AV_LOG_ERROR, "Encoding frames with subsampling and unaligned "
-                                        "dimensions is only supported in version 4 (-level 4)\n");
-            return AVERROR_PATCHWELCOME;
-        }
-    }
-
-    if (fv->force_pcm) {
-        if (f->version < 4) {
-            av_log(avctx, AV_LOG_ERROR, "PCM coding only supported by version 4 (-level 4)\n");
-            return AVERROR_INVALIDDATA;
-        } else if (f->ac == AC_GOLOMB_RICE) {
-            av_log(avctx, AV_LOG_ERROR, "PCM coding requires range coding\n");
-            return AVERROR_INVALIDDATA;
-        }
-    }
-
-    /* Init Vulkan */
-    err = ff_vk_init(&fv->s, avctx, NULL, avctx->hw_frames_ctx);
-    if (err < 0)
-        return err;
-
-    fv->qf = ff_vk_qf_find(&fv->s, VK_QUEUE_COMPUTE_BIT, 0);
-    if (!fv->qf) {
-        av_log(avctx, AV_LOG_ERROR, "Device has no compute queues!\n");
-        return err;
-    }
-
-    /* Try to measure VRAM size */
-    max_heap_size = 0;
-    max_host_size = 0;
-    for (int i = 0; i < fv->s.mprops.memoryHeapCount; i++) {
-        if (fv->s.mprops.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
-            max_heap_size = FFMAX(fv->max_heap_size,
-                                  fv->s.mprops.memoryHeaps[i].size);
-        if (!(fv->s.mprops.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT))
-            max_host_size = FFMAX(max_host_size,
-                                  fv->s.mprops.memoryHeaps[i].size);
-    }
-    fv->max_heap_size = max_heap_size;
-
-    maxsize = ff_ffv1_encode_buffer_size(avctx);
-    if (maxsize > fv->s.props_11.maxMemoryAllocationSize) {
-        av_log(avctx, AV_LOG_WARNING, "Encoding buffer size (%zu) larger "
-                                      "than maximum device allocation (%zu), clipping\n",
-               maxsize, fv->s.props_11.maxMemoryAllocationSize);
-        maxsize = fv->s.props_11.maxMemoryAllocationSize;
-    }
-
-    if (max_heap_size < maxsize) {
-        av_log(avctx, AV_LOG_WARNING, "Encoding buffer (%zu) larger than VRAM (%zu), "
-                                      "using host memory (slower)\n",
-               maxsize, fv->max_heap_size);
-
-        /* Keep 1/2th of RAM as headroom */
-        max_heap_size = max_host_size - (max_host_size >> 1);
-    } else {
-        /* Keep 1/8th of VRAM as headroom */
-        max_heap_size = max_heap_size - (max_heap_size >> 3);
-    }
-
-    av_log(avctx, AV_LOG_INFO, "Async buffers: %zuMiB per context, %zuMiB total, depth: %i\n",
-           maxsize / (1024*1024),
-           (fv->async_depth * maxsize) / (1024*1024),
-           fv->async_depth);
-
-    err = ff_vk_exec_pool_init(&fv->s, fv->qf, &fv->exec_pool,
-                               fv->async_depth,
-                               0, 0, 0, NULL);
-    if (err < 0)
-        return err;
-
-    fv->transfer_qf = ff_vk_qf_find(&fv->s, VK_QUEUE_TRANSFER_BIT, 0);
-    if (!fv->transfer_qf) {
-        av_log(avctx, AV_LOG_ERROR, "Device has no transfer queues!\n");
-        return err;
-    }
-
-    err = ff_vk_exec_pool_init(&fv->s, fv->transfer_qf, &fv->transfer_exec_pool,
-                               1,
-                               0, 0, 0, NULL);
-    if (err < 0)
-        return err;
-
-    spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    /* Detect the special RGB coding mode */
-    fv->is_rgb = !(f->colorspace == 0 && avctx->sw_pix_fmt != AV_PIX_FMT_YA8) &&
-                 !(avctx->sw_pix_fmt == AV_PIX_FMT_YA8);
-
-    /* bits_per_raw_sample use regular unsigned representation,
-     * but in higher bit depths, the data is casted to int16_t */
-    fv->rep_fmt = FF_VK_REP_UINT;
-    if (!fv->is_rgb && f->bits_per_raw_sample > 8)
-        fv->rep_fmt = FF_VK_REP_INT;
-
-    /* Init rct search shader */
-    fv->optimize_rct = fv->is_rgb && f->version >= 4 &&
-                       !fv->force_pcm && fv->optimize_rct;
-    if (fv->optimize_rct) {
-        err = init_rct_search_shader(avctx, spv);
-        if (err < 0) {
-            spv->uninit(&spv);
-            return err;
-        }
-    }
-
-    /* Init setup shader */
-    err = init_setup_shader(avctx, spv);
-    if (err < 0) {
-        spv->uninit(&spv);
-        return err;
-    }
-
-    /* Init reset shader */
-    err = init_reset_shader(avctx, spv);
-    if (err < 0) {
-        spv->uninit(&spv);
-        return err;
-    }
-
-    if (fv->is_rgb) {
-        enum AVPixelFormat intermediate_fmt = get_supported_rgb_buffer_fmt(avctx);
-        if (intermediate_fmt == AV_PIX_FMT_NONE) {
-            av_log(avctx, AV_LOG_ERROR, "Unable to find a supported compatible "
-                                        "pixel format for RCT buffer!\n");
-            return AVERROR(ENOTSUP);
-        }
-
-        RET(init_indirect(avctx, intermediate_fmt));
-    }
-
-    /* Encode shader */
-    err = init_encode_shader(avctx, spv);
-    if (err < 0) {
-        spv->uninit(&spv);
-        return err;
-    }
-
-    spv->uninit(&spv);
-
-    /* Range coder data */
-    err = ff_ffv1_vk_init_state_transition_data(&fv->s,
-                                                &fv->rangecoder_static_buf,
-                                                f);
-    if (err < 0)
-        return err;
-
-    /* Quantization table data */
-    err = ff_ffv1_vk_init_quant_table_data(&fv->s,
-                                           &fv->quant_buf,
-                                           f);
-    if (err < 0)
-        return err;
-
-    /* CRC table buffer */
-    err = ff_ffv1_vk_init_crc_table_data(&fv->s,
-                                         &fv->crc_tab_buf,
-                                         f);
-    if (err < 0)
-        return err;
-
-    /* Update setup global descriptors */
-    RET(ff_vk_shader_update_desc_buffer(&fv->s, &fv->exec_pool.contexts[0],
-                                        &fv->setup, 0, 0, 0,
-                                        &fv->rangecoder_static_buf,
-                                        0, fv->rangecoder_static_buf.size,
-                                        VK_FORMAT_UNDEFINED));
-
-    /* Update encode global descriptors */
-    RET(ff_vk_shader_update_desc_buffer(&fv->s, &fv->exec_pool.contexts[0],
-                                        &fv->enc, 0, 0, 0,
-                                        &fv->rangecoder_static_buf,
-                                        0, fv->rangecoder_static_buf.size,
-                                        VK_FORMAT_UNDEFINED));
-    RET(ff_vk_shader_update_desc_buffer(&fv->s, &fv->exec_pool.contexts[0],
-                                        &fv->enc, 0, 1, 0,
-                                        &fv->quant_buf,
-                                        0, fv->quant_buf.size,
-                                        VK_FORMAT_UNDEFINED));
-    RET(ff_vk_shader_update_desc_buffer(&fv->s, &fv->exec_pool.contexts[0],
-                                        &fv->enc, 0, 2, 0,
-                                        &fv->crc_tab_buf,
-                                        0, fv->crc_tab_buf.size,
-                                        VK_FORMAT_UNDEFINED));
-
-    /* Temporary frame */
-    fv->frame = av_frame_alloc();
-    if (!fv->frame)
-        return AVERROR(ENOMEM);
-
-    /* Async data pool */
-    fv->async_depth = fv->exec_pool.pool_size;
-    fv->exec_ctx_info = av_calloc(fv->async_depth, sizeof(*fv->exec_ctx_info));
-    if (!fv->exec_ctx_info)
-        return AVERROR(ENOMEM);
-    for (int i = 0; i < fv->async_depth; i++)
-        fv->exec_pool.contexts[i].opaque = &fv->exec_ctx_info[i];
-
-    fv->buf_regions = av_malloc_array(f->max_slice_count, sizeof(*fv->buf_regions));
-    if (!fv->buf_regions)
-        return AVERROR(ENOMEM);
-
-fail:
-    return err;
-}
-
-static av_cold int vulkan_encode_ffv1_close(AVCodecContext *avctx)
-{
-    VulkanEncodeFFv1Context *fv = avctx->priv_data;
-
-    ff_vk_exec_pool_free(&fv->s, &fv->exec_pool);
-    ff_vk_exec_pool_free(&fv->s, &fv->transfer_exec_pool);
-
-    ff_vk_shader_free(&fv->s, &fv->enc);
-    ff_vk_shader_free(&fv->s, &fv->reset);
-    ff_vk_shader_free(&fv->s, &fv->setup);
-    ff_vk_shader_free(&fv->s, &fv->rct_search);
-
-    if (fv->exec_ctx_info) {
-        for (int i = 0; i < fv->async_depth; i++) {
-            VulkanEncodeFFv1FrameData *fd = &fv->exec_ctx_info[i];
-            av_buffer_unref(&fd->out_data_ref);
-            av_buffer_unref(&fd->results_data_ref);
-            av_buffer_unref(&fd->frame_opaque_ref);
-        }
-    }
-    av_free(fv->exec_ctx_info);
-
-    av_buffer_unref(&fv->intermediate_frames_ref);
-
-    av_buffer_pool_uninit(&fv->results_data_pool);
-
-    av_buffer_pool_uninit(&fv->out_data_pool);
-
-    av_buffer_unref(&fv->keyframe_slice_data_ref);
-    av_buffer_pool_uninit(&fv->slice_data_pool);
-
-    ff_vk_free_buf(&fv->s, &fv->quant_buf);
-    ff_vk_free_buf(&fv->s, &fv->rangecoder_static_buf);
-    ff_vk_free_buf(&fv->s, &fv->crc_tab_buf);
-
-    av_free(fv->buf_regions);
-    av_frame_free(&fv->frame);
-    ff_vk_uninit(&fv->s);
-
-    return 0;
-}
-
-#define OFFSET(x) offsetof(VulkanEncodeFFv1Context, x)
-#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
-static const AVOption vulkan_encode_ffv1_options[] = {
-    { "slicecrc", "Protect slices with CRCs", OFFSET(ctx.ec), AV_OPT_TYPE_INT,
-            { .i64 = -1 }, -1, 2, VE },
-    { "context", "Context model", OFFSET(ctx.context_model), AV_OPT_TYPE_INT,
-            { .i64 = 0 }, 0, 1, VE },
-    { "coder", "Coder type", OFFSET(ctx.ac), AV_OPT_TYPE_INT,
-            { .i64 = AC_RANGE_CUSTOM_TAB }, -2, 2, VE, .unit = "coder" },
-        { "rice", "Golomb rice", 0, AV_OPT_TYPE_CONST,
-            { .i64 = AC_GOLOMB_RICE }, INT_MIN, INT_MAX, VE, .unit = "coder" },
-        { "range_def", "Range with default table", 0, AV_OPT_TYPE_CONST,
-            { .i64 = AC_RANGE_DEFAULT_TAB_FORCE }, INT_MIN, INT_MAX, VE, .unit = "coder" },
-        { "range_tab", "Range with custom table", 0, AV_OPT_TYPE_CONST,
-            { .i64 = AC_RANGE_CUSTOM_TAB }, INT_MIN, INT_MAX, VE, .unit = "coder" },
-    { "qtable", "Quantization table", OFFSET(ctx.qtable), AV_OPT_TYPE_INT,
-            { .i64 = -1 }, -1, 2, VE , .unit = "qtable"},
-        { "default", NULL, 0, AV_OPT_TYPE_CONST,
-            { .i64 = QTABLE_DEFAULT }, INT_MIN, INT_MAX, VE, .unit = "qtable" },
-        { "8bit", NULL, 0, AV_OPT_TYPE_CONST,
-            { .i64 = QTABLE_8BIT }, INT_MIN, INT_MAX, VE, .unit = "qtable" },
-        { "greater8bit", NULL, 0, AV_OPT_TYPE_CONST,
-            { .i64 = QTABLE_GT8BIT }, INT_MIN, INT_MAX, VE, .unit = "qtable" },
-
-    { "slices_h", "Number of horizontal slices", OFFSET(num_h_slices), AV_OPT_TYPE_INT,
-            { .i64 = -1 }, -1, MAX_SLICES, VE },
-    { "slices_v", "Number of vertical slices", OFFSET(num_v_slices), AV_OPT_TYPE_INT,
-            { .i64 = -1 }, -1, MAX_SLICES, VE },
-
-    { "force_pcm", "Code all slices with no prediction", OFFSET(force_pcm), AV_OPT_TYPE_BOOL,
-            { .i64 = 0 }, 0, 1, VE },
-
-    { "rct_search", "Run a search for RCT parameters (level 4 only)", OFFSET(optimize_rct), AV_OPT_TYPE_BOOL,
-            { .i64 = 1 }, 0, 1, VE },
-
-    { "async_depth", "Internal parallelization depth", OFFSET(async_depth), AV_OPT_TYPE_INT,
-            { .i64 = 1 }, 1, INT_MAX, VE },
-
-    { NULL }
-};
-
-static const FFCodecDefault vulkan_encode_ffv1_defaults[] = {
-    { "g", "1" },
-    { NULL },
-};
-
-static const AVClass vulkan_encode_ffv1_class = {
-    .class_name = "ffv1_vulkan",
-    .item_name  = av_default_item_name,
-    .option     = vulkan_encode_ffv1_options,
-    .version    = LIBAVUTIL_VERSION_INT,
-};
-
-const AVCodecHWConfigInternal *const vulkan_encode_ffv1_hw_configs[] = {
-    HW_CONFIG_ENCODER_FRAMES(VULKAN, VULKAN),
-    NULL,
-};
-
-const FFCodec ff_ffv1_vulkan_encoder = {
-    .p.name         = "ffv1_vulkan",
-    CODEC_LONG_NAME("FFmpeg video codec #1 (Vulkan)"),
-    .p.type         = AVMEDIA_TYPE_VIDEO,
-    .p.id           = AV_CODEC_ID_FFV1,
-    .priv_data_size = sizeof(VulkanEncodeFFv1Context),
-    .init           = &vulkan_encode_ffv1_init,
-    FF_CODEC_RECEIVE_PACKET_CB(&vulkan_encode_ffv1_receive_packet),
-    .close          = &vulkan_encode_ffv1_close,
-    .p.priv_class   = &vulkan_encode_ffv1_class,
-    .p.capabilities = AV_CODEC_CAP_DELAY |
-                      AV_CODEC_CAP_HARDWARE |
-                      AV_CODEC_CAP_DR1 |
-                      AV_CODEC_CAP_ENCODER_FLUSH |
-                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
-    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_EOF_FLUSH,
-    .defaults       = vulkan_encode_ffv1_defaults,
-    CODEC_PIXFMTS(AV_PIX_FMT_VULKAN),
-    .hw_configs     = vulkan_encode_ffv1_hw_configs,
-    .p.wrapper_name = "vulkan",
-};
-- 
2.49.1


From d3767c0fcc87dec9a467071f5ae33ceeec30780f Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:25:53 +0000
Subject: [PATCH 060/118] Changing vulkan file directory

---
 libavcodec/vulkan/ffv1enc_vulkan.c | 1848 ++++++++++++++++++++++++++++
 1 file changed, 1848 insertions(+)
 create mode 100644 libavcodec/vulkan/ffv1enc_vulkan.c

diff --git a/libavcodec/vulkan/ffv1enc_vulkan.c b/libavcodec/vulkan/ffv1enc_vulkan.c
new file mode 100644
index 0000000000..883ad75d9b
--- /dev/null
+++ b/libavcodec/vulkan/ffv1enc_vulkan.c
@@ -0,0 +1,1848 @@
+/*
+ * Copyright (c) 2024 Lynne <dev@lynne.ee>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/mem.h"
+#include "../../libavutil/vulkan/vulkan.h"
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+
+#include "libavcodec/avcodec.h"
+#include "libavcodec/internal.h"
+#include "libavcodec/hwconfig.h"
+#include "libavcodec/encode.h"
+#include "libavutil/opt.h"
+#include "libavcodec/codec_internal.h"
+
+#include "libavcodec/ffv1.h"
+#include "libavcodec/ffv1enc.h"
+#include "ffv1_vulkan.h"
+
+/* Parallel Golomb alignment */
+#define LG_ALIGN_W 32
+#define LG_ALIGN_H 32
+
+/* Unlike the decoder, we need 4 lines (but really only 3) */
+#define RGB_LINECACHE 4
+
+typedef struct VulkanEncodeFFv1FrameData {
+    /* Output data */
+    AVBufferRef *out_data_ref;
+
+    /* Results data */
+    AVBufferRef *results_data_ref;
+
+    /* Copied from the source */
+    int64_t pts;
+    int64_t duration;
+    void        *frame_opaque;
+    AVBufferRef *frame_opaque_ref;
+
+    int key_frame;
+} VulkanEncodeFFv1FrameData;
+
+typedef struct VulkanEncodeFFv1Context {
+    FFV1Context ctx;
+    AVFrame *frame;
+
+    FFVulkanContext s;
+    AVVulkanDeviceQueueFamily *qf;
+    FFVkExecPool exec_pool;
+
+    AVVulkanDeviceQueueFamily *transfer_qf;
+    FFVkExecPool transfer_exec_pool;
+
+    VkBufferCopy *buf_regions;
+    VulkanEncodeFFv1FrameData *exec_ctx_info;
+    int in_flight;
+    int async_depth;
+    size_t max_heap_size;
+
+    FFVulkanShader setup;
+    FFVulkanShader rct_search;
+    FFVulkanShader reset;
+    FFVulkanShader enc;
+
+    /* Constant read-only buffers */
+    FFVkBuffer quant_buf;
+    FFVkBuffer rangecoder_static_buf;
+    FFVkBuffer crc_tab_buf;
+
+    /* Slice data buffer pool */
+    AVBufferPool *slice_data_pool;
+    AVBufferRef *keyframe_slice_data_ref;
+
+    /* Output data buffer */
+    AVBufferPool *out_data_pool;
+
+    /* Slice results buffer */
+    AVBufferPool *results_data_pool;
+
+    /* Intermediate frame pool */
+    AVBufferRef *intermediate_frames_ref;
+
+    /* Representation mode */
+    enum FFVkShaderRepFormat rep_fmt;
+
+    int num_h_slices;
+    int num_v_slices;
+    int force_pcm;
+    int optimize_rct;
+
+    int is_rgb;
+    int ppi;
+    int chunks;
+} VulkanEncodeFFv1Context;
+
+extern const char *ff_source_common_comp;
+extern const char *ff_source_rangecoder_comp;
+extern const char *ff_source_ffv1_vlc_comp;
+extern const char *ff_source_ffv1_common_comp;
+extern const char *ff_source_ffv1_reset_comp;
+extern const char *ff_source_ffv1_rct_search_comp;
+extern const char *ff_source_ffv1_enc_setup_comp;
+extern const char *ff_source_ffv1_enc_comp;
+
+typedef struct FFv1VkParameters {
+    VkDeviceAddress slice_state;
+    VkDeviceAddress scratch_data;
+    VkDeviceAddress out_data;
+
+    int32_t fmt_lut[4];
+    int32_t sar[2];
+    uint32_t chroma_shift[2];
+
+    uint32_t plane_state_size;
+    uint32_t context_count;
+    uint32_t crcref;
+    uint32_t slice_size_max;
+    int      rct_offset;
+
+    uint8_t extend_lookup[8];
+    uint8_t bits_per_raw_sample;
+    uint8_t context_model;
+    uint8_t version;
+    uint8_t micro_version;
+    uint8_t force_pcm;
+    uint8_t key_frame;
+    uint8_t components;
+    uint8_t planes;
+    uint8_t codec_planes;
+    uint8_t planar_rgb;
+    uint8_t transparency;
+    uint8_t colorspace;
+    uint8_t pic_mode;
+    uint8_t ec;
+    uint8_t ppi;
+    uint8_t chunks;
+    uint8_t rct_search;
+    uint8_t padding[3];
+} FFv1VkParameters;
+
+static void add_push_data(FFVulkanShader *shd)
+{
+    GLSLC(0, layout(push_constant, scalar) uniform pushConstants {            );
+    GLSLC(1,    u8buf slice_state;                                            );
+    GLSLC(1,    u8buf scratch_data;                                           );
+    GLSLC(1,    u8buf out_data;                                               );
+    GLSLC(0,                                                                  );
+    GLSLC(1,    ivec4 fmt_lut;                                                );
+    GLSLC(1,    ivec2 sar;                                                    );
+    GLSLC(1,    uvec2 chroma_shift;                                           );
+    GLSLC(0,                                                                  );
+    GLSLC(1,    uint plane_state_size;                                        );
+    GLSLC(1,    uint context_count;                                           );
+    GLSLC(1,    uint32_t crcref;                                              );
+    GLSLC(1,    uint32_t slice_size_max;                                      );
+    GLSLC(1,    int rct_offset;                                               );
+    GLSLC(0,                                                                  );
+    GLSLC(1,    uint8_t extend_lookup[8];                                     );
+    GLSLC(1,    uint8_t bits_per_raw_sample;                                  );
+    GLSLC(1,    uint8_t context_model;                                        );
+    GLSLC(1,    uint8_t version;                                              );
+    GLSLC(1,    uint8_t micro_version;                                        );
+    GLSLC(1,    uint8_t force_pcm;                                            );
+    GLSLC(1,    uint8_t key_frame;                                            );
+    GLSLC(1,    uint8_t components;                                           );
+    GLSLC(1,    uint8_t planes;                                               );
+    GLSLC(1,    uint8_t codec_planes;                                         );
+    GLSLC(1,    uint8_t planar_rgb;                                           );
+    GLSLC(1,    uint8_t transparency;                                         );
+    GLSLC(1,    uint8_t colorspace;                                           );
+    GLSLC(1,    uint8_t pic_mode;                                             );
+    GLSLC(1,    uint8_t ec;                                                   );
+    GLSLC(1,    uint8_t ppi;                                                  );
+    GLSLC(1,    uint8_t chunks;                                               );
+    GLSLC(1,    uint8_t rct_search;                                           );
+    GLSLC(1,    uint8_t padding[3];                                           );
+    GLSLC(0, };                                                               );
+    ff_vk_shader_add_push_const(shd, 0, sizeof(FFv1VkParameters),
+                                VK_SHADER_STAGE_COMPUTE_BIT);
+}
+
+typedef struct FFv1VkRCTSearchParameters {
+    int fmt_lut[4];
+    int rct_offset;
+    uint8_t planar_rgb;
+    uint8_t transparency;
+    uint8_t key_frame;
+    uint8_t force_pcm;
+    uint8_t version;
+    uint8_t micro_version;
+    uint8_t padding[2];
+} FFv1VkRCTSearchParameters;
+
+static int run_rct_search(AVCodecContext *avctx, FFVkExecContext *exec,
+                          AVFrame *enc_in, VkImageView *enc_in_views,
+                          FFVkBuffer *slice_data_buf, uint32_t slice_data_size)
+{
+    VulkanEncodeFFv1Context *fv = avctx->priv_data;
+    FFV1Context *f = &fv->ctx;
+    FFVulkanFunctions *vk = &fv->s.vkfn;
+    AVHWFramesContext *src_hwfc = (AVHWFramesContext *)enc_in->hw_frames_ctx->data;
+    FFv1VkRCTSearchParameters pd;
+
+    /* Update descriptors */
+    ff_vk_shader_update_desc_buffer(&fv->s, exec, &fv->rct_search,
+                                    0, 0, 0,
+                                    slice_data_buf,
+                                    0, slice_data_size*f->slice_count,
+                                    VK_FORMAT_UNDEFINED);
+    ff_vk_shader_update_img_array(&fv->s, exec, &fv->rct_search,
+                                  enc_in, enc_in_views,
+                                  0, 1,
+                                  VK_IMAGE_LAYOUT_GENERAL,
+                                  VK_NULL_HANDLE);
+
+    ff_vk_exec_bind_shader(&fv->s, exec, &fv->rct_search);
+
+    pd = (FFv1VkRCTSearchParameters) {
+        .rct_offset = 1 << f->bits_per_raw_sample,
+        .planar_rgb = ff_vk_mt_is_np_rgb(src_hwfc->sw_format) &&
+                      (ff_vk_count_images((AVVkFrame *)enc_in->data[0]) > 1),
+        .transparency = f->transparency,
+        .key_frame = f->key_frame,
+        .force_pcm = fv->force_pcm,
+        .version = f->version,
+        .micro_version = f->micro_version,
+    };
+
+    if (avctx->sw_pix_fmt == AV_PIX_FMT_GBRP10 ||
+        avctx->sw_pix_fmt == AV_PIX_FMT_GBRP12 ||
+        avctx->sw_pix_fmt == AV_PIX_FMT_GBRP14)
+        memcpy(pd.fmt_lut, (int [4]) { 2, 1, 0, 3 }, 4*sizeof(int));
+    else
+        ff_vk_set_perm(avctx->sw_pix_fmt, pd.fmt_lut, 1);
+
+    ff_vk_shader_update_push_const(&fv->s, exec, &fv->rct_search,
+                                   VK_SHADER_STAGE_COMPUTE_BIT,
+                                   0, sizeof(pd), &pd);
+
+    vk->CmdDispatch(exec->buf, fv->ctx.num_h_slices, fv->ctx.num_v_slices, 1);
+
+    return 0;
+}
+
+static int vulkan_encode_ffv1_submit_frame(AVCodecContext *avctx,
+                                           FFVkExecContext *exec,
+                                           const AVFrame *pict)
+{
+    int err;
+    VulkanEncodeFFv1Context *fv = avctx->priv_data;
+    FFV1Context *f = &fv->ctx;
+    FFVulkanFunctions *vk = &fv->s.vkfn;
+
+    VulkanEncodeFFv1FrameData *fd = exec->opaque;
+    FFv1VkParameters pd;
+
+    /* Slice data */
+    AVBufferRef *slice_data_ref;
+    FFVkBuffer *slice_data_buf;
+    uint32_t plane_state_size;
+    uint32_t slice_state_size;
+    uint32_t slice_data_size;
+
+    /* Output data */
+    size_t maxsize;
+    FFVkBuffer *out_data_buf;
+
+    /* Results data */
+    FFVkBuffer *results_data_buf;
+
+    int has_inter = avctx->gop_size > 1;
+    uint32_t context_count = f->context_count[f->context_model];
+    const AVPixFmtDescriptor *fmt_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt);
+
+    AVFrame *src = (AVFrame *)pict;
+    VkImageView src_views[AV_NUM_DATA_POINTERS];
+
+    AVFrame *tmp = NULL;
+    VkImageView tmp_views[AV_NUM_DATA_POINTERS];
+
+    VkImageMemoryBarrier2 img_bar[37];
+    int nb_img_bar = 0;
+    VkBufferMemoryBarrier2 buf_bar[8];
+    int nb_buf_bar = 0;
+
+    /* Start recording */
+    ff_vk_exec_start(&fv->s, exec);
+
+    /* Frame state */
+    f->cur_enc_frame = pict;
+    if (avctx->gop_size == 0 || f->picture_number % avctx->gop_size == 0) {
+        av_buffer_unref(&fv->keyframe_slice_data_ref);
+        f->key_frame = fd->key_frame = 1;
+        f->gob_count++;
+    } else {
+        f->key_frame = fd->key_frame = 0;
+    }
+
+    f->slice_count = f->max_slice_count;
+
+    /* Allocate slice buffer data */
+    if (f->ac == AC_GOLOMB_RICE)
+        plane_state_size = 8;
+    else
+        plane_state_size = CONTEXT_SIZE;
+
+    plane_state_size *= context_count;
+    slice_state_size = plane_state_size*f->plane_count;
+
+    slice_data_size = 256; /* Overestimation for the SliceContext struct */
+    slice_state_size += slice_data_size;
+    slice_state_size = FFALIGN(slice_state_size, 8);
+
+    /* Allocate slice data buffer */
+    slice_data_ref = fv->keyframe_slice_data_ref;
+    if (!slice_data_ref) {
+        RET(ff_vk_get_pooled_buffer(&fv->s, &fv->slice_data_pool,
+                                    &slice_data_ref,
+                                    VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
+                                    VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
+                                    NULL, slice_state_size*f->slice_count,
+                                    VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
+
+        /* Only save it if we're going to use it again */
+        if (has_inter)
+            fv->keyframe_slice_data_ref = slice_data_ref;
+    }
+    slice_data_buf = (FFVkBuffer *)slice_data_ref->data;
+    ff_vk_exec_add_dep_buf(&fv->s, exec, &slice_data_ref, 1, has_inter);
+
+    /* Allocate results buffer */
+    RET(ff_vk_get_pooled_buffer(&fv->s, &fv->results_data_pool,
+                                &fd->results_data_ref,
+                                VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
+                                VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
+                                NULL, 2*f->slice_count*sizeof(uint64_t),
+                                VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+                                VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
+    results_data_buf = (FFVkBuffer *)fd->results_data_ref->data;
+    ff_vk_exec_add_dep_buf(&fv->s, exec, &fd->results_data_ref, 1, 1);
+
+    /* Output buffer size */
+    maxsize = ff_ffv1_encode_buffer_size(avctx);
+    maxsize = FFMIN(maxsize, fv->s.props_11.maxMemoryAllocationSize);
+
+    /* Allocate output buffer */
+    RET(ff_vk_get_pooled_buffer(&fv->s, &fv->out_data_pool,
+                                &fd->out_data_ref,
+                                VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
+                                VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
+                                VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
+                                NULL, maxsize,
+                                VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+                                (maxsize < fv->max_heap_size ?
+                                 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT : 0x0) |
+                                (!(fv->s.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY) ?
+                                 VK_MEMORY_PROPERTY_HOST_CACHED_BIT : 0x0)));
+    out_data_buf = (FFVkBuffer *)fd->out_data_ref->data;
+    ff_vk_exec_add_dep_buf(&fv->s, exec, &fd->out_data_ref, 1, 1);
+
+    /* Prepare input frame */
+    RET(ff_vk_exec_add_dep_frame(&fv->s, exec, src,
+                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
+
+    RET(ff_vk_create_imageviews(&fv->s, exec, src_views, src,
+                                fv->rep_fmt));
+    ff_vk_frame_barrier(&fv->s, exec, src, img_bar, &nb_img_bar,
+                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                        VK_ACCESS_SHADER_READ_BIT,
+                        VK_IMAGE_LAYOUT_GENERAL,
+                        VK_QUEUE_FAMILY_IGNORED);
+
+    if (fv->is_rgb) {
+        /* Create a temporaty frame */
+        tmp = av_frame_alloc();
+        if (!(tmp))
+            return AVERROR(ENOMEM);
+
+        RET(av_hwframe_get_buffer(fv->intermediate_frames_ref,
+                                  tmp, 0));
+
+        RET(ff_vk_exec_add_dep_frame(&fv->s, exec, tmp,
+                                     VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                     VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
+        RET(ff_vk_create_imageviews(&fv->s, exec, tmp_views,
+                                    tmp,
+                                    fv->rep_fmt));
+    }
+
+    /* Setup shader */
+    ff_vk_shader_update_desc_buffer(&fv->s, exec, &fv->setup,
+                                    1, 0, 0,
+                                    slice_data_buf,
+                                    0, slice_data_size*f->slice_count,
+                                    VK_FORMAT_UNDEFINED);
+    ff_vk_shader_update_img_array(&fv->s, exec, &fv->setup,
+                                  src, src_views,
+                                  1, 1,
+                                  VK_IMAGE_LAYOUT_GENERAL,
+                                  VK_NULL_HANDLE);
+
+    /* Add a buffer barrier between previous and current frame */
+    if (!f->key_frame) {
+        buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
+            .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+            .srcStageMask = slice_data_buf->stage,
+            .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+            .srcAccessMask = slice_data_buf->access,
+            .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
+                             VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
+            .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+            .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+            .buffer = slice_data_buf->buf,
+            .size = VK_WHOLE_SIZE,
+            .offset = 0,
+        };
+    }
+
+    if (fv->optimize_rct) {
+        RET(run_rct_search(avctx, exec,
+                           src, src_views,
+                           slice_data_buf, slice_data_size));
+
+        buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
+            .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+            .srcStageMask = slice_data_buf->stage,
+            .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+            .srcAccessMask = slice_data_buf->access,
+            .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
+            .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+            .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+            .buffer = slice_data_buf->buf,
+            .size = slice_data_size*f->slice_count,
+            .offset = 0,
+        };
+    }
+
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+        .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+        .pImageMemoryBarriers = img_bar,
+        .imageMemoryBarrierCount = nb_img_bar,
+        .pBufferMemoryBarriers = buf_bar,
+        .bufferMemoryBarrierCount = nb_buf_bar,
+    });
+    nb_img_bar = 0;
+    if (nb_buf_bar) {
+        slice_data_buf->stage = buf_bar[0].dstStageMask;
+        slice_data_buf->access = buf_bar[0].dstAccessMask;
+        nb_buf_bar = 0;
+    }
+
+    /* Run setup shader */
+    ff_vk_exec_bind_shader(&fv->s, exec, &fv->setup);
+    pd = (FFv1VkParameters) {
+        .slice_state = slice_data_buf->address + f->slice_count*256,
+        .out_data = out_data_buf->address,
+        .bits_per_raw_sample = f->bits_per_raw_sample,
+        .sar[0] = pict->sample_aspect_ratio.num,
+        .sar[1] = pict->sample_aspect_ratio.den,
+        .chroma_shift[0] = f->chroma_h_shift,
+        .chroma_shift[1] = f->chroma_v_shift,
+        .plane_state_size = plane_state_size,
+        .context_count = context_count,
+        .crcref = f->crcref,
+        .rct_offset = 1 << f->bits_per_raw_sample,
+        .slice_size_max = out_data_buf->size / f->slice_count,
+        .context_model = fv->ctx.context_model,
+        .version = f->version,
+        .micro_version = f->micro_version,
+        .force_pcm = fv->force_pcm,
+        .key_frame = f->key_frame,
+        .components = fmt_desc->nb_components,
+        .planes = av_pix_fmt_count_planes(avctx->sw_pix_fmt),
+        .codec_planes = f->plane_count,
+        .planar_rgb = ff_vk_mt_is_np_rgb(avctx->sw_pix_fmt) &&
+                      (ff_vk_count_images((AVVkFrame *)src->data[0]) > 1),
+        .transparency = f->transparency,
+        .colorspace = f->colorspace,
+        .pic_mode = !(pict->flags & AV_FRAME_FLAG_INTERLACED) ? 3 :
+                    !(pict->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? 2 : 1,
+        .ec = f->ec,
+        .ppi = fv->ppi,
+        .chunks = fv->chunks,
+        .rct_search = fv->optimize_rct,
+    };
+
+    /* For some reason the C FFv1 encoder/decoder treats these differently */
+    if (avctx->sw_pix_fmt == AV_PIX_FMT_GBRP10 ||
+        avctx->sw_pix_fmt == AV_PIX_FMT_GBRP12 ||
+        avctx->sw_pix_fmt == AV_PIX_FMT_GBRP14)
+        memcpy(pd.fmt_lut, (int [4]) { 2, 1, 0, 3 }, 4*sizeof(int));
+    else
+        ff_vk_set_perm(avctx->sw_pix_fmt, pd.fmt_lut, 1);
+
+    for (int i = 0; i < f->quant_table_count; i++)
+        pd.extend_lookup[i] = (f->quant_tables[i][3][127] != 0) ||
+                              (f->quant_tables[i][4][127] != 0);
+    ff_vk_shader_update_push_const(&fv->s, exec, &fv->setup,
+                                   VK_SHADER_STAGE_COMPUTE_BIT,
+                                   0, sizeof(pd), &pd);
+    vk->CmdDispatch(exec->buf, fv->ctx.num_h_slices, fv->ctx.num_v_slices, 1);
+
+    /* Clean up temporary image */
+    if (fv->is_rgb) {
+        AVVkFrame *vkf = (AVVkFrame *)tmp->data[0];
+        vk->CmdClearColorImage(exec->buf, vkf->img[0], VK_IMAGE_LAYOUT_GENERAL,
+                               &((VkClearColorValue) { 0 }),
+                               1, &((VkImageSubresourceRange) {
+                                   .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+                                   .levelCount = 1,
+                                   .layerCount = 1,
+                               }));
+    }
+
+    /* Setup shader modified the slice data buffer */
+    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
+        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+        .srcStageMask = slice_data_buf->stage,
+        .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+        .srcAccessMask = slice_data_buf->access,
+        .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
+                         VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
+        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .buffer = slice_data_buf->buf,
+        .size = slice_data_size*f->slice_count,
+        .offset = 0,
+    };
+
+    if (f->key_frame || f->version > 3) {
+        FFv1VkResetParameters pd_reset;
+
+        ff_vk_shader_update_desc_buffer(&fv->s, exec, &fv->reset,
+                                        1, 0, 0,
+                                        slice_data_buf,
+                                        0, slice_data_size*f->slice_count,
+                                        VK_FORMAT_UNDEFINED);
+
+        /* Run setup shader */
+        ff_vk_exec_bind_shader(&fv->s, exec, &fv->reset);
+        pd_reset = (FFv1VkResetParameters) {
+            .slice_state = slice_data_buf->address + f->slice_count*256,
+            .plane_state_size = plane_state_size,
+            .codec_planes = f->plane_count,
+            .key_frame = f->key_frame,
+        };
+        for (int i = 0; i < f->quant_table_count; i++)
+            pd_reset.context_count[i] = f->context_count[i];
+
+        ff_vk_shader_update_push_const(&fv->s, exec, &fv->reset,
+                                       VK_SHADER_STAGE_COMPUTE_BIT,
+                                       0, sizeof(pd_reset), &pd_reset);
+
+        /* Sync between setup and reset shaders */
+        vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+            .pBufferMemoryBarriers = buf_bar,
+            .bufferMemoryBarrierCount = nb_buf_bar,
+        });
+        slice_data_buf->stage = buf_bar[0].dstStageMask;
+        slice_data_buf->access = buf_bar[0].dstAccessMask;
+        nb_buf_bar = 0;
+
+        vk->CmdDispatch(exec->buf, fv->ctx.num_h_slices, fv->ctx.num_v_slices,
+                        f->plane_count);
+    }
+
+    /* If the reset shader ran, insert a barrier now. */
+    if (f->key_frame || f->version > 3) {
+        /* Reset shader modified the slice data buffer */
+        buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
+            .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+            .srcStageMask = slice_data_buf->stage,
+            .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+            .srcAccessMask = slice_data_buf->access,
+            .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
+                             VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
+            .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+            .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+            .buffer = slice_data_buf->buf,
+            .size = slice_data_buf->size - slice_data_size*f->slice_count,
+            .offset = slice_data_size*f->slice_count,
+        };
+    }
+
+    if (fv->is_rgb) {
+        ff_vk_frame_barrier(&fv->s, exec, tmp, img_bar, &nb_img_bar,
+                            VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                            VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                            VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
+                            VK_IMAGE_LAYOUT_GENERAL,
+                            VK_QUEUE_FAMILY_IGNORED);
+    }
+
+    /* Final barrier before encoding */
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+        .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+        .pImageMemoryBarriers = img_bar,
+        .imageMemoryBarrierCount = nb_img_bar,
+        .pBufferMemoryBarriers = buf_bar,
+        .bufferMemoryBarrierCount = nb_buf_bar,
+    });
+    nb_img_bar = 0;
+    if (nb_buf_bar) {
+        slice_data_buf->stage = buf_bar[0].dstStageMask;
+        slice_data_buf->access = buf_bar[0].dstAccessMask;
+        nb_buf_bar = 0;
+    }
+
+    /* Main encode shader */
+    ff_vk_shader_update_desc_buffer(&fv->s, exec, &fv->enc,
+                                    1, 0, 0,
+                                    slice_data_buf,
+                                    0, slice_data_size*f->slice_count,
+                                    VK_FORMAT_UNDEFINED);
+    ff_vk_shader_update_img_array(&fv->s, exec, &fv->enc,
+                                  src, src_views,
+                                  1, 1,
+                                  VK_IMAGE_LAYOUT_GENERAL,
+                                  VK_NULL_HANDLE);
+    ff_vk_shader_update_desc_buffer(&fv->s, exec,
+                                    &fv->enc, 1, 2, 0,
+                                    results_data_buf,
+                                    0, results_data_buf->size,
+                                    VK_FORMAT_UNDEFINED);
+    if (fv->is_rgb)
+        ff_vk_shader_update_img_array(&fv->s, exec, &fv->enc,
+                                      tmp, tmp_views,
+                                      1, 3,
+                                      VK_IMAGE_LAYOUT_GENERAL,
+                                      VK_NULL_HANDLE);
+
+    ff_vk_exec_bind_shader(&fv->s, exec, &fv->enc);
+    ff_vk_shader_update_push_const(&fv->s, exec, &fv->enc,
+                                   VK_SHADER_STAGE_COMPUTE_BIT,
+                                   0, sizeof(pd), &pd);
+    vk->CmdDispatch(exec->buf, fv->ctx.num_h_slices, fv->ctx.num_v_slices, 1);
+
+    /* Submit */
+    err = ff_vk_exec_submit(&fv->s, exec);
+    if (err < 0)
+        return err;
+
+    f->picture_number++;
+
+    /* This, if needed, was referenced by the execution context
+     * as it was declared as a dependency. */
+    av_frame_free(&tmp);
+    return 0;
+
+fail:
+    av_frame_free(&tmp);
+    ff_vk_exec_discard_deps(&fv->s, exec);
+
+    return err;
+}
+
+static int transfer_slices(AVCodecContext *avctx,
+                           VkBufferCopy *buf_regions, int nb_regions,
+                           VulkanEncodeFFv1FrameData *fd,
+                           uint8_t *dst, AVBufferRef *dst_ref)
+{
+    int err;
+    VulkanEncodeFFv1Context *fv = avctx->priv_data;
+    FFVulkanFunctions *vk = &fv->s.vkfn;
+    FFVkExecContext *exec;
+
+    FFVkBuffer *out_data_buf = (FFVkBuffer *)fd->out_data_ref->data;
+
+    AVBufferRef *mapped_ref;
+    FFVkBuffer *mapped_buf;
+
+    VkBufferMemoryBarrier2 buf_bar[8];
+    int nb_buf_bar = 0;
+
+    err = ff_vk_host_map_buffer(&fv->s, &mapped_ref, dst, dst_ref,
+                                VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+    if (err < 0)
+        return err;
+
+    mapped_buf = (FFVkBuffer *)mapped_ref->data;
+
+    /* Transfer the slices */
+    exec = ff_vk_exec_get(&fv->s, &fv->transfer_exec_pool);
+    ff_vk_exec_start(&fv->s, exec);
+
+    ff_vk_exec_add_dep_buf(&fv->s, exec, &fd->out_data_ref, 1, 0);
+    fd->out_data_ref = NULL; /* Ownership passed */
+
+    ff_vk_exec_add_dep_buf(&fv->s, exec, &mapped_ref, 1, 0);
+    mapped_ref = NULL; /* Ownership passed */
+
+    /* Ensure the output buffer is finished */
+    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
+        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+        .srcStageMask = out_data_buf->stage,
+        .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
+        .srcAccessMask = out_data_buf->access,
+        .dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT,
+        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .buffer = out_data_buf->buf,
+        .size = VK_WHOLE_SIZE,
+        .offset = 0,
+    };
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+        .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+        .pBufferMemoryBarriers = buf_bar,
+        .bufferMemoryBarrierCount = nb_buf_bar,
+    });
+    out_data_buf->stage = buf_bar[0].dstStageMask;
+    out_data_buf->access = buf_bar[0].dstAccessMask;
+    nb_buf_bar = 0;
+
+    for (int i = 0; i < nb_regions; i++)
+        buf_regions[i].dstOffset += mapped_buf->virtual_offset;
+
+    vk->CmdCopyBuffer(exec->buf,
+                      out_data_buf->buf, mapped_buf->buf,
+                      nb_regions, buf_regions);
+
+    /* Submit */
+    err = ff_vk_exec_submit(&fv->s, exec);
+    if (err < 0)
+        return err;
+
+    /* We need the encoded data immediately */
+    ff_vk_exec_wait(&fv->s, exec);
+
+    return 0;
+}
+
+static int get_packet(AVCodecContext *avctx, FFVkExecContext *exec,
+                      AVPacket *pkt)
+{
+    int err;
+    VulkanEncodeFFv1Context *fv = avctx->priv_data;
+    FFV1Context *f = &fv->ctx;
+    FFVulkanFunctions *vk = &fv->s.vkfn;
+    VulkanEncodeFFv1FrameData *fd = exec->opaque;
+
+    FFVkBuffer *out_data_buf = (FFVkBuffer *)fd->out_data_ref->data;
+    FFVkBuffer *results_data_buf = (FFVkBuffer *)fd->results_data_ref->data;
+    uint64_t *sc;
+
+    /* Make sure encoding's done */
+    ff_vk_exec_wait(&fv->s, exec);
+
+    /* Invalidate slice/output data if needed */
+    if (!(results_data_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
+        VkMappedMemoryRange invalidate_data = {
+            .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+            .memory = results_data_buf->mem,
+            .offset = 0,
+            .size = VK_WHOLE_SIZE,
+        };
+        vk->InvalidateMappedMemoryRanges(fv->s.hwctx->act_dev,
+                                         1, &invalidate_data);
+    }
+
+    /* Calculate final size */
+    pkt->size = 0;
+    for (int i = 0; i < f->slice_count; i++) {
+        sc = &((uint64_t *)results_data_buf->mapped_mem)[i*2];
+        av_log(avctx, AV_LOG_DEBUG, "Slice %i size = %"PRIu64", "
+                                    "src offset = %"PRIu64"\n",
+               i, sc[0], sc[1]);
+
+        fv->buf_regions[i] = (VkBufferCopy) {
+            .srcOffset = sc[1],
+            .dstOffset = pkt->size,
+            .size = sc[0],
+        };
+        pkt->size += sc[0];
+    }
+    av_log(avctx, AV_LOG_VERBOSE, "Encoded data: %iMiB\n", pkt->size / (1024*1024));
+    av_buffer_unref(&fd->results_data_ref); /* No need for this buffer anymore */
+
+    /* Allocate packet */
+    if ((err = ff_get_encode_buffer(avctx, pkt, pkt->size, 0)) < 0)
+        return err;
+
+    pkt->pts      = fd->pts;
+    pkt->dts      = fd->pts;
+    pkt->duration = fd->duration;
+    pkt->flags   |= AV_PKT_FLAG_KEY * fd->key_frame;
+
+    if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
+        pkt->opaque          = fd->frame_opaque;
+        pkt->opaque_ref      = fd->frame_opaque_ref;
+        fd->frame_opaque_ref = NULL;
+    }
+
+    /* Try using host mapped memory transfers first */
+    if (fv->s.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY) {
+        err = transfer_slices(avctx, fv->buf_regions, f->slice_count, fd,
+                              pkt->data, pkt->buf);
+        if (err >= 0)
+            return err;
+    }
+
+    /* Invalidate slice/output data if needed */
+    if (!(out_data_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
+        VkMappedMemoryRange invalidate_data = {
+            .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+            .memory = out_data_buf->mem,
+            .offset = 0,
+            .size = VK_WHOLE_SIZE,
+        };
+        vk->InvalidateMappedMemoryRanges(fv->s.hwctx->act_dev,
+                                         1, &invalidate_data);
+    }
+
+    /* Copy each slice */
+    for (int i = 0; i < f->slice_count; i++) {
+        VkBufferCopy *region = &fv->buf_regions[i];
+        memcpy(pkt->data + region->dstOffset,
+               out_data_buf->mapped_mem + region->srcOffset,
+               region->size);
+    }
+
+    av_buffer_unref(&fd->out_data_ref);
+
+    return 0;
+}
+
+static int vulkan_encode_ffv1_receive_packet(AVCodecContext *avctx,
+                                             AVPacket *pkt)
+{
+    int err;
+    VulkanEncodeFFv1Context *fv = avctx->priv_data;
+    VulkanEncodeFFv1FrameData *fd;
+    FFVkExecContext *exec;
+    AVFrame *frame;
+
+    while (1) {
+        /* Roll an execution context */
+        exec = ff_vk_exec_get(&fv->s, &fv->exec_pool);
+
+        /* If it had a frame, immediately output it */
+        if (exec->had_submission) {
+            exec->had_submission = 0;
+            fv->in_flight--;
+            return get_packet(avctx, exec, pkt);
+        }
+
+        /* Get next frame to encode */
+        frame = fv->frame;
+        err = ff_encode_get_frame(avctx, frame);
+        if (err < 0 && err != AVERROR_EOF) {
+            return err;
+        } else if (err == AVERROR_EOF) {
+            if (!fv->in_flight)
+                return err;
+            continue;
+        }
+
+        /* Encode frame */
+        fd = exec->opaque;
+        fd->pts = frame->pts;
+        fd->duration = frame->duration;
+        if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
+            fd->frame_opaque     = frame->opaque;
+            fd->frame_opaque_ref = frame->opaque_ref;
+            frame->opaque_ref    = NULL;
+        }
+
+        err = vulkan_encode_ffv1_submit_frame(avctx, exec, frame);
+        av_frame_unref(frame);
+        if (err < 0)
+            return err;
+
+        fv->in_flight++;
+        if (fv->in_flight < fv->async_depth)
+            return AVERROR(EAGAIN);
+    }
+
+    return 0;
+}
+
+static int init_indirect(AVCodecContext *avctx, enum AVPixelFormat sw_format)
+{
+    int err;
+    VulkanEncodeFFv1Context *fv = avctx->priv_data;
+    FFV1Context *f = &fv->ctx;
+    AVHWFramesContext *frames_ctx;
+    AVVulkanFramesContext *vk_frames;
+
+    fv->intermediate_frames_ref = av_hwframe_ctx_alloc(fv->s.device_ref);
+    if (!fv->intermediate_frames_ref)
+        return AVERROR(ENOMEM);
+
+    frames_ctx = (AVHWFramesContext *)fv->intermediate_frames_ref->data;
+    frames_ctx->format    = AV_PIX_FMT_VULKAN;
+    frames_ctx->sw_format = sw_format;
+    frames_ctx->width     = fv->s.frames->width;
+    frames_ctx->height    = f->num_v_slices*RGB_LINECACHE;
+
+    vk_frames = frames_ctx->hwctx;
+    vk_frames->tiling    = VK_IMAGE_TILING_OPTIMAL;
+    vk_frames->usage     = VK_IMAGE_USAGE_STORAGE_BIT |
+                           VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+    vk_frames->img_flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
+
+    err = av_hwframe_ctx_init(fv->intermediate_frames_ref);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to initialize frame pool with format %s: %s\n",
+               av_get_pix_fmt_name(sw_format), av_err2str(err));
+        av_buffer_unref(&fv->intermediate_frames_ref);
+        return err;
+    }
+
+    return 0;
+}
+
+static int check_support(AVHWFramesConstraints *constraints,
+                         enum AVPixelFormat fmt)
+{
+    for (int i = 0; constraints->valid_sw_formats[i]; i++) {
+        if (constraints->valid_sw_formats[i] == fmt)
+            return 1;
+    }
+    return 0;
+}
+
+static enum AVPixelFormat get_supported_rgb_buffer_fmt(AVCodecContext *avctx)
+{
+    VulkanEncodeFFv1Context *fv = avctx->priv_data;
+
+    enum AVPixelFormat fmt;
+    AVHWFramesConstraints *constraints;
+    constraints = av_hwdevice_get_hwframe_constraints(fv->s.device_ref,
+                                                      NULL);
+
+    /* What we'd like to optimally have */
+    fmt = fv->ctx.use32bit ?
+          (fv->ctx.transparency ? AV_PIX_FMT_RGBA128 : AV_PIX_FMT_RGB96) :
+          (fv->ctx.transparency ? AV_PIX_FMT_RGBA64  : AV_PIX_FMT_RGB48);
+    if (check_support(constraints, fmt))
+        goto end;
+
+    if (fv->ctx.use32bit) {
+        if (check_support(constraints, (fmt = AV_PIX_FMT_RGBA128)))
+            goto end;
+    } else {
+        if (check_support(constraints, (fmt = AV_PIX_FMT_RGBA64)))
+            goto end;
+
+        if (!fv->ctx.transparency &&
+            check_support(constraints, (fmt = AV_PIX_FMT_RGB96)))
+                goto end;
+
+        if (check_support(constraints, (fmt = AV_PIX_FMT_RGBA128)))
+            goto end;
+    }
+
+    fmt = AV_PIX_FMT_NONE;
+
+end:
+    av_hwframe_constraints_free(&constraints);
+    return fmt;
+}
+
+static void define_shared_code(AVCodecContext *avctx, FFVulkanShader *shd)
+{
+    VulkanEncodeFFv1Context *fv = avctx->priv_data;
+    FFV1Context *f = &fv->ctx;
+    int smp_bits = fv->ctx.use32bit ? 32 : 16;
+
+    av_bprintf(&shd->src, "#define RGB_LINECACHE %i\n"                   ,RGB_LINECACHE);
+    av_bprintf(&shd->src, "#define CONTEXT_SIZE %i\n"                    ,CONTEXT_SIZE);
+    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_MASK 0x%x\n"          ,MAX_QUANT_TABLE_MASK);
+
+    if (f->ac == AC_GOLOMB_RICE) {
+        av_bprintf(&shd->src, "#define PB_UNALIGNED\n"                   );
+        av_bprintf(&shd->src, "#define GOLOMB\n"                         );
+    }
+
+    if (fv->is_rgb)
+        av_bprintf(&shd->src, "#define RGB\n");
+
+    GLSLF(0, #define TYPE int%i_t                                        ,smp_bits);
+    GLSLF(0, #define VTYPE2 i%ivec2                                      ,smp_bits);
+    GLSLF(0, #define VTYPE3 i%ivec3                                      ,smp_bits);
+    GLSLD(ff_source_rangecoder_comp);
+
+    if (f->ac == AC_GOLOMB_RICE)
+        GLSLD(ff_source_ffv1_vlc_comp);
+
+    GLSLD(ff_source_ffv1_common_comp);
+}
+
+static int init_rct_search_shader(AVCodecContext *avctx, FFVkSPIRVCompiler *spv)
+{
+    int err;
+    VulkanEncodeFFv1Context *fv = avctx->priv_data;
+    FFV1Context *f = &fv->ctx;
+    FFVulkanShader *shd = &fv->rct_search;
+    FFVulkanDescriptorSetBinding *desc_set;
+
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+
+    RET(ff_vk_shader_init(&fv->s, shd, "ffv1_rct_search",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          (const char *[]) { "GL_EXT_buffer_reference",
+                                             "GL_EXT_buffer_reference2",
+                                             "GL_EXT_null_initializer" }, 3,
+                          32, 32, 1,
+                          0));
+
+    /* Common codec header */
+    GLSLD(ff_source_common_comp);
+
+    GLSLC(0, layout(push_constant, scalar) uniform pushConstants {             );
+    GLSLC(1,    ivec4 fmt_lut;                                                 );
+    GLSLC(1,    int rct_offset;                                                );
+    GLSLC(1,    uint8_t planar_rgb;                                            );
+    GLSLC(1,    uint8_t transparency;                                          );
+    GLSLC(1,    uint8_t key_frame;                                             );
+    GLSLC(1,    uint8_t force_pcm;                                             );
+    GLSLC(1,    uint8_t version;                                               );
+    GLSLC(1,    uint8_t micro_version;                                         );
+    GLSLC(1,    uint8_t padding[3];                                            );
+    GLSLC(0, };                                                                );
+    ff_vk_shader_add_push_const(shd, 0, sizeof(FFv1VkResetParameters),
+                                VK_SHADER_STAGE_COMPUTE_BIT);
+
+    av_bprintf(&shd->src, "#define MAX_QUANT_TABLES %i\n", MAX_QUANT_TABLES);
+    av_bprintf(&shd->src, "#define MAX_CONTEXT_INPUTS %i\n", MAX_CONTEXT_INPUTS);
+    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_SIZE %i\n", MAX_QUANT_TABLE_SIZE);
+
+    /* Never used */
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "rangecoder_static_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "uint8_t zero_one_state[512];",
+        },
+        {
+            .name        = "quant_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "int16_t quant_table[MAX_QUANT_TABLES]"
+                           "[MAX_CONTEXT_INPUTS][MAX_QUANT_TABLE_SIZE];",
+        },
+    };
+    RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 2, 1, 1));
+
+    define_shared_code(avctx, shd);
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "slice_data_buf",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "SliceContext slice_ctx",
+            .buf_elems   = f->max_slice_count,
+        },
+        {
+            .name       = "src",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .dimensions = 2,
+            .mem_layout = ff_vk_shader_rep_fmt(fv->s.frames->sw_format,
+                                               fv->rep_fmt),
+            .elems      = av_pix_fmt_count_planes(fv->s.frames->sw_format),
+            .mem_quali  = "readonly",
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+    };
+    RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 2, 0, 0));
+
+    GLSLD(ff_source_ffv1_rct_search_comp);
+
+    RET(spv->compile_shader(&fv->s, spv, shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(&fv->s, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(&fv->s, &fv->exec_pool, shd));
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+
+    return err;
+}
+
+static int init_setup_shader(AVCodecContext *avctx, FFVkSPIRVCompiler *spv)
+{
+    int err;
+    VulkanEncodeFFv1Context *fv = avctx->priv_data;
+    FFV1Context *f = &fv->ctx;
+    FFVulkanShader *shd = &fv->setup;
+    FFVulkanDescriptorSetBinding *desc_set;
+
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+
+    RET(ff_vk_shader_init(&fv->s, shd, "ffv1_setup",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          (const char *[]) { "GL_EXT_buffer_reference",
+                                             "GL_EXT_buffer_reference2" }, 2,
+                          1, 1, 1,
+                          0));
+
+    /* Common codec header */
+    GLSLD(ff_source_common_comp);
+    add_push_data(shd);
+
+    av_bprintf(&shd->src, "#define MAX_QUANT_TABLES %i\n", MAX_QUANT_TABLES);
+    av_bprintf(&shd->src, "#define MAX_CONTEXT_INPUTS %i\n", MAX_CONTEXT_INPUTS);
+    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_SIZE %i\n", MAX_QUANT_TABLE_SIZE);
+    av_bprintf(&shd->src, "#define FULL_RENORM\n");
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "rangecoder_static_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "uint8_t zero_one_state[512];",
+        },
+        { /* This descriptor is never used */
+            .name        = "quant_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "int16_t quant_table[MAX_QUANT_TABLES]"
+                           "[MAX_CONTEXT_INPUTS][MAX_QUANT_TABLE_SIZE];",
+        },
+    };
+    RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 2, 1, 0));
+
+    define_shared_code(avctx, shd);
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "slice_data_buf",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "SliceContext slice_ctx",
+            .buf_elems   = f->max_slice_count,
+        },
+        {
+            .name       = "src",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .dimensions = 2,
+            .mem_layout = ff_vk_shader_rep_fmt(fv->s.frames->sw_format,
+                                               fv->rep_fmt),
+            .elems      = av_pix_fmt_count_planes(fv->s.frames->sw_format),
+            .mem_quali  = "readonly",
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+    };
+    RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 2, 0, 0));
+
+    GLSLD(ff_source_ffv1_enc_setup_comp);
+
+    RET(spv->compile_shader(&fv->s, spv, shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(&fv->s, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(&fv->s, &fv->exec_pool, shd));
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+
+    return err;
+}
+
+static int init_reset_shader(AVCodecContext *avctx, FFVkSPIRVCompiler *spv)
+{
+    int err;
+    VulkanEncodeFFv1Context *fv = avctx->priv_data;
+    FFV1Context *f = &fv->ctx;
+    FFVulkanShader *shd = &fv->reset;
+    FFVulkanDescriptorSetBinding *desc_set;
+
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    int wg_dim = FFMIN(fv->s.props.properties.limits.maxComputeWorkGroupSize[0], 1024);
+
+    RET(ff_vk_shader_init(&fv->s, shd, "ffv1_reset",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          (const char *[]) { "GL_EXT_buffer_reference",
+                                             "GL_EXT_buffer_reference2" }, 2,
+                          wg_dim, 1, 1,
+                          0));
+
+    /* Common codec header */
+    GLSLD(ff_source_common_comp);
+
+    GLSLC(0, layout(push_constant, scalar) uniform pushConstants {             );
+    GLSLF(1,    uint context_count[%i];                                        ,MAX_QUANT_TABLES);
+    GLSLC(1,    u8buf slice_state;                                             );
+    GLSLC(1,    uint plane_state_size;                                         );
+    GLSLC(1,    uint8_t codec_planes;                                          );
+    GLSLC(1,    uint8_t key_frame;                                             );
+    GLSLC(1,    uint8_t version;                                               );
+    GLSLC(1,    uint8_t micro_version;                                         );
+    GLSLC(1,    uint8_t padding[1];                                            );
+    GLSLC(0, };                                                                );
+    ff_vk_shader_add_push_const(shd, 0, sizeof(FFv1VkResetParameters),
+                                VK_SHADER_STAGE_COMPUTE_BIT);
+
+    av_bprintf(&shd->src, "#define MAX_QUANT_TABLES %i\n", MAX_QUANT_TABLES);
+    av_bprintf(&shd->src, "#define MAX_CONTEXT_INPUTS %i\n", MAX_CONTEXT_INPUTS);
+    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_SIZE %i\n", MAX_QUANT_TABLE_SIZE);
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "rangecoder_static_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "uint8_t zero_one_state[512];",
+        },
+        {
+            .name        = "quant_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "int16_t quant_table[MAX_QUANT_TABLES]"
+                           "[MAX_CONTEXT_INPUTS][MAX_QUANT_TABLE_SIZE];",
+        },
+    };
+    RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 2, 1, 0));
+
+    define_shared_code(avctx, shd);
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "slice_data_buf",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .mem_quali   = "readonly",
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "SliceContext slice_ctx",
+            .buf_elems   = f->max_slice_count,
+        },
+    };
+    RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 1, 0, 0));
+
+    GLSLD(ff_source_ffv1_reset_comp);
+
+    RET(spv->compile_shader(&fv->s, spv, shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(&fv->s, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(&fv->s, &fv->exec_pool, shd));
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+
+    return err;
+}
+
+static int init_encode_shader(AVCodecContext *avctx, FFVkSPIRVCompiler *spv)
+{
+    int err;
+    VulkanEncodeFFv1Context *fv = avctx->priv_data;
+    FFV1Context *f = &fv->ctx;
+    FFVulkanShader *shd = &fv->enc;
+    FFVulkanDescriptorSetBinding *desc_set;
+
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    int use_cached_reader = fv->ctx.ac != AC_GOLOMB_RICE;
+
+    RET(ff_vk_shader_init(&fv->s, shd, "ffv1_enc",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          (const char *[]) { "GL_EXT_buffer_reference",
+                                             "GL_EXT_buffer_reference2" }, 2,
+                          use_cached_reader ? CONTEXT_SIZE : 1, 1, 1,
+                          0));
+
+    /* Common codec header */
+    GLSLD(ff_source_common_comp);
+
+    add_push_data(shd);
+
+    av_bprintf(&shd->src, "#define MAX_QUANT_TABLES %i\n", MAX_QUANT_TABLES);
+    av_bprintf(&shd->src, "#define MAX_CONTEXT_INPUTS %i\n", MAX_CONTEXT_INPUTS);
+    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_SIZE %i\n", MAX_QUANT_TABLE_SIZE);
+
+    if (use_cached_reader)
+        av_bprintf(&shd->src, "#define CACHED_SYMBOL_READER 1\n");
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "rangecoder_static_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "uint8_t zero_one_state[512];",
+        },
+        {
+            .name        = "quant_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "int16_t quant_table[MAX_QUANT_TABLES]"
+                           "[MAX_CONTEXT_INPUTS][MAX_QUANT_TABLE_SIZE];",
+        },
+        {
+            .name        = "crc_ieee_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "uint32_t crc_ieee[256];",
+        },
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 3, 1, 0));
+
+    define_shared_code(avctx, shd);
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "slice_data_buf",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "SliceContext slice_ctx",
+            .buf_elems   = f->max_slice_count,
+        },
+        {
+            .name       = "src",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .dimensions = 2,
+            .mem_layout = ff_vk_shader_rep_fmt(fv->s.frames->sw_format,
+                                               fv->rep_fmt),
+            .elems      = av_pix_fmt_count_planes(fv->s.frames->sw_format),
+            .mem_quali  = "readonly",
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+        {
+            .name        = "results_data_buf",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_quali   = "writeonly",
+            .buf_content = "uint64_t slice_results[2048];",
+        },
+        { /* place holder for desc_set[3] */
+        },
+    };
+    if (fv->is_rgb) {
+        AVHWFramesContext *intermediate_frames_ctx;
+        intermediate_frames_ctx = (AVHWFramesContext *)fv->intermediate_frames_ref->data;
+        desc_set[3] = (FFVulkanDescriptorSetBinding) {
+            .name       = "tmp",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .dimensions = 2,
+            .mem_layout = ff_vk_shader_rep_fmt(intermediate_frames_ctx->sw_format,
+                                               FF_VK_REP_NATIVE),
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        };
+    }
+    RET(ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set, 3 + fv->is_rgb, 0, 0));
+
+    GLSLD(ff_source_ffv1_enc_comp);
+
+    RET(spv->compile_shader(&fv->s, spv, shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(&fv->s, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(&fv->s, &fv->exec_pool, shd));
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+
+    return err;
+}
+
+static av_cold int vulkan_encode_ffv1_init(AVCodecContext *avctx)
+{
+    int err;
+    size_t maxsize, max_heap_size, max_host_size;
+    VulkanEncodeFFv1Context *fv = avctx->priv_data;
+    FFV1Context *f = &fv->ctx;
+    FFVkSPIRVCompiler *spv;
+
+    if ((err = ff_ffv1_common_init(avctx, f)) < 0)
+        return err;
+
+    if (f->ac == 1)
+        f->ac = AC_RANGE_CUSTOM_TAB;
+
+    err = ff_ffv1_encode_setup_plane_info(avctx, avctx->sw_pix_fmt);
+    if (err < 0)
+        return err;
+
+    /* Target version 3 by default */
+    f->version = 3;
+
+    err = ff_ffv1_encode_init(avctx);
+    if (err < 0)
+        return err;
+
+    /* Rice coding did not support high bit depths */
+    if (f->bits_per_raw_sample > (f->version > 3 ? 16 : 8)) {
+        if (f->ac == AC_GOLOMB_RICE) {
+            av_log(avctx, AV_LOG_WARNING, "bits_per_raw_sample > 8, "
+                                          "forcing range coder\n");
+            f->ac = AC_RANGE_CUSTOM_TAB;
+        }
+    }
+
+    if (f->version < 4 && avctx->gop_size > 1) {
+        av_log(avctx, AV_LOG_ERROR, "Using inter frames requires version 4 (-level 4)\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    if (f->version == 4 && avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
+        av_log(avctx, AV_LOG_ERROR, "Version 4 is experimental and requires -strict -2\n");
+            return AVERROR_INVALIDDATA;
+    }
+
+    /* We target version 4.3 */
+    if (f->version == 4 && f->micro_version > 4)
+        f->micro_version = 3;
+
+    //if (fv->ctx.ac == AC_GOLOMB_RICE) {
+    if (0) {
+        int w_a = FFALIGN(avctx->width, LG_ALIGN_W);
+        int h_a = FFALIGN(avctx->height, LG_ALIGN_H);
+        int w_sl, h_sl;
+
+        /* Pixels per line an invocation handles */
+        int ppi = 0;
+        /* Chunk size */
+        int chunks = 0;
+
+        do {
+            if (ppi < 2)
+                ppi++;
+            chunks++;
+            w_sl = w_a / (LG_ALIGN_W*ppi);
+            h_sl = h_a / (LG_ALIGN_H*chunks);
+        } while (w_sl > MAX_SLICES / h_sl);
+
+        av_log(avctx, AV_LOG_VERBOSE, "Slice config: %ix%i, %i total\n",
+               LG_ALIGN_W*ppi, LG_ALIGN_H*chunks, w_sl*h_sl);
+        av_log(avctx, AV_LOG_VERBOSE, "Horizontal slices: %i (%i pixels per invoc)\n",
+               w_sl, ppi);
+        av_log(avctx, AV_LOG_VERBOSE, "Vertical slices: %i (%i chunks)\n",
+               h_sl, chunks);
+
+        f->num_h_slices = w_sl;
+        f->num_v_slices = h_sl;
+
+        fv->ppi = ppi;
+        fv->chunks = chunks;
+    } else {
+        f->num_h_slices = fv->num_h_slices;
+        f->num_v_slices = fv->num_v_slices;
+
+        if (f->num_h_slices <= 0 && f->num_v_slices <= 0) {
+            if (avctx->slices) {
+                err = ff_ffv1_encode_determine_slices(avctx);
+                if (err < 0)
+                    return err;
+            } else {
+                f->num_h_slices = 32;
+                f->num_v_slices = 32;
+            }
+        } else if (f->num_h_slices && f->num_v_slices <= 0) {
+            f->num_v_slices = MAX_SLICES / f->num_h_slices;
+        } else if (f->num_v_slices && f->num_h_slices <= 0) {
+            f->num_h_slices = MAX_SLICES / f->num_v_slices;
+        }
+
+        f->num_h_slices = FFMIN(f->num_h_slices, avctx->width);
+        f->num_v_slices = FFMIN(f->num_v_slices, avctx->height);
+
+        if (f->num_h_slices * f->num_v_slices > MAX_SLICES) {
+            av_log(avctx, AV_LOG_ERROR, "Too many slices (%i), maximum supported "
+                                        "by the standard is %i\n",
+                   f->num_h_slices * f->num_v_slices, MAX_SLICES);
+            return AVERROR_PATCHWELCOME;
+        }
+    }
+
+    f->max_slice_count = f->num_h_slices * f->num_v_slices;
+
+    if ((err = ff_ffv1_write_extradata(avctx)) < 0)
+        return err;
+
+    if (f->version < 4) {
+        if (((f->chroma_h_shift > 0) && (avctx->width % (64 << f->chroma_h_shift))) ||
+            ((f->chroma_v_shift > 0) && (avctx->height % (64 << f->chroma_v_shift)))) {
+            av_log(avctx, AV_LOG_ERROR, "Encoding frames with subsampling and unaligned "
+                                        "dimensions is only supported in version 4 (-level 4)\n");
+            return AVERROR_PATCHWELCOME;
+        }
+    }
+
+    if (fv->force_pcm) {
+        if (f->version < 4) {
+            av_log(avctx, AV_LOG_ERROR, "PCM coding only supported by version 4 (-level 4)\n");
+            return AVERROR_INVALIDDATA;
+        } else if (f->ac == AC_GOLOMB_RICE) {
+            av_log(avctx, AV_LOG_ERROR, "PCM coding requires range coding\n");
+            return AVERROR_INVALIDDATA;
+        }
+    }
+
+    /* Init Vulkan */
+    err = ff_vk_init(&fv->s, avctx, NULL, avctx->hw_frames_ctx);
+    if (err < 0)
+        return err;
+
+    fv->qf = ff_vk_qf_find(&fv->s, VK_QUEUE_COMPUTE_BIT, 0);
+    if (!fv->qf) {
+        av_log(avctx, AV_LOG_ERROR, "Device has no compute queues!\n");
+        return err;
+    }
+
+    /* Try to measure VRAM size */
+    max_heap_size = 0;
+    max_host_size = 0;
+    for (int i = 0; i < fv->s.mprops.memoryHeapCount; i++) {
+        if (fv->s.mprops.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
+            max_heap_size = FFMAX(fv->max_heap_size,
+                                  fv->s.mprops.memoryHeaps[i].size);
+        if (!(fv->s.mprops.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT))
+            max_host_size = FFMAX(max_host_size,
+                                  fv->s.mprops.memoryHeaps[i].size);
+    }
+    fv->max_heap_size = max_heap_size;
+
+    maxsize = ff_ffv1_encode_buffer_size(avctx);
+    if (maxsize > fv->s.props_11.maxMemoryAllocationSize) {
+        av_log(avctx, AV_LOG_WARNING, "Encoding buffer size (%"SIZE_SPECIFIER") larger "
+                                      "than maximum device allocation (%"SIZE_SPECIFIER"), clipping\n",
+               maxsize, fv->s.props_11.maxMemoryAllocationSize);
+        maxsize = fv->s.props_11.maxMemoryAllocationSize;
+    }
+
+    if (max_heap_size < maxsize) {
+        av_log(avctx, AV_LOG_WARNING, "Encoding buffer (%"SIZE_SPECIFIER") larger than VRAM (%"SIZE_SPECIFIER"), "
+                                      "using host memory (slower)\n",
+               maxsize, fv->max_heap_size);
+
+        /* Keep 1/2th of RAM as headroom */
+        max_heap_size = max_host_size - (max_host_size >> 1);
+    } else {
+        /* Keep 1/8th of VRAM as headroom */
+        max_heap_size = max_heap_size - (max_heap_size >> 3);
+    }
+
+    av_log(avctx, AV_LOG_INFO, "Async buffers: %"SIZE_SPECIFIER"MiB per context, %"SIZE_SPECIFIER"MiB total, depth: %i\n",
+           maxsize / (1024*1024),
+           (fv->async_depth * maxsize) / (1024*1024),
+           fv->async_depth);
+
+    err = ff_vk_exec_pool_init(&fv->s, fv->qf, &fv->exec_pool,
+                               fv->async_depth,
+                               0, 0, 0, NULL);
+    if (err < 0)
+        return err;
+
+    fv->transfer_qf = ff_vk_qf_find(&fv->s, VK_QUEUE_TRANSFER_BIT, 0);
+    if (!fv->transfer_qf) {
+        av_log(avctx, AV_LOG_ERROR, "Device has no transfer queues!\n");
+        return err;
+    }
+
+    err = ff_vk_exec_pool_init(&fv->s, fv->transfer_qf, &fv->transfer_exec_pool,
+                               1,
+                               0, 0, 0, NULL);
+    if (err < 0)
+        return err;
+
+    spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    /* Detect the special RGB coding mode */
+    fv->is_rgb = !(f->colorspace == 0 && avctx->sw_pix_fmt != AV_PIX_FMT_YA8) &&
+                 !(avctx->sw_pix_fmt == AV_PIX_FMT_YA8);
+
+    /* bits_per_raw_sample use regular unsigned representation,
+     * but in higher bit depths, the data is casted to int16_t */
+    fv->rep_fmt = FF_VK_REP_UINT;
+    if (!fv->is_rgb && f->bits_per_raw_sample > 8)
+        fv->rep_fmt = FF_VK_REP_INT;
+
+    /* Init rct search shader */
+    fv->optimize_rct = fv->is_rgb && f->version >= 4 &&
+                       !fv->force_pcm && fv->optimize_rct;
+    if (fv->optimize_rct) {
+        err = init_rct_search_shader(avctx, spv);
+        if (err < 0) {
+            spv->uninit(&spv);
+            return err;
+        }
+    }
+
+    /* Init setup shader */
+    err = init_setup_shader(avctx, spv);
+    if (err < 0) {
+        spv->uninit(&spv);
+        return err;
+    }
+
+    /* Init reset shader */
+    err = init_reset_shader(avctx, spv);
+    if (err < 0) {
+        spv->uninit(&spv);
+        return err;
+    }
+
+    if (fv->is_rgb) {
+        enum AVPixelFormat intermediate_fmt = get_supported_rgb_buffer_fmt(avctx);
+        if (intermediate_fmt == AV_PIX_FMT_NONE) {
+            av_log(avctx, AV_LOG_ERROR, "Unable to find a supported compatible "
+                                        "pixel format for RCT buffer!\n");
+            return AVERROR(ENOTSUP);
+        }
+
+        RET(init_indirect(avctx, intermediate_fmt));
+    }
+
+    /* Encode shader */
+    err = init_encode_shader(avctx, spv);
+    if (err < 0) {
+        spv->uninit(&spv);
+        return err;
+    }
+
+    spv->uninit(&spv);
+
+    /* Range coder data */
+    err = ff_ffv1_vk_init_state_transition_data(&fv->s,
+                                                &fv->rangecoder_static_buf,
+                                                f);
+    if (err < 0)
+        return err;
+
+    /* Quantization table data */
+    err = ff_ffv1_vk_init_quant_table_data(&fv->s,
+                                           &fv->quant_buf,
+                                           f);
+    if (err < 0)
+        return err;
+
+    /* CRC table buffer */
+    err = ff_ffv1_vk_init_crc_table_data(&fv->s,
+                                         &fv->crc_tab_buf,
+                                         f);
+    if (err < 0)
+        return err;
+
+    /* Update setup global descriptors */
+    RET(ff_vk_shader_update_desc_buffer(&fv->s, &fv->exec_pool.contexts[0],
+                                        &fv->setup, 0, 0, 0,
+                                        &fv->rangecoder_static_buf,
+                                        0, fv->rangecoder_static_buf.size,
+                                        VK_FORMAT_UNDEFINED));
+
+    /* Update encode global descriptors */
+    RET(ff_vk_shader_update_desc_buffer(&fv->s, &fv->exec_pool.contexts[0],
+                                        &fv->enc, 0, 0, 0,
+                                        &fv->rangecoder_static_buf,
+                                        0, fv->rangecoder_static_buf.size,
+                                        VK_FORMAT_UNDEFINED));
+    RET(ff_vk_shader_update_desc_buffer(&fv->s, &fv->exec_pool.contexts[0],
+                                        &fv->enc, 0, 1, 0,
+                                        &fv->quant_buf,
+                                        0, fv->quant_buf.size,
+                                        VK_FORMAT_UNDEFINED));
+    RET(ff_vk_shader_update_desc_buffer(&fv->s, &fv->exec_pool.contexts[0],
+                                        &fv->enc, 0, 2, 0,
+                                        &fv->crc_tab_buf,
+                                        0, fv->crc_tab_buf.size,
+                                        VK_FORMAT_UNDEFINED));
+
+    /* Temporary frame */
+    fv->frame = av_frame_alloc();
+    if (!fv->frame)
+        return AVERROR(ENOMEM);
+
+    /* Async data pool */
+    fv->async_depth = fv->exec_pool.pool_size;
+    fv->exec_ctx_info = av_calloc(fv->async_depth, sizeof(*fv->exec_ctx_info));
+    if (!fv->exec_ctx_info)
+        return AVERROR(ENOMEM);
+    for (int i = 0; i < fv->async_depth; i++)
+        fv->exec_pool.contexts[i].opaque = &fv->exec_ctx_info[i];
+
+    fv->buf_regions = av_malloc_array(f->max_slice_count, sizeof(*fv->buf_regions));
+    if (!fv->buf_regions)
+        return AVERROR(ENOMEM);
+
+fail:
+    return err;
+}
+
+static av_cold int vulkan_encode_ffv1_close(AVCodecContext *avctx)
+{
+    VulkanEncodeFFv1Context *fv = avctx->priv_data;
+
+    ff_vk_exec_pool_free(&fv->s, &fv->exec_pool);
+    ff_vk_exec_pool_free(&fv->s, &fv->transfer_exec_pool);
+
+    ff_vk_shader_free(&fv->s, &fv->enc);
+    ff_vk_shader_free(&fv->s, &fv->reset);
+    ff_vk_shader_free(&fv->s, &fv->setup);
+    ff_vk_shader_free(&fv->s, &fv->rct_search);
+
+    if (fv->exec_ctx_info) {
+        for (int i = 0; i < fv->async_depth; i++) {
+            VulkanEncodeFFv1FrameData *fd = &fv->exec_ctx_info[i];
+            av_buffer_unref(&fd->out_data_ref);
+            av_buffer_unref(&fd->results_data_ref);
+            av_buffer_unref(&fd->frame_opaque_ref);
+        }
+    }
+    av_free(fv->exec_ctx_info);
+
+    av_buffer_unref(&fv->intermediate_frames_ref);
+
+    av_buffer_pool_uninit(&fv->results_data_pool);
+
+    av_buffer_pool_uninit(&fv->out_data_pool);
+
+    av_buffer_unref(&fv->keyframe_slice_data_ref);
+    av_buffer_pool_uninit(&fv->slice_data_pool);
+
+    ff_vk_free_buf(&fv->s, &fv->quant_buf);
+    ff_vk_free_buf(&fv->s, &fv->rangecoder_static_buf);
+    ff_vk_free_buf(&fv->s, &fv->crc_tab_buf);
+
+    av_free(fv->buf_regions);
+    av_frame_free(&fv->frame);
+    ff_vk_uninit(&fv->s);
+
+    return 0;
+}
+
+#define OFFSET(x) offsetof(VulkanEncodeFFv1Context, x)
+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
+static const AVOption vulkan_encode_ffv1_options[] = {
+    { "slicecrc", "Protect slices with CRCs", OFFSET(ctx.ec), AV_OPT_TYPE_INT,
+            { .i64 = -1 }, -1, 2, VE },
+    { "context", "Context model", OFFSET(ctx.context_model), AV_OPT_TYPE_INT,
+            { .i64 = 0 }, 0, 1, VE },
+    { "coder", "Coder type", OFFSET(ctx.ac), AV_OPT_TYPE_INT,
+            { .i64 = AC_RANGE_CUSTOM_TAB }, -2, 2, VE, .unit = "coder" },
+        { "rice", "Golomb rice", 0, AV_OPT_TYPE_CONST,
+            { .i64 = AC_GOLOMB_RICE }, INT_MIN, INT_MAX, VE, .unit = "coder" },
+        { "range_def", "Range with default table", 0, AV_OPT_TYPE_CONST,
+            { .i64 = AC_RANGE_DEFAULT_TAB_FORCE }, INT_MIN, INT_MAX, VE, .unit = "coder" },
+        { "range_tab", "Range with custom table", 0, AV_OPT_TYPE_CONST,
+            { .i64 = AC_RANGE_CUSTOM_TAB }, INT_MIN, INT_MAX, VE, .unit = "coder" },
+    { "qtable", "Quantization table", OFFSET(ctx.qtable), AV_OPT_TYPE_INT,
+            { .i64 = -1 }, -1, 2, VE , .unit = "qtable"},
+        { "default", NULL, 0, AV_OPT_TYPE_CONST,
+            { .i64 = QTABLE_DEFAULT }, INT_MIN, INT_MAX, VE, .unit = "qtable" },
+        { "8bit", NULL, 0, AV_OPT_TYPE_CONST,
+            { .i64 = QTABLE_8BIT }, INT_MIN, INT_MAX, VE, .unit = "qtable" },
+        { "greater8bit", NULL, 0, AV_OPT_TYPE_CONST,
+            { .i64 = QTABLE_GT8BIT }, INT_MIN, INT_MAX, VE, .unit = "qtable" },
+
+    { "slices_h", "Number of horizontal slices", OFFSET(num_h_slices), AV_OPT_TYPE_INT,
+            { .i64 = -1 }, -1, MAX_SLICES, VE },
+    { "slices_v", "Number of vertical slices", OFFSET(num_v_slices), AV_OPT_TYPE_INT,
+            { .i64 = -1 }, -1, MAX_SLICES, VE },
+
+    { "force_pcm", "Code all slices with no prediction", OFFSET(force_pcm), AV_OPT_TYPE_BOOL,
+            { .i64 = 0 }, 0, 1, VE },
+
+    { "rct_search", "Run a search for RCT parameters (level 4 only)", OFFSET(optimize_rct), AV_OPT_TYPE_BOOL,
+            { .i64 = 1 }, 0, 1, VE },
+
+    { "async_depth", "Internal parallelization depth", OFFSET(async_depth), AV_OPT_TYPE_INT,
+            { .i64 = 1 }, 1, INT_MAX, VE },
+
+    { NULL }
+};
+
+static const FFCodecDefault vulkan_encode_ffv1_defaults[] = {
+    { "g", "1" },
+    { NULL },
+};
+
+static const AVClass vulkan_encode_ffv1_class = {
+    .class_name = "ffv1_vulkan",
+    .item_name  = av_default_item_name,
+    .option     = vulkan_encode_ffv1_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+const AVCodecHWConfigInternal *const vulkan_encode_ffv1_hw_configs[] = {
+    HW_CONFIG_ENCODER_FRAMES(VULKAN, VULKAN),
+    NULL,
+};
+
+const FFCodec ff_ffv1_vulkan_encoder = {
+    .p.name         = "ffv1_vulkan",
+    CODEC_LONG_NAME("FFmpeg video codec #1 (Vulkan)"),
+    .p.type         = AVMEDIA_TYPE_VIDEO,
+    .p.id           = AV_CODEC_ID_FFV1,
+    .priv_data_size = sizeof(VulkanEncodeFFv1Context),
+    .init           = &vulkan_encode_ffv1_init,
+    FF_CODEC_RECEIVE_PACKET_CB(&vulkan_encode_ffv1_receive_packet),
+    .close          = &vulkan_encode_ffv1_close,
+    .p.priv_class   = &vulkan_encode_ffv1_class,
+    .p.capabilities = AV_CODEC_CAP_DELAY |
+                      AV_CODEC_CAP_HARDWARE |
+                      AV_CODEC_CAP_DR1 |
+                      AV_CODEC_CAP_ENCODER_FLUSH |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
+    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_EOF_FLUSH,
+    .defaults       = vulkan_encode_ffv1_defaults,
+    CODEC_PIXFMTS(AV_PIX_FMT_VULKAN),
+    .hw_configs     = vulkan_encode_ffv1_hw_configs,
+    .p.wrapper_name = "vulkan",
+};
-- 
2.49.1


From 4a4f6b372e5ba088bed0c72a038d6076550dce9b Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:26:42 +0000
Subject: [PATCH 061/118] Changing vulkan file directory

---
 libavcodec/ffv1_vulkan.h | 62 ----------------------------------------
 1 file changed, 62 deletions(-)
 delete mode 100644 libavcodec/ffv1_vulkan.h

diff --git a/libavcodec/ffv1_vulkan.h b/libavcodec/ffv1_vulkan.h
deleted file mode 100644
index 372478f4b7..0000000000
--- a/libavcodec/ffv1_vulkan.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2024 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVCODEC_FFV1_VULKAN_H
-#define AVCODEC_FFV1_VULKAN_H
-
-#include "libavutil/vulkan.h"
-#include "ffv1.h"
-
-int ff_ffv1_vk_update_state_transition_data(FFVulkanContext *s,
-                                            FFVkBuffer *vkb, FFV1Context *f);
-
-int ff_ffv1_vk_init_state_transition_data(FFVulkanContext *s,
-                                          FFVkBuffer *vkb, FFV1Context *f);
-
-int ff_ffv1_vk_init_quant_table_data(FFVulkanContext *s,
-                                     FFVkBuffer *vkb, FFV1Context *f);
-
-int ff_ffv1_vk_init_crc_table_data(FFVulkanContext *s,
-                                   FFVkBuffer *vkb, FFV1Context *f);
-
-typedef struct FFv1VkRCTParameters {
-    int fmt_lut[4];
-    int offset;
-    uint8_t bits;
-    uint8_t planar_rgb;
-    uint8_t color_planes;
-    uint8_t transparency;
-    uint8_t version;
-    uint8_t micro_version;
-    uint8_t padding[2];
-} FFv1VkRCTParameters;
-
-typedef struct FFv1VkResetParameters {
-    uint32_t context_count[MAX_QUANT_TABLES];
-    VkDeviceAddress slice_state;
-    uint32_t plane_state_size;
-    uint8_t codec_planes;
-    uint8_t key_frame;
-    uint8_t version;
-    uint8_t micro_version;
-    uint8_t padding[1];
-} FFv1VkResetParameters;
-
-#endif /* AVCODEC_FFV1_VULKAN_H */
-- 
2.49.1


From f6350a14b74676335b5761c96b26bf647c13f93f Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:27:27 +0000
Subject: [PATCH 062/118] Changing vulkan file directory

---
 libavcodec/vulkan/ffv1_vulkan.h | 62 +++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)
 create mode 100644 libavcodec/vulkan/ffv1_vulkan.h

diff --git a/libavcodec/vulkan/ffv1_vulkan.h b/libavcodec/vulkan/ffv1_vulkan.h
new file mode 100644
index 0000000000..bb10770576
--- /dev/null
+++ b/libavcodec/vulkan/ffv1_vulkan.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2024 Lynne <dev@lynne.ee>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_FFV1_VULKAN_H
+#define AVCODEC_FFV1_VULKAN_H
+
+#include "../../libavutil/vulkan/vulkan.h"
+#include "libavcodec/ffv1.h"
+
+int ff_ffv1_vk_update_state_transition_data(FFVulkanContext *s,
+                                            FFVkBuffer *vkb, FFV1Context *f);
+
+int ff_ffv1_vk_init_state_transition_data(FFVulkanContext *s,
+                                          FFVkBuffer *vkb, FFV1Context *f);
+
+int ff_ffv1_vk_init_quant_table_data(FFVulkanContext *s,
+                                     FFVkBuffer *vkb, FFV1Context *f);
+
+int ff_ffv1_vk_init_crc_table_data(FFVulkanContext *s,
+                                   FFVkBuffer *vkb, FFV1Context *f);
+
+typedef struct FFv1VkRCTParameters {
+    int fmt_lut[4];
+    int offset;
+    uint8_t bits;
+    uint8_t planar_rgb;
+    uint8_t color_planes;
+    uint8_t transparency;
+    uint8_t version;
+    uint8_t micro_version;
+    uint8_t padding[2];
+} FFv1VkRCTParameters;
+
+typedef struct FFv1VkResetParameters {
+    uint32_t context_count[MAX_QUANT_TABLES];
+    VkDeviceAddress slice_state;
+    uint32_t plane_state_size;
+    uint8_t codec_planes;
+    uint8_t key_frame;
+    uint8_t version;
+    uint8_t micro_version;
+    uint8_t padding[1];
+} FFv1VkResetParameters;
+
+#endif /* AVCODEC_FFV1_VULKAN_H */
-- 
2.49.1


From 3ed29bbe35ad3e34df22f15888c5dd2111f9974f Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:27:54 +0000
Subject: [PATCH 063/118] Changing vulkan file directory

---
 libavcodec/vulkan_av1.c | 670 ----------------------------------------
 1 file changed, 670 deletions(-)
 delete mode 100644 libavcodec/vulkan_av1.c

diff --git a/libavcodec/vulkan_av1.c b/libavcodec/vulkan_av1.c
deleted file mode 100644
index 788e3cca78..0000000000
--- a/libavcodec/vulkan_av1.c
+++ /dev/null
@@ -1,670 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "av1dec.h"
-
-#include "vulkan_decode.h"
-
-/* Maximum number of tiles specified by any defined level */
-#define MAX_TILES 256
-
-const FFVulkanDecodeDescriptor ff_vk_dec_av1_desc = {
-    .codec_id         = AV_CODEC_ID_AV1,
-    .decode_extension = FF_VK_EXT_VIDEO_DECODE_AV1,
-    .queue_flags      = VK_QUEUE_VIDEO_DECODE_BIT_KHR,
-    .decode_op        = VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR,
-    .ext_props = {
-        .extensionName = VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_EXTENSION_NAME,
-        .specVersion   = VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_SPEC_VERSION,
-    },
-};
-
-typedef struct AV1VulkanDecodePicture {
-    FFVulkanDecodePicture           vp;
-
-    /* TODO: investigate if this can be removed to make decoding completely
-     * independent. */
-    FFVulkanDecodeContext          *dec;
-
-    uint32_t tile_sizes[MAX_TILES];
-
-    /* Current picture */
-    StdVideoDecodeAV1ReferenceInfo     std_ref;
-    VkVideoDecodeAV1DpbSlotInfoKHR     vkav1_ref;
-    uint16_t width_in_sbs_minus1[64];
-    uint16_t height_in_sbs_minus1[64];
-    uint16_t mi_col_starts[64];
-    uint16_t mi_row_starts[64];
-    StdVideoAV1TileInfo tile_info;
-    StdVideoAV1Quantization quantization;
-    StdVideoAV1Segmentation segmentation;
-    StdVideoAV1LoopFilter loop_filter;
-    StdVideoAV1CDEF cdef;
-    StdVideoAV1LoopRestoration loop_restoration;
-    StdVideoAV1GlobalMotion global_motion;
-    StdVideoAV1FilmGrain film_grain;
-    StdVideoDecodeAV1PictureInfo    std_pic_info;
-    VkVideoDecodeAV1PictureInfoKHR     av1_pic_info;
-
-    /* Picture refs */
-    const AV1Frame                     *ref_src   [AV1_NUM_REF_FRAMES];
-    StdVideoDecodeAV1ReferenceInfo      std_refs  [AV1_NUM_REF_FRAMES];
-    VkVideoDecodeAV1DpbSlotInfoKHR      vkav1_refs[AV1_NUM_REF_FRAMES];
-
-    uint8_t frame_id_set;
-    uint8_t frame_id;
-    uint8_t ref_frame_sign_bias_mask;
-} AV1VulkanDecodePicture;
-
-static int vk_av1_fill_pict(AVCodecContext *avctx, const AV1Frame **ref_src,
-                            VkVideoReferenceSlotInfoKHR *ref_slot,      /* Main structure */
-                            VkVideoPictureResourceInfoKHR *ref,         /* Goes in ^ */
-                            StdVideoDecodeAV1ReferenceInfo *vkav1_std_ref,
-                            VkVideoDecodeAV1DpbSlotInfoKHR *vkav1_ref, /* Goes in ^ */
-                            const AV1Frame *pic, int is_current, int has_grain,
-                            const uint8_t *saved_order_hints)
-{
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-    AV1VulkanDecodePicture *hp = pic->hwaccel_picture_private;
-    FFVulkanDecodePicture *vkpic = &hp->vp;
-
-    int err = ff_vk_decode_prepare_frame(dec, pic->f, vkpic, is_current,
-                                         has_grain || dec->dedicated_dpb);
-    if (err < 0)
-        return err;
-
-    *vkav1_std_ref = (StdVideoDecodeAV1ReferenceInfo) {
-        .flags = (StdVideoDecodeAV1ReferenceInfoFlags) {
-            .disable_frame_end_update_cdf = pic->raw_frame_header->disable_frame_end_update_cdf,
-            .segmentation_enabled = pic->raw_frame_header->segmentation_enabled,
-        },
-        .frame_type = pic->raw_frame_header->frame_type,
-        .OrderHint = pic->raw_frame_header->order_hint,
-        .RefFrameSignBias = hp->ref_frame_sign_bias_mask,
-    };
-
-    if (saved_order_hints) {
-        if (dec->quirk_av1_offset)
-            for (int i = 1; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++)
-                vkav1_std_ref->SavedOrderHints[i - 1] = saved_order_hints[i];
-        else
-            for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++)
-                vkav1_std_ref->SavedOrderHints[i] = saved_order_hints[i];
-    }
-
-    *vkav1_ref = (VkVideoDecodeAV1DpbSlotInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_DPB_SLOT_INFO_KHR,
-        .pStdReferenceInfo = vkav1_std_ref,
-    };
-
-    vkav1_std_ref->flags.disable_frame_end_update_cdf = pic->raw_frame_header->disable_frame_end_update_cdf;
-    vkav1_std_ref->flags.segmentation_enabled = pic->raw_frame_header->segmentation_enabled;
-    vkav1_std_ref->frame_type = pic->raw_frame_header->frame_type;
-
-    *ref = (VkVideoPictureResourceInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
-        .codedOffset = (VkOffset2D){ 0, 0 },
-        .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
-        .baseArrayLayer = ((has_grain || dec->dedicated_dpb) && ctx->common.layered_dpb) ?
-                          hp->frame_id : 0,
-        .imageViewBinding = vkpic->view.ref[0],
-    };
-
-    *ref_slot = (VkVideoReferenceSlotInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
-        .pNext = vkav1_ref,
-        .slotIndex = hp->frame_id,
-        .pPictureResource = ref,
-    };
-
-    if (ref_src)
-        *ref_src = pic;
-
-    return 0;
-}
-
-static void vk_av1_params_fill(AVCodecContext *avctx,
-                               StdVideoAV1TimingInfo *av1_timing_info,
-                               StdVideoAV1ColorConfig *av1_color_config,
-                               StdVideoAV1SequenceHeader *av1_sequence_header)
-{
-    const AV1DecContext *s = avctx->priv_data;
-    const AV1RawSequenceHeader *seq = s->raw_seq;
-
-    *av1_timing_info = (StdVideoAV1TimingInfo) {
-        .flags = (StdVideoAV1TimingInfoFlags) {
-            .equal_picture_interval = seq->timing_info.equal_picture_interval,
-        },
-        .num_units_in_display_tick = seq->timing_info.num_units_in_display_tick,
-        .time_scale = seq->timing_info.time_scale,
-        .num_ticks_per_picture_minus_1 = seq->timing_info.num_ticks_per_picture_minus_1,
-    };
-
-    *av1_color_config = (StdVideoAV1ColorConfig) {
-        .flags = (StdVideoAV1ColorConfigFlags) {
-            .mono_chrome = seq->color_config.mono_chrome,
-            .color_range = seq->color_config.color_range,
-            .separate_uv_delta_q = seq->color_config.separate_uv_delta_q,
-        },
-        .BitDepth = seq->color_config.twelve_bit    ? 12 :
-                    seq->color_config.high_bitdepth ? 10 : 8,
-        .subsampling_x = seq->color_config.subsampling_x,
-        .subsampling_y = seq->color_config.subsampling_y,
-        .color_primaries = seq->color_config.color_primaries,
-        .transfer_characteristics = seq->color_config.transfer_characteristics,
-        .matrix_coefficients = seq->color_config.matrix_coefficients,
-    };
-
-    *av1_sequence_header = (StdVideoAV1SequenceHeader) {
-        .flags = (StdVideoAV1SequenceHeaderFlags) {
-            .still_picture = seq->still_picture,
-            .reduced_still_picture_header = seq->reduced_still_picture_header,
-            .use_128x128_superblock = seq->use_128x128_superblock,
-            .enable_filter_intra = seq->enable_filter_intra,
-            .enable_intra_edge_filter = seq->enable_intra_edge_filter,
-            .enable_interintra_compound = seq->enable_interintra_compound,
-            .enable_masked_compound = seq->enable_masked_compound,
-            .enable_warped_motion = seq->enable_warped_motion,
-            .enable_dual_filter = seq->enable_dual_filter,
-            .enable_order_hint = seq->enable_order_hint,
-            .enable_jnt_comp = seq->enable_jnt_comp,
-            .enable_ref_frame_mvs = seq->enable_ref_frame_mvs,
-            .frame_id_numbers_present_flag = seq->frame_id_numbers_present_flag,
-            .enable_superres = seq->enable_superres,
-            .enable_cdef = seq->enable_cdef,
-            .enable_restoration = seq->enable_restoration,
-            .film_grain_params_present = seq->film_grain_params_present,
-            .timing_info_present_flag = seq->timing_info_present_flag,
-            .initial_display_delay_present_flag = seq->initial_display_delay_present_flag,
-        },
-        .seq_profile = seq->seq_profile,
-        .frame_width_bits_minus_1 = seq->frame_width_bits_minus_1,
-        .frame_height_bits_minus_1 = seq->frame_height_bits_minus_1,
-        .max_frame_width_minus_1 = seq->max_frame_width_minus_1,
-        .max_frame_height_minus_1 = seq->max_frame_height_minus_1,
-        .delta_frame_id_length_minus_2 = seq->delta_frame_id_length_minus_2,
-        .additional_frame_id_length_minus_1 = seq->additional_frame_id_length_minus_1,
-        .order_hint_bits_minus_1 = seq->order_hint_bits_minus_1,
-        .seq_force_integer_mv = seq->seq_force_integer_mv,
-        .seq_force_screen_content_tools = seq->seq_force_screen_content_tools,
-        .pTimingInfo = av1_timing_info,
-        .pColorConfig = av1_color_config,
-    };
-}
-
-static int vk_av1_create_params(AVCodecContext *avctx, AVBufferRef **buf,
-                                AV1VulkanDecodePicture *ap)
-{
-    int err;
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-
-    StdVideoAV1SequenceHeader av1_sequence_header;
-    StdVideoAV1TimingInfo av1_timing_info;
-    StdVideoAV1ColorConfig av1_color_config;
-    VkVideoDecodeAV1SessionParametersCreateInfoKHR av1_params;
-    VkVideoSessionParametersCreateInfoKHR session_params_create;
-
-    vk_av1_params_fill(avctx, &av1_timing_info, &av1_color_config,
-                       &av1_sequence_header);
-
-    av1_params = (VkVideoDecodeAV1SessionParametersCreateInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR,
-        .pStdSequenceHeader = &av1_sequence_header,
-    };
-    session_params_create = (VkVideoSessionParametersCreateInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
-        .pNext = &av1_params,
-        .videoSession = ctx->common.session,
-        .videoSessionParametersTemplate = VK_NULL_HANDLE,
-    };
-
-    err = ff_vk_decode_create_params(buf, avctx, ctx, &session_params_create);
-    if (err < 0)
-        return err;
-
-    av_log(avctx, AV_LOG_DEBUG, "Created frame parameters\n");
-
-    return 0;
-}
-
-static int vk_av1_start_frame(AVCodecContext          *avctx,
-                              av_unused const AVBufferRef *buffer_ref,
-                              av_unused const uint8_t *buffer,
-                              av_unused uint32_t       size)
-{
-    int err;
-    int ref_count = 0;
-    AV1DecContext *s = avctx->priv_data;
-    const AV1Frame *pic = &s->cur_frame;
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    uint32_t frame_id_alloc_mask = 0;
-
-    AV1VulkanDecodePicture *ap = pic->hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &ap->vp;
-
-    const AV1RawFrameHeader *frame_header = s->raw_frame_header;
-    const AV1RawFilmGrainParams *film_grain = &s->cur_frame.film_grain;
-
-    const int apply_grain = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) &&
-                            film_grain->apply_grain;
-    StdVideoAV1FrameRestorationType remap_lr_type[4] = { STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_NONE,
-                                                         STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_SWITCHABLE,
-                                                         STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_WIENER,
-                                                         STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_SGRPROJ };
-
-    /* Use the current frame_ids in ref[] to decide occupied frame_ids */
-    for (int i = 0; i < STD_VIDEO_AV1_NUM_REF_FRAMES; i++) {
-        const AV1VulkanDecodePicture* rp = s->ref[i].hwaccel_picture_private;
-        if (rp)
-            frame_id_alloc_mask |= 1 << rp->frame_id;
-    }
-
-    if (!ap->frame_id_set) {
-        unsigned slot_idx = 0;
-        for (unsigned i = 0; i < 32; i++) {
-            if (!(frame_id_alloc_mask & (1 << i))) {
-                slot_idx = i;
-                break;
-            }
-        }
-        ap->frame_id = slot_idx;
-        ap->frame_id_set = 1;
-        frame_id_alloc_mask |= (1 << slot_idx);
-    }
-
-    ap->ref_frame_sign_bias_mask = 0x0;
-    for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++)
-        ap->ref_frame_sign_bias_mask |= pic->ref_frame_sign_bias[i] << i;
-
-    for (int i = 0; i < STD_VIDEO_AV1_REFS_PER_FRAME; i++) {
-        const int idx = pic->raw_frame_header->ref_frame_idx[i];
-        const AV1Frame *ref_frame = &s->ref[idx];
-        AV1VulkanDecodePicture *hp = ref_frame->hwaccel_picture_private;
-        int found = 0;
-
-        if (!ref_frame->f)
-            continue;
-
-        for (int j = 0; j < ref_count; j++) {
-            if (vp->ref_slots[j].slotIndex == hp->frame_id) {
-                found = 1;
-                break;
-            }
-        }
-        if (found)
-            continue;
-
-        err = vk_av1_fill_pict(avctx, &ap->ref_src[ref_count], &vp->ref_slots[ref_count],
-                               &vp->refs[ref_count], &ap->std_refs[ref_count], &ap->vkav1_refs[ref_count],
-                               ref_frame, 0, 0, ref_frame->order_hints);
-        if (err < 0)
-            return err;
-
-        ref_count++;
-    }
-
-    err = vk_av1_fill_pict(avctx, NULL, &vp->ref_slot, &vp->ref,
-                           &ap->std_ref,
-                           &ap->vkav1_ref,
-                           pic, 1, apply_grain, NULL);
-    if (err < 0)
-        return err;
-
-    ap->av1_pic_info = (VkVideoDecodeAV1PictureInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PICTURE_INFO_KHR,
-        .pStdPictureInfo = &ap->std_pic_info,
-        .frameHeaderOffset = 0,
-        .tileCount = 0,
-        .pTileOffsets = NULL,
-        .pTileSizes = ap->tile_sizes,
-    };
-
-    for (int i = 0; i < STD_VIDEO_AV1_REFS_PER_FRAME; i++) {
-        const int idx = pic->raw_frame_header->ref_frame_idx[i];
-        const AV1Frame *ref_frame = &s->ref[idx];
-        AV1VulkanDecodePicture *hp = ref_frame->hwaccel_picture_private;
-
-        if (!ref_frame->f)
-            ap->av1_pic_info.referenceNameSlotIndices[i] = AV1_REF_FRAME_NONE;
-        else
-            ap->av1_pic_info.referenceNameSlotIndices[i] = hp->frame_id;
-    }
-
-    vp->decode_info = (VkVideoDecodeInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR,
-        .pNext = &ap->av1_pic_info,
-        .flags = 0x0,
-        .pSetupReferenceSlot = &vp->ref_slot,
-        .referenceSlotCount = ref_count,
-        .pReferenceSlots = vp->ref_slots,
-        .dstPictureResource = (VkVideoPictureResourceInfoKHR) {
-            .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
-            .codedOffset = (VkOffset2D){ 0, 0 },
-            .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
-            .baseArrayLayer = 0,
-            .imageViewBinding = vp->view.out[0],
-        },
-    };
-
-    ap->tile_info = (StdVideoAV1TileInfo) {
-        .flags = (StdVideoAV1TileInfoFlags) {
-            .uniform_tile_spacing_flag = frame_header->uniform_tile_spacing_flag,
-        },
-        .TileCols = frame_header->tile_cols,
-        .TileRows = frame_header->tile_rows,
-        .context_update_tile_id = frame_header->context_update_tile_id,
-        .tile_size_bytes_minus_1 = frame_header->tile_size_bytes_minus1,
-        .pWidthInSbsMinus1 = ap->width_in_sbs_minus1,
-        .pHeightInSbsMinus1 = ap->height_in_sbs_minus1,
-        .pMiColStarts = ap->mi_col_starts,
-        .pMiRowStarts = ap->mi_row_starts,
-    };
-
-    ap->quantization = (StdVideoAV1Quantization) {
-        .flags.using_qmatrix = frame_header->using_qmatrix,
-        .flags.diff_uv_delta = frame_header->diff_uv_delta,
-        .base_q_idx = frame_header->base_q_idx,
-        .DeltaQYDc = frame_header->delta_q_y_dc,
-        .DeltaQUDc = frame_header->delta_q_u_dc,
-        .DeltaQUAc = frame_header->delta_q_u_ac,
-        .DeltaQVDc = frame_header->delta_q_v_dc,
-        .DeltaQVAc = frame_header->delta_q_v_ac,
-        .qm_y = frame_header->qm_y,
-        .qm_u = frame_header->qm_u,
-        .qm_v = frame_header->qm_v,
-    };
-
-    ap->loop_filter = (StdVideoAV1LoopFilter) {
-        .flags = (StdVideoAV1LoopFilterFlags) {
-            .loop_filter_delta_enabled = frame_header->loop_filter_delta_enabled,
-            .loop_filter_delta_update = frame_header->loop_filter_delta_update,
-        },
-        .loop_filter_sharpness = frame_header->loop_filter_sharpness,
-    };
-
-    for (int i = 0; i < STD_VIDEO_AV1_MAX_LOOP_FILTER_STRENGTHS; i++)
-        ap->loop_filter.loop_filter_level[i] = frame_header->loop_filter_level[i];
-    for (int i = 0; i < STD_VIDEO_AV1_LOOP_FILTER_ADJUSTMENTS; i++)
-        ap->loop_filter.loop_filter_mode_deltas[i] = frame_header->loop_filter_mode_deltas[i];
-
-    ap->cdef = (StdVideoAV1CDEF) {
-        .cdef_damping_minus_3 = frame_header->cdef_damping_minus_3,
-        .cdef_bits = frame_header->cdef_bits,
-    };
-
-    ap->loop_restoration = (StdVideoAV1LoopRestoration) {
-        .FrameRestorationType[0] = remap_lr_type[frame_header->lr_type[0]],
-        .FrameRestorationType[1] = remap_lr_type[frame_header->lr_type[1]],
-        .FrameRestorationType[2] = remap_lr_type[frame_header->lr_type[2]],
-        .LoopRestorationSize[0] = 1 + frame_header->lr_unit_shift,
-        .LoopRestorationSize[1] = 1 + frame_header->lr_unit_shift - frame_header->lr_uv_shift,
-        .LoopRestorationSize[2] = 1 + frame_header->lr_unit_shift - frame_header->lr_uv_shift,
-    };
-
-    ap->film_grain = (StdVideoAV1FilmGrain) {
-        .flags = (StdVideoAV1FilmGrainFlags) {
-            .chroma_scaling_from_luma = film_grain->chroma_scaling_from_luma,
-            .overlap_flag = film_grain->overlap_flag,
-            .clip_to_restricted_range = film_grain->clip_to_restricted_range,
-        },
-        .grain_scaling_minus_8 = film_grain->grain_scaling_minus_8,
-        .ar_coeff_lag = film_grain->ar_coeff_lag,
-        .ar_coeff_shift_minus_6 = film_grain->ar_coeff_shift_minus_6,
-        .grain_scale_shift = film_grain->grain_scale_shift,
-        .grain_seed = film_grain->grain_seed,
-        .film_grain_params_ref_idx = film_grain->film_grain_params_ref_idx,
-        .num_y_points = film_grain->num_y_points,
-        .num_cb_points = film_grain->num_cb_points,
-        .num_cr_points = film_grain->num_cr_points,
-        .cb_mult = film_grain->cb_mult,
-        .cb_luma_mult = film_grain->cb_luma_mult,
-        .cb_offset = film_grain->cb_offset,
-        .cr_mult = film_grain->cr_mult,
-        .cr_luma_mult = film_grain->cr_luma_mult,
-        .cr_offset = film_grain->cr_offset,
-    };
-
-    /* Setup frame header */
-    ap->std_pic_info = (StdVideoDecodeAV1PictureInfo) {
-        .flags = (StdVideoDecodeAV1PictureInfoFlags) {
-            .error_resilient_mode = frame_header->error_resilient_mode,
-            .disable_cdf_update = frame_header->disable_cdf_update,
-            .use_superres = frame_header->use_superres,
-            .render_and_frame_size_different = frame_header->render_and_frame_size_different,
-            .allow_screen_content_tools = frame_header->allow_screen_content_tools,
-            .is_filter_switchable = frame_header->is_filter_switchable,
-            .force_integer_mv = pic->force_integer_mv,
-            .frame_size_override_flag = frame_header->frame_size_override_flag,
-            .buffer_removal_time_present_flag = frame_header->buffer_removal_time_present_flag,
-            .allow_intrabc = frame_header->allow_intrabc,
-            .frame_refs_short_signaling = frame_header->frame_refs_short_signaling,
-            .allow_high_precision_mv = frame_header->allow_high_precision_mv,
-            .is_motion_mode_switchable = frame_header->is_motion_mode_switchable,
-            .use_ref_frame_mvs = frame_header->use_ref_frame_mvs,
-            .disable_frame_end_update_cdf = frame_header->disable_frame_end_update_cdf,
-            .allow_warped_motion = frame_header->allow_warped_motion,
-            .reduced_tx_set = frame_header->reduced_tx_set,
-            .reference_select = frame_header->reference_select,
-            .skip_mode_present = frame_header->skip_mode_present,
-            .delta_q_present = frame_header->delta_q_present,
-            .delta_lf_present = frame_header->delta_lf_present,
-            .delta_lf_multi = frame_header->delta_lf_multi,
-            .segmentation_enabled = frame_header->segmentation_enabled,
-            .segmentation_update_map = frame_header->segmentation_update_map,
-            .segmentation_temporal_update = frame_header->segmentation_temporal_update,
-            .segmentation_update_data = frame_header->segmentation_update_data,
-            .UsesLr = frame_header->lr_type[0] || frame_header->lr_type[1] || frame_header->lr_type[2],
-            .apply_grain = apply_grain,
-        },
-        .frame_type = frame_header->frame_type,
-        .current_frame_id = frame_header->current_frame_id,
-        .OrderHint = frame_header->order_hint,
-        .primary_ref_frame = frame_header->primary_ref_frame,
-        .refresh_frame_flags = frame_header->refresh_frame_flags,
-        .interpolation_filter = frame_header->interpolation_filter,
-        .TxMode = frame_header->tx_mode,
-        .delta_q_res = frame_header->delta_q_res,
-        .delta_lf_res = frame_header->delta_lf_res,
-        .SkipModeFrame[0] = s->cur_frame.skip_mode_frame_idx[0],
-        .SkipModeFrame[1] = s->cur_frame.skip_mode_frame_idx[1],
-        .coded_denom = frame_header->coded_denom,
-        .pTileInfo = &ap->tile_info,
-        .pQuantization = &ap->quantization,
-        .pSegmentation = &ap->segmentation,
-        .pLoopFilter = &ap->loop_filter,
-        .pCDEF = &ap->cdef,
-        .pLoopRestoration = &ap->loop_restoration,
-        .pGlobalMotion = &ap->global_motion,
-        .pFilmGrain = apply_grain ? &ap->film_grain : NULL,
-    };
-
-    for (int i = 0; i < 64; i++) {
-        ap->width_in_sbs_minus1[i] = frame_header->width_in_sbs_minus_1[i];
-        ap->height_in_sbs_minus1[i] = frame_header->height_in_sbs_minus_1[i];
-        ap->mi_col_starts[i] = frame_header->tile_start_col_sb[i];
-        ap->mi_row_starts[i] = frame_header->tile_start_row_sb[i];
-    }
-
-    for (int i = 0; i < STD_VIDEO_AV1_MAX_SEGMENTS; i++) {
-        ap->segmentation.FeatureEnabled[i] = 0x0;
-        for (int j = 0; j < STD_VIDEO_AV1_SEG_LVL_MAX; j++) {
-            ap->segmentation.FeatureEnabled[i] |= (frame_header->feature_enabled[i][j] << j);
-            ap->segmentation.FeatureData[i][j] = frame_header->feature_value[i][j];
-        }
-    }
-
-    if (dec->quirk_av1_offset)
-        for (int i = 1; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++)
-            ap->std_pic_info.OrderHints[i - 1] = pic->order_hints[i];
-    else
-        for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++)
-            ap->std_pic_info.OrderHints[i] = pic->order_hints[i];
-
-    for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++) {
-        ap->loop_filter.loop_filter_ref_deltas[i] = frame_header->loop_filter_ref_deltas[i];
-        ap->global_motion.GmType[i] = s->cur_frame.gm_type[i];
-        for (int j = 0; j < STD_VIDEO_AV1_GLOBAL_MOTION_PARAMS; j++) {
-            ap->global_motion.gm_params[i][j] = s->cur_frame.gm_params[i][j];
-        }
-    }
-
-    for (int i = 0; i < STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS; i++) {
-        ap->cdef.cdef_y_pri_strength[i] = frame_header->cdef_y_pri_strength[i];
-        ap->cdef.cdef_y_sec_strength[i] = frame_header->cdef_y_sec_strength[i];
-        ap->cdef.cdef_uv_pri_strength[i] = frame_header->cdef_uv_pri_strength[i];
-        ap->cdef.cdef_uv_sec_strength[i] = frame_header->cdef_uv_sec_strength[i];
-    }
-
-    if (apply_grain) {
-        for (int i = 0; i < STD_VIDEO_AV1_MAX_NUM_Y_POINTS; i++) {
-            ap->film_grain.point_y_value[i] = film_grain->point_y_value[i];
-            ap->film_grain.point_y_scaling[i] = film_grain->point_y_scaling[i];
-        }
-
-        for (int i = 0; i < STD_VIDEO_AV1_MAX_NUM_CB_POINTS; i++) {
-            ap->film_grain.point_cb_value[i] = film_grain->point_cb_value[i];
-            ap->film_grain.point_cb_scaling[i] = film_grain->point_cb_scaling[i];
-            ap->film_grain.point_cr_value[i] = film_grain->point_cr_value[i];
-            ap->film_grain.point_cr_scaling[i] = film_grain->point_cr_scaling[i];
-        }
-
-        for (int i = 0; i < STD_VIDEO_AV1_MAX_NUM_POS_LUMA; i++)
-            ap->film_grain.ar_coeffs_y_plus_128[i] = film_grain->ar_coeffs_y_plus_128[i];
-
-        for (int i = 0; i < STD_VIDEO_AV1_MAX_NUM_POS_CHROMA; i++) {
-            ap->film_grain.ar_coeffs_cb_plus_128[i] = film_grain->ar_coeffs_cb_plus_128[i];
-            ap->film_grain.ar_coeffs_cr_plus_128[i] = film_grain->ar_coeffs_cr_plus_128[i];
-        }
-    }
-
-    ap->dec = dec;
-
-    return 0;
-}
-
-static int vk_av1_decode_slice(AVCodecContext *avctx,
-                               const uint8_t  *data,
-                               uint32_t        size)
-{
-    int err;
-    const AV1DecContext *s = avctx->priv_data;
-    AV1VulkanDecodePicture *ap = s->cur_frame.hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &ap->vp;
-
-    /* Too many tiles, exceeding all defined levels in the AV1 spec */
-    if (ap->av1_pic_info.tileCount > MAX_TILES)
-        return AVERROR(ENOSYS);
-
-    for (int i = s->tg_start; i <= s->tg_end; i++) {
-        ap->tile_sizes[ap->av1_pic_info.tileCount] = s->tile_group_info[i].tile_size;
-
-        err = ff_vk_decode_add_slice(avctx, vp,
-                                     data + s->tile_group_info[i].tile_offset,
-                                     s->tile_group_info[i].tile_size, 0,
-                                     &ap->av1_pic_info.tileCount,
-                                     &ap->av1_pic_info.pTileOffsets);
-        if (err < 0)
-            return err;
-    }
-
-    return 0;
-}
-
-static int vk_av1_end_frame(AVCodecContext *avctx)
-{
-    const AV1DecContext *s = avctx->priv_data;
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-
-    const AV1Frame *pic = &s->cur_frame;
-    AV1VulkanDecodePicture *ap = pic->hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &ap->vp;
-    FFVulkanDecodePicture *rvp[AV1_NUM_REF_FRAMES] = { 0 };
-    AVFrame *rav[AV1_NUM_REF_FRAMES] = { 0 };
-
-#ifdef VK_KHR_video_maintenance2
-    StdVideoAV1SequenceHeader av1_sequence_header;
-    StdVideoAV1TimingInfo av1_timing_info;
-    StdVideoAV1ColorConfig av1_color_config;
-    VkVideoDecodeAV1InlineSessionParametersInfoKHR av1_params;
-
-    if (ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2) {
-        vk_av1_params_fill(avctx, &av1_timing_info, &av1_color_config,
-                           &av1_sequence_header);
-        av1_params = (VkVideoDecodeAV1InlineSessionParametersInfoKHR) {
-            .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_INLINE_SESSION_PARAMETERS_INFO_KHR,
-            .pStdSequenceHeader = &av1_sequence_header,
-        };
-        ap->av1_pic_info.pNext = &av1_params;
-    }
-#endif
-
-    if (!ap->av1_pic_info.tileCount)
-        return 0;
-
-    if (!dec->session_params &&
-        !(ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)) {
-        int err = vk_av1_create_params(avctx, &dec->session_params, ap);
-        if (err < 0)
-            return err;
-    }
-
-    for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
-        const AV1Frame *rp = ap->ref_src[i];
-        AV1VulkanDecodePicture *rhp = rp->hwaccel_picture_private;
-
-        rvp[i] = &rhp->vp;
-        rav[i] = ap->ref_src[i]->f;
-    }
-
-    av_log(avctx, AV_LOG_DEBUG, "Decoding frame, %"SIZE_SPECIFIER" bytes, %i tiles\n",
-           vp->slices_size, ap->av1_pic_info.tileCount);
-
-    return ff_vk_decode_frame(avctx, pic->f, vp, rav, rvp);
-}
-
-static void vk_av1_free_frame_priv(AVRefStructOpaque _hwctx, void *data)
-{
-    AVHWDeviceContext *hwctx = _hwctx.nc;
-    AV1VulkanDecodePicture *ap = data;
-
-    /* Free frame resources, this also destroys the session parameters. */
-    ff_vk_decode_free_frame(hwctx, &ap->vp);
-}
-
-const FFHWAccel ff_av1_vulkan_hwaccel = {
-    .p.name                = "av1_vulkan",
-    .p.type                = AVMEDIA_TYPE_VIDEO,
-    .p.id                  = AV_CODEC_ID_AV1,
-    .p.pix_fmt             = AV_PIX_FMT_VULKAN,
-    .start_frame           = &vk_av1_start_frame,
-    .decode_slice          = &vk_av1_decode_slice,
-    .end_frame             = &vk_av1_end_frame,
-    .free_frame_priv       = &vk_av1_free_frame_priv,
-    .frame_priv_data_size  = sizeof(AV1VulkanDecodePicture),
-    .init                  = &ff_vk_decode_init,
-    .update_thread_context = &ff_vk_update_thread_context,
-    .decode_params         = &ff_vk_params_invalidate,
-    .flush                 = &ff_vk_decode_flush,
-    .uninit                = &ff_vk_decode_uninit,
-    .frame_params          = &ff_vk_frame_params,
-    .priv_data_size        = sizeof(FFVulkanDecodeContext),
-    .caps_internal         = HWACCEL_CAP_ASYNC_SAFE,
-};
-- 
2.49.1


From 02605012d1182416beca37099a3a670ff0e29c26 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:28:22 +0000
Subject: [PATCH 064/118] Changing vulkan file directory

---
 libavcodec/vulkan/vulkan_av1.c | 670 +++++++++++++++++++++++++++++++++
 1 file changed, 670 insertions(+)
 create mode 100644 libavcodec/vulkan/vulkan_av1.c

diff --git a/libavcodec/vulkan/vulkan_av1.c b/libavcodec/vulkan/vulkan_av1.c
new file mode 100644
index 0000000000..ee954a46ed
--- /dev/null
+++ b/libavcodec/vulkan/vulkan_av1.c
@@ -0,0 +1,670 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavcodec/av1dec.h"
+
+#include "vulkan_decode.h"
+
+/* Maximum number of tiles specified by any defined level */
+#define MAX_TILES 256
+
+const FFVulkanDecodeDescriptor ff_vk_dec_av1_desc = {
+    .codec_id         = AV_CODEC_ID_AV1,
+    .decode_extension = FF_VK_EXT_VIDEO_DECODE_AV1,
+    .queue_flags      = VK_QUEUE_VIDEO_DECODE_BIT_KHR,
+    .decode_op        = VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR,
+    .ext_props = {
+        .extensionName = VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_EXTENSION_NAME,
+        .specVersion   = VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_SPEC_VERSION,
+    },
+};
+
+typedef struct AV1VulkanDecodePicture {
+    FFVulkanDecodePicture           vp;
+
+    /* TODO: investigate if this can be removed to make decoding completely
+     * independent. */
+    FFVulkanDecodeContext          *dec;
+
+    uint32_t tile_sizes[MAX_TILES];
+
+    /* Current picture */
+    StdVideoDecodeAV1ReferenceInfo     std_ref;
+    VkVideoDecodeAV1DpbSlotInfoKHR     vkav1_ref;
+    uint16_t width_in_sbs_minus1[64];
+    uint16_t height_in_sbs_minus1[64];
+    uint16_t mi_col_starts[64];
+    uint16_t mi_row_starts[64];
+    StdVideoAV1TileInfo tile_info;
+    StdVideoAV1Quantization quantization;
+    StdVideoAV1Segmentation segmentation;
+    StdVideoAV1LoopFilter loop_filter;
+    StdVideoAV1CDEF cdef;
+    StdVideoAV1LoopRestoration loop_restoration;
+    StdVideoAV1GlobalMotion global_motion;
+    StdVideoAV1FilmGrain film_grain;
+    StdVideoDecodeAV1PictureInfo    std_pic_info;
+    VkVideoDecodeAV1PictureInfoKHR     av1_pic_info;
+
+    /* Picture refs */
+    const AV1Frame                     *ref_src   [AV1_NUM_REF_FRAMES];
+    StdVideoDecodeAV1ReferenceInfo      std_refs  [AV1_NUM_REF_FRAMES];
+    VkVideoDecodeAV1DpbSlotInfoKHR      vkav1_refs[AV1_NUM_REF_FRAMES];
+
+    uint8_t frame_id_set;
+    uint8_t frame_id;
+    uint8_t ref_frame_sign_bias_mask;
+} AV1VulkanDecodePicture;
+
+static int vk_av1_fill_pict(AVCodecContext *avctx, const AV1Frame **ref_src,
+                            VkVideoReferenceSlotInfoKHR *ref_slot,      /* Main structure */
+                            VkVideoPictureResourceInfoKHR *ref,         /* Goes in ^ */
+                            StdVideoDecodeAV1ReferenceInfo *vkav1_std_ref,
+                            VkVideoDecodeAV1DpbSlotInfoKHR *vkav1_ref, /* Goes in ^ */
+                            const AV1Frame *pic, int is_current, int has_grain,
+                            const uint8_t *saved_order_hints)
+{
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+    AV1VulkanDecodePicture *hp = pic->hwaccel_picture_private;
+    FFVulkanDecodePicture *vkpic = &hp->vp;
+
+    int err = ff_vk_decode_prepare_frame(dec, pic->f, vkpic, is_current,
+                                         has_grain || dec->dedicated_dpb);
+    if (err < 0)
+        return err;
+
+    *vkav1_std_ref = (StdVideoDecodeAV1ReferenceInfo) {
+        .flags = (StdVideoDecodeAV1ReferenceInfoFlags) {
+            .disable_frame_end_update_cdf = pic->raw_frame_header->disable_frame_end_update_cdf,
+            .segmentation_enabled = pic->raw_frame_header->segmentation_enabled,
+        },
+        .frame_type = pic->raw_frame_header->frame_type,
+        .OrderHint = pic->raw_frame_header->order_hint,
+        .RefFrameSignBias = hp->ref_frame_sign_bias_mask,
+    };
+
+    if (saved_order_hints) {
+        if (dec->quirk_av1_offset)
+            for (int i = 1; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++)
+                vkav1_std_ref->SavedOrderHints[i - 1] = saved_order_hints[i];
+        else
+            for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++)
+                vkav1_std_ref->SavedOrderHints[i] = saved_order_hints[i];
+    }
+
+    *vkav1_ref = (VkVideoDecodeAV1DpbSlotInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_DPB_SLOT_INFO_KHR,
+        .pStdReferenceInfo = vkav1_std_ref,
+    };
+
+    vkav1_std_ref->flags.disable_frame_end_update_cdf = pic->raw_frame_header->disable_frame_end_update_cdf;
+    vkav1_std_ref->flags.segmentation_enabled = pic->raw_frame_header->segmentation_enabled;
+    vkav1_std_ref->frame_type = pic->raw_frame_header->frame_type;
+
+    *ref = (VkVideoPictureResourceInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
+        .codedOffset = (VkOffset2D){ 0, 0 },
+        .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
+        .baseArrayLayer = ((has_grain || dec->dedicated_dpb) && ctx->common.layered_dpb) ?
+                          hp->frame_id : 0,
+        .imageViewBinding = vkpic->view.ref[0],
+    };
+
+    *ref_slot = (VkVideoReferenceSlotInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
+        .pNext = vkav1_ref,
+        .slotIndex = hp->frame_id,
+        .pPictureResource = ref,
+    };
+
+    if (ref_src)
+        *ref_src = pic;
+
+    return 0;
+}
+
+static void vk_av1_params_fill(AVCodecContext *avctx,
+                               StdVideoAV1TimingInfo *av1_timing_info,
+                               StdVideoAV1ColorConfig *av1_color_config,
+                               StdVideoAV1SequenceHeader *av1_sequence_header)
+{
+    const AV1DecContext *s = avctx->priv_data;
+    const AV1RawSequenceHeader *seq = s->raw_seq;
+
+    *av1_timing_info = (StdVideoAV1TimingInfo) {
+        .flags = (StdVideoAV1TimingInfoFlags) {
+            .equal_picture_interval = seq->timing_info.equal_picture_interval,
+        },
+        .num_units_in_display_tick = seq->timing_info.num_units_in_display_tick,
+        .time_scale = seq->timing_info.time_scale,
+        .num_ticks_per_picture_minus_1 = seq->timing_info.num_ticks_per_picture_minus_1,
+    };
+
+    *av1_color_config = (StdVideoAV1ColorConfig) {
+        .flags = (StdVideoAV1ColorConfigFlags) {
+            .mono_chrome = seq->color_config.mono_chrome,
+            .color_range = seq->color_config.color_range,
+            .separate_uv_delta_q = seq->color_config.separate_uv_delta_q,
+        },
+        .BitDepth = seq->color_config.twelve_bit    ? 12 :
+                    seq->color_config.high_bitdepth ? 10 : 8,
+        .subsampling_x = seq->color_config.subsampling_x,
+        .subsampling_y = seq->color_config.subsampling_y,
+        .color_primaries = seq->color_config.color_primaries,
+        .transfer_characteristics = seq->color_config.transfer_characteristics,
+        .matrix_coefficients = seq->color_config.matrix_coefficients,
+    };
+
+    *av1_sequence_header = (StdVideoAV1SequenceHeader) {
+        .flags = (StdVideoAV1SequenceHeaderFlags) {
+            .still_picture = seq->still_picture,
+            .reduced_still_picture_header = seq->reduced_still_picture_header,
+            .use_128x128_superblock = seq->use_128x128_superblock,
+            .enable_filter_intra = seq->enable_filter_intra,
+            .enable_intra_edge_filter = seq->enable_intra_edge_filter,
+            .enable_interintra_compound = seq->enable_interintra_compound,
+            .enable_masked_compound = seq->enable_masked_compound,
+            .enable_warped_motion = seq->enable_warped_motion,
+            .enable_dual_filter = seq->enable_dual_filter,
+            .enable_order_hint = seq->enable_order_hint,
+            .enable_jnt_comp = seq->enable_jnt_comp,
+            .enable_ref_frame_mvs = seq->enable_ref_frame_mvs,
+            .frame_id_numbers_present_flag = seq->frame_id_numbers_present_flag,
+            .enable_superres = seq->enable_superres,
+            .enable_cdef = seq->enable_cdef,
+            .enable_restoration = seq->enable_restoration,
+            .film_grain_params_present = seq->film_grain_params_present,
+            .timing_info_present_flag = seq->timing_info_present_flag,
+            .initial_display_delay_present_flag = seq->initial_display_delay_present_flag,
+        },
+        .seq_profile = seq->seq_profile,
+        .frame_width_bits_minus_1 = seq->frame_width_bits_minus_1,
+        .frame_height_bits_minus_1 = seq->frame_height_bits_minus_1,
+        .max_frame_width_minus_1 = seq->max_frame_width_minus_1,
+        .max_frame_height_minus_1 = seq->max_frame_height_minus_1,
+        .delta_frame_id_length_minus_2 = seq->delta_frame_id_length_minus_2,
+        .additional_frame_id_length_minus_1 = seq->additional_frame_id_length_minus_1,
+        .order_hint_bits_minus_1 = seq->order_hint_bits_minus_1,
+        .seq_force_integer_mv = seq->seq_force_integer_mv,
+        .seq_force_screen_content_tools = seq->seq_force_screen_content_tools,
+        .pTimingInfo = av1_timing_info,
+        .pColorConfig = av1_color_config,
+    };
+}
+
+static int vk_av1_create_params(AVCodecContext *avctx, AVBufferRef **buf,
+                                AV1VulkanDecodePicture *ap)
+{
+    int err;
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+
+    StdVideoAV1SequenceHeader av1_sequence_header;
+    StdVideoAV1TimingInfo av1_timing_info;
+    StdVideoAV1ColorConfig av1_color_config;
+    VkVideoDecodeAV1SessionParametersCreateInfoKHR av1_params;
+    VkVideoSessionParametersCreateInfoKHR session_params_create;
+
+    vk_av1_params_fill(avctx, &av1_timing_info, &av1_color_config,
+                       &av1_sequence_header);
+
+    av1_params = (VkVideoDecodeAV1SessionParametersCreateInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR,
+        .pStdSequenceHeader = &av1_sequence_header,
+    };
+    session_params_create = (VkVideoSessionParametersCreateInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
+        .pNext = &av1_params,
+        .videoSession = ctx->common.session,
+        .videoSessionParametersTemplate = VK_NULL_HANDLE,
+    };
+
+    err = ff_vk_decode_create_params(buf, avctx, ctx, &session_params_create);
+    if (err < 0)
+        return err;
+
+    av_log(avctx, AV_LOG_DEBUG, "Created frame parameters\n");
+
+    return 0;
+}
+
+static int vk_av1_start_frame(AVCodecContext          *avctx,
+                              av_unused const AVBufferRef *buffer_ref,
+                              av_unused const uint8_t *buffer,
+                              av_unused uint32_t       size)
+{
+    int err;
+    int ref_count = 0;
+    AV1DecContext *s = avctx->priv_data;
+    const AV1Frame *pic = &s->cur_frame;
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    uint32_t frame_id_alloc_mask = 0;
+
+    AV1VulkanDecodePicture *ap = pic->hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &ap->vp;
+
+    const AV1RawFrameHeader *frame_header = s->raw_frame_header;
+    const AV1RawFilmGrainParams *film_grain = &s->cur_frame.film_grain;
+
+    const int apply_grain = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) &&
+                            film_grain->apply_grain;
+    StdVideoAV1FrameRestorationType remap_lr_type[4] = { STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_NONE,
+                                                         STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_SWITCHABLE,
+                                                         STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_WIENER,
+                                                         STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_SGRPROJ };
+
+    /* Use the current frame_ids in ref[] to decide occupied frame_ids */
+    for (int i = 0; i < STD_VIDEO_AV1_NUM_REF_FRAMES; i++) {
+        const AV1VulkanDecodePicture* rp = s->ref[i].hwaccel_picture_private;
+        if (rp)
+            frame_id_alloc_mask |= 1 << rp->frame_id;
+    }
+
+    if (!ap->frame_id_set) {
+        unsigned slot_idx = 0;
+        for (unsigned i = 0; i < 32; i++) {
+            if (!(frame_id_alloc_mask & (1 << i))) {
+                slot_idx = i;
+                break;
+            }
+        }
+        ap->frame_id = slot_idx;
+        ap->frame_id_set = 1;
+        frame_id_alloc_mask |= (1 << slot_idx);
+    }
+
+    ap->ref_frame_sign_bias_mask = 0x0;
+    for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++)
+        ap->ref_frame_sign_bias_mask |= pic->ref_frame_sign_bias[i] << i;
+
+    for (int i = 0; i < STD_VIDEO_AV1_REFS_PER_FRAME; i++) {
+        const int idx = pic->raw_frame_header->ref_frame_idx[i];
+        const AV1Frame *ref_frame = &s->ref[idx];
+        AV1VulkanDecodePicture *hp = ref_frame->hwaccel_picture_private;
+        int found = 0;
+
+        if (!ref_frame->f)
+            continue;
+
+        for (int j = 0; j < ref_count; j++) {
+            if (vp->ref_slots[j].slotIndex == hp->frame_id) {
+                found = 1;
+                break;
+            }
+        }
+        if (found)
+            continue;
+
+        err = vk_av1_fill_pict(avctx, &ap->ref_src[ref_count], &vp->ref_slots[ref_count],
+                               &vp->refs[ref_count], &ap->std_refs[ref_count], &ap->vkav1_refs[ref_count],
+                               ref_frame, 0, 0, ref_frame->order_hints);
+        if (err < 0)
+            return err;
+
+        ref_count++;
+    }
+
+    err = vk_av1_fill_pict(avctx, NULL, &vp->ref_slot, &vp->ref,
+                           &ap->std_ref,
+                           &ap->vkav1_ref,
+                           pic, 1, apply_grain, NULL);
+    if (err < 0)
+        return err;
+
+    ap->av1_pic_info = (VkVideoDecodeAV1PictureInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PICTURE_INFO_KHR,
+        .pStdPictureInfo = &ap->std_pic_info,
+        .frameHeaderOffset = 0,
+        .tileCount = 0,
+        .pTileOffsets = NULL,
+        .pTileSizes = ap->tile_sizes,
+    };
+
+    for (int i = 0; i < STD_VIDEO_AV1_REFS_PER_FRAME; i++) {
+        const int idx = pic->raw_frame_header->ref_frame_idx[i];
+        const AV1Frame *ref_frame = &s->ref[idx];
+        AV1VulkanDecodePicture *hp = ref_frame->hwaccel_picture_private;
+
+        if (!ref_frame->f)
+            ap->av1_pic_info.referenceNameSlotIndices[i] = AV1_REF_FRAME_NONE;
+        else
+            ap->av1_pic_info.referenceNameSlotIndices[i] = hp->frame_id;
+    }
+
+    vp->decode_info = (VkVideoDecodeInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR,
+        .pNext = &ap->av1_pic_info,
+        .flags = 0x0,
+        .pSetupReferenceSlot = &vp->ref_slot,
+        .referenceSlotCount = ref_count,
+        .pReferenceSlots = vp->ref_slots,
+        .dstPictureResource = (VkVideoPictureResourceInfoKHR) {
+            .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
+            .codedOffset = (VkOffset2D){ 0, 0 },
+            .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
+            .baseArrayLayer = 0,
+            .imageViewBinding = vp->view.out[0],
+        },
+    };
+
+    ap->tile_info = (StdVideoAV1TileInfo) {
+        .flags = (StdVideoAV1TileInfoFlags) {
+            .uniform_tile_spacing_flag = frame_header->uniform_tile_spacing_flag,
+        },
+        .TileCols = frame_header->tile_cols,
+        .TileRows = frame_header->tile_rows,
+        .context_update_tile_id = frame_header->context_update_tile_id,
+        .tile_size_bytes_minus_1 = frame_header->tile_size_bytes_minus1,
+        .pWidthInSbsMinus1 = ap->width_in_sbs_minus1,
+        .pHeightInSbsMinus1 = ap->height_in_sbs_minus1,
+        .pMiColStarts = ap->mi_col_starts,
+        .pMiRowStarts = ap->mi_row_starts,
+    };
+
+    ap->quantization = (StdVideoAV1Quantization) {
+        .flags.using_qmatrix = frame_header->using_qmatrix,
+        .flags.diff_uv_delta = frame_header->diff_uv_delta,
+        .base_q_idx = frame_header->base_q_idx,
+        .DeltaQYDc = frame_header->delta_q_y_dc,
+        .DeltaQUDc = frame_header->delta_q_u_dc,
+        .DeltaQUAc = frame_header->delta_q_u_ac,
+        .DeltaQVDc = frame_header->delta_q_v_dc,
+        .DeltaQVAc = frame_header->delta_q_v_ac,
+        .qm_y = frame_header->qm_y,
+        .qm_u = frame_header->qm_u,
+        .qm_v = frame_header->qm_v,
+    };
+
+    ap->loop_filter = (StdVideoAV1LoopFilter) {
+        .flags = (StdVideoAV1LoopFilterFlags) {
+            .loop_filter_delta_enabled = frame_header->loop_filter_delta_enabled,
+            .loop_filter_delta_update = frame_header->loop_filter_delta_update,
+        },
+        .loop_filter_sharpness = frame_header->loop_filter_sharpness,
+    };
+
+    for (int i = 0; i < STD_VIDEO_AV1_MAX_LOOP_FILTER_STRENGTHS; i++)
+        ap->loop_filter.loop_filter_level[i] = frame_header->loop_filter_level[i];
+    for (int i = 0; i < STD_VIDEO_AV1_LOOP_FILTER_ADJUSTMENTS; i++)
+        ap->loop_filter.loop_filter_mode_deltas[i] = frame_header->loop_filter_mode_deltas[i];
+
+    ap->cdef = (StdVideoAV1CDEF) {
+        .cdef_damping_minus_3 = frame_header->cdef_damping_minus_3,
+        .cdef_bits = frame_header->cdef_bits,
+    };
+
+    ap->loop_restoration = (StdVideoAV1LoopRestoration) {
+        .FrameRestorationType[0] = remap_lr_type[frame_header->lr_type[0]],
+        .FrameRestorationType[1] = remap_lr_type[frame_header->lr_type[1]],
+        .FrameRestorationType[2] = remap_lr_type[frame_header->lr_type[2]],
+        .LoopRestorationSize[0] = 1 + frame_header->lr_unit_shift,
+        .LoopRestorationSize[1] = 1 + frame_header->lr_unit_shift - frame_header->lr_uv_shift,
+        .LoopRestorationSize[2] = 1 + frame_header->lr_unit_shift - frame_header->lr_uv_shift,
+    };
+
+    ap->film_grain = (StdVideoAV1FilmGrain) {
+        .flags = (StdVideoAV1FilmGrainFlags) {
+            .chroma_scaling_from_luma = film_grain->chroma_scaling_from_luma,
+            .overlap_flag = film_grain->overlap_flag,
+            .clip_to_restricted_range = film_grain->clip_to_restricted_range,
+        },
+        .grain_scaling_minus_8 = film_grain->grain_scaling_minus_8,
+        .ar_coeff_lag = film_grain->ar_coeff_lag,
+        .ar_coeff_shift_minus_6 = film_grain->ar_coeff_shift_minus_6,
+        .grain_scale_shift = film_grain->grain_scale_shift,
+        .grain_seed = film_grain->grain_seed,
+        .film_grain_params_ref_idx = film_grain->film_grain_params_ref_idx,
+        .num_y_points = film_grain->num_y_points,
+        .num_cb_points = film_grain->num_cb_points,
+        .num_cr_points = film_grain->num_cr_points,
+        .cb_mult = film_grain->cb_mult,
+        .cb_luma_mult = film_grain->cb_luma_mult,
+        .cb_offset = film_grain->cb_offset,
+        .cr_mult = film_grain->cr_mult,
+        .cr_luma_mult = film_grain->cr_luma_mult,
+        .cr_offset = film_grain->cr_offset,
+    };
+
+    /* Setup frame header */
+    ap->std_pic_info = (StdVideoDecodeAV1PictureInfo) {
+        .flags = (StdVideoDecodeAV1PictureInfoFlags) {
+            .error_resilient_mode = frame_header->error_resilient_mode,
+            .disable_cdf_update = frame_header->disable_cdf_update,
+            .use_superres = frame_header->use_superres,
+            .render_and_frame_size_different = frame_header->render_and_frame_size_different,
+            .allow_screen_content_tools = frame_header->allow_screen_content_tools,
+            .is_filter_switchable = frame_header->is_filter_switchable,
+            .force_integer_mv = pic->force_integer_mv,
+            .frame_size_override_flag = frame_header->frame_size_override_flag,
+            .buffer_removal_time_present_flag = frame_header->buffer_removal_time_present_flag,
+            .allow_intrabc = frame_header->allow_intrabc,
+            .frame_refs_short_signaling = frame_header->frame_refs_short_signaling,
+            .allow_high_precision_mv = frame_header->allow_high_precision_mv,
+            .is_motion_mode_switchable = frame_header->is_motion_mode_switchable,
+            .use_ref_frame_mvs = frame_header->use_ref_frame_mvs,
+            .disable_frame_end_update_cdf = frame_header->disable_frame_end_update_cdf,
+            .allow_warped_motion = frame_header->allow_warped_motion,
+            .reduced_tx_set = frame_header->reduced_tx_set,
+            .reference_select = frame_header->reference_select,
+            .skip_mode_present = frame_header->skip_mode_present,
+            .delta_q_present = frame_header->delta_q_present,
+            .delta_lf_present = frame_header->delta_lf_present,
+            .delta_lf_multi = frame_header->delta_lf_multi,
+            .segmentation_enabled = frame_header->segmentation_enabled,
+            .segmentation_update_map = frame_header->segmentation_update_map,
+            .segmentation_temporal_update = frame_header->segmentation_temporal_update,
+            .segmentation_update_data = frame_header->segmentation_update_data,
+            .UsesLr = frame_header->lr_type[0] || frame_header->lr_type[1] || frame_header->lr_type[2],
+            .apply_grain = apply_grain,
+        },
+        .frame_type = frame_header->frame_type,
+        .current_frame_id = frame_header->current_frame_id,
+        .OrderHint = frame_header->order_hint,
+        .primary_ref_frame = frame_header->primary_ref_frame,
+        .refresh_frame_flags = frame_header->refresh_frame_flags,
+        .interpolation_filter = frame_header->interpolation_filter,
+        .TxMode = frame_header->tx_mode,
+        .delta_q_res = frame_header->delta_q_res,
+        .delta_lf_res = frame_header->delta_lf_res,
+        .SkipModeFrame[0] = s->cur_frame.skip_mode_frame_idx[0],
+        .SkipModeFrame[1] = s->cur_frame.skip_mode_frame_idx[1],
+        .coded_denom = frame_header->coded_denom,
+        .pTileInfo = &ap->tile_info,
+        .pQuantization = &ap->quantization,
+        .pSegmentation = &ap->segmentation,
+        .pLoopFilter = &ap->loop_filter,
+        .pCDEF = &ap->cdef,
+        .pLoopRestoration = &ap->loop_restoration,
+        .pGlobalMotion = &ap->global_motion,
+        .pFilmGrain = apply_grain ? &ap->film_grain : NULL,
+    };
+
+    for (int i = 0; i < 64; i++) {
+        ap->width_in_sbs_minus1[i] = frame_header->width_in_sbs_minus_1[i];
+        ap->height_in_sbs_minus1[i] = frame_header->height_in_sbs_minus_1[i];
+        ap->mi_col_starts[i] = frame_header->tile_start_col_sb[i];
+        ap->mi_row_starts[i] = frame_header->tile_start_row_sb[i];
+    }
+
+    for (int i = 0; i < STD_VIDEO_AV1_MAX_SEGMENTS; i++) {
+        ap->segmentation.FeatureEnabled[i] = 0x0;
+        for (int j = 0; j < STD_VIDEO_AV1_SEG_LVL_MAX; j++) {
+            ap->segmentation.FeatureEnabled[i] |= (frame_header->feature_enabled[i][j] << j);
+            ap->segmentation.FeatureData[i][j] = frame_header->feature_value[i][j];
+        }
+    }
+
+    if (dec->quirk_av1_offset)
+        for (int i = 1; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++)
+            ap->std_pic_info.OrderHints[i - 1] = pic->order_hints[i];
+    else
+        for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++)
+            ap->std_pic_info.OrderHints[i] = pic->order_hints[i];
+
+    for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++) {
+        ap->loop_filter.loop_filter_ref_deltas[i] = frame_header->loop_filter_ref_deltas[i];
+        ap->global_motion.GmType[i] = s->cur_frame.gm_type[i];
+        for (int j = 0; j < STD_VIDEO_AV1_GLOBAL_MOTION_PARAMS; j++) {
+            ap->global_motion.gm_params[i][j] = s->cur_frame.gm_params[i][j];
+        }
+    }
+
+    for (int i = 0; i < STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS; i++) {
+        ap->cdef.cdef_y_pri_strength[i] = frame_header->cdef_y_pri_strength[i];
+        ap->cdef.cdef_y_sec_strength[i] = frame_header->cdef_y_sec_strength[i];
+        ap->cdef.cdef_uv_pri_strength[i] = frame_header->cdef_uv_pri_strength[i];
+        ap->cdef.cdef_uv_sec_strength[i] = frame_header->cdef_uv_sec_strength[i];
+    }
+
+    if (apply_grain) {
+        for (int i = 0; i < STD_VIDEO_AV1_MAX_NUM_Y_POINTS; i++) {
+            ap->film_grain.point_y_value[i] = film_grain->point_y_value[i];
+            ap->film_grain.point_y_scaling[i] = film_grain->point_y_scaling[i];
+        }
+
+        for (int i = 0; i < STD_VIDEO_AV1_MAX_NUM_CB_POINTS; i++) {
+            ap->film_grain.point_cb_value[i] = film_grain->point_cb_value[i];
+            ap->film_grain.point_cb_scaling[i] = film_grain->point_cb_scaling[i];
+            ap->film_grain.point_cr_value[i] = film_grain->point_cr_value[i];
+            ap->film_grain.point_cr_scaling[i] = film_grain->point_cr_scaling[i];
+        }
+
+        for (int i = 0; i < STD_VIDEO_AV1_MAX_NUM_POS_LUMA; i++)
+            ap->film_grain.ar_coeffs_y_plus_128[i] = film_grain->ar_coeffs_y_plus_128[i];
+
+        for (int i = 0; i < STD_VIDEO_AV1_MAX_NUM_POS_CHROMA; i++) {
+            ap->film_grain.ar_coeffs_cb_plus_128[i] = film_grain->ar_coeffs_cb_plus_128[i];
+            ap->film_grain.ar_coeffs_cr_plus_128[i] = film_grain->ar_coeffs_cr_plus_128[i];
+        }
+    }
+
+    ap->dec = dec;
+
+    return 0;
+}
+
+static int vk_av1_decode_slice(AVCodecContext *avctx,
+                               const uint8_t  *data,
+                               uint32_t        size)
+{
+    int err;
+    const AV1DecContext *s = avctx->priv_data;
+    AV1VulkanDecodePicture *ap = s->cur_frame.hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &ap->vp;
+
+    /* Too many tiles, exceeding all defined levels in the AV1 spec */
+    if (ap->av1_pic_info.tileCount > MAX_TILES)
+        return AVERROR(ENOSYS);
+
+    for (int i = s->tg_start; i <= s->tg_end; i++) {
+        ap->tile_sizes[ap->av1_pic_info.tileCount] = s->tile_group_info[i].tile_size;
+
+        err = ff_vk_decode_add_slice(avctx, vp,
+                                     data + s->tile_group_info[i].tile_offset,
+                                     s->tile_group_info[i].tile_size, 0,
+                                     &ap->av1_pic_info.tileCount,
+                                     &ap->av1_pic_info.pTileOffsets);
+        if (err < 0)
+            return err;
+    }
+
+    return 0;
+}
+
+static int vk_av1_end_frame(AVCodecContext *avctx)
+{
+    const AV1DecContext *s = avctx->priv_data;
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+
+    const AV1Frame *pic = &s->cur_frame;
+    AV1VulkanDecodePicture *ap = pic->hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &ap->vp;
+    FFVulkanDecodePicture *rvp[AV1_NUM_REF_FRAMES] = { 0 };
+    AVFrame *rav[AV1_NUM_REF_FRAMES] = { 0 };
+
+#ifdef VK_KHR_video_maintenance2
+    StdVideoAV1SequenceHeader av1_sequence_header;
+    StdVideoAV1TimingInfo av1_timing_info;
+    StdVideoAV1ColorConfig av1_color_config;
+    VkVideoDecodeAV1InlineSessionParametersInfoKHR av1_params;
+
+    if (ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2) {
+        vk_av1_params_fill(avctx, &av1_timing_info, &av1_color_config,
+                           &av1_sequence_header);
+        av1_params = (VkVideoDecodeAV1InlineSessionParametersInfoKHR) {
+            .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_INLINE_SESSION_PARAMETERS_INFO_KHR,
+            .pStdSequenceHeader = &av1_sequence_header,
+        };
+        ap->av1_pic_info.pNext = &av1_params;
+    }
+#endif
+
+    if (!ap->av1_pic_info.tileCount)
+        return 0;
+
+    if (!dec->session_params &&
+        !(ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)) {
+        int err = vk_av1_create_params(avctx, &dec->session_params, ap);
+        if (err < 0)
+            return err;
+    }
+
+    for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
+        const AV1Frame *rp = ap->ref_src[i];
+        AV1VulkanDecodePicture *rhp = rp->hwaccel_picture_private;
+
+        rvp[i] = &rhp->vp;
+        rav[i] = ap->ref_src[i]->f;
+    }
+
+    av_log(avctx, AV_LOG_DEBUG, "Decoding frame, %"SIZE_SPECIFIER" bytes, %i tiles\n",
+           vp->slices_size, ap->av1_pic_info.tileCount);
+
+    return ff_vk_decode_frame(avctx, pic->f, vp, rav, rvp);
+}
+
+static void vk_av1_free_frame_priv(AVRefStructOpaque _hwctx, void *data)
+{
+    AVHWDeviceContext *hwctx = _hwctx.nc;
+    AV1VulkanDecodePicture *ap = data;
+
+    /* Free frame resources, this also destroys the session parameters. */
+    ff_vk_decode_free_frame(hwctx, &ap->vp);
+}
+
+const FFHWAccel ff_av1_vulkan_hwaccel = {
+    .p.name                = "av1_vulkan",
+    .p.type                = AVMEDIA_TYPE_VIDEO,
+    .p.id                  = AV_CODEC_ID_AV1,
+    .p.pix_fmt             = AV_PIX_FMT_VULKAN,
+    .start_frame           = &vk_av1_start_frame,
+    .decode_slice          = &vk_av1_decode_slice,
+    .end_frame             = &vk_av1_end_frame,
+    .free_frame_priv       = &vk_av1_free_frame_priv,
+    .frame_priv_data_size  = sizeof(AV1VulkanDecodePicture),
+    .init                  = &ff_vk_decode_init,
+    .update_thread_context = &ff_vk_update_thread_context,
+    .decode_params         = &ff_vk_params_invalidate,
+    .flush                 = &ff_vk_decode_flush,
+    .uninit                = &ff_vk_decode_uninit,
+    .frame_params          = &ff_vk_frame_params,
+    .priv_data_size        = sizeof(FFVulkanDecodeContext),
+    .caps_internal         = HWACCEL_CAP_ASYNC_SAFE,
+};
-- 
2.49.1


From 170d83ecd684b45078a6377dbfbc9652713102db Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:29:02 +0000
Subject: [PATCH 065/118] Changing vulkan file directory

---
 libavcodec/vulkan_decode.c | 1399 ------------------------------------
 1 file changed, 1399 deletions(-)
 delete mode 100644 libavcodec/vulkan_decode.c

diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c
deleted file mode 100644
index b038d456dd..0000000000
--- a/libavcodec/vulkan_decode.c
+++ /dev/null
@@ -1,1399 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/refstruct.h"
-#include "vulkan_video.h"
-#include "vulkan_decode.h"
-#include "config_components.h"
-#include "libavutil/avassert.h"
-#include "libavutil/mem.h"
-#include "libavutil/vulkan_loader.h"
-
-#define DECODER_IS_SDR(codec_id) \
-    (((codec_id) == AV_CODEC_ID_FFV1) || \
-     ((codec_id) == AV_CODEC_ID_PRORES_RAW))
-
-#if CONFIG_H264_VULKAN_HWACCEL
-extern const FFVulkanDecodeDescriptor ff_vk_dec_h264_desc;
-#endif
-#if CONFIG_HEVC_VULKAN_HWACCEL
-extern const FFVulkanDecodeDescriptor ff_vk_dec_hevc_desc;
-#endif
-#if CONFIG_VP9_VULKAN_HWACCEL
-extern const FFVulkanDecodeDescriptor ff_vk_dec_vp9_desc;
-#endif
-#if CONFIG_AV1_VULKAN_HWACCEL
-extern const FFVulkanDecodeDescriptor ff_vk_dec_av1_desc;
-#endif
-#if CONFIG_FFV1_VULKAN_HWACCEL
-extern const FFVulkanDecodeDescriptor ff_vk_dec_ffv1_desc;
-#endif
-#if CONFIG_PRORES_RAW_VULKAN_HWACCEL
-extern const FFVulkanDecodeDescriptor ff_vk_dec_prores_raw_desc;
-#endif
-
-static const FFVulkanDecodeDescriptor *dec_descs[] = {
-#if CONFIG_H264_VULKAN_HWACCEL
-    &ff_vk_dec_h264_desc,
-#endif
-#if CONFIG_HEVC_VULKAN_HWACCEL
-    &ff_vk_dec_hevc_desc,
-#endif
-#if CONFIG_VP9_VULKAN_HWACCEL
-    &ff_vk_dec_vp9_desc,
-#endif
-#if CONFIG_AV1_VULKAN_HWACCEL
-    &ff_vk_dec_av1_desc,
-#endif
-#if CONFIG_FFV1_VULKAN_HWACCEL
-    &ff_vk_dec_ffv1_desc,
-#endif
-#if CONFIG_PRORES_RAW_VULKAN_HWACCEL
-    &ff_vk_dec_prores_raw_desc,
-#endif
-};
-
-typedef struct FFVulkanDecodeProfileData {
-     VkVideoDecodeH264ProfileInfoKHR h264_profile;
-     VkVideoDecodeH265ProfileInfoKHR h265_profile;
-#if CONFIG_VP9_VULKAN_HWACCEL
-     VkVideoDecodeVP9ProfileInfoKHR vp9_profile;
-#endif
-     VkVideoDecodeAV1ProfileInfoKHR av1_profile;
-
-    VkVideoDecodeUsageInfoKHR usage;
-    VkVideoProfileInfoKHR profile;
-    VkVideoProfileListInfoKHR profile_list;
-} FFVulkanDecodeProfileData;
-
-static const FFVulkanDecodeDescriptor *get_codecdesc(enum AVCodecID codec_id)
-{
-    for (size_t i = 0; i < FF_ARRAY_ELEMS(dec_descs); i++)
-        if (dec_descs[i]->codec_id == codec_id)
-            return dec_descs[i];
-    av_assert1(!"no codec descriptor");
-    return NULL;
-}
-
-static const VkVideoProfileInfoKHR *get_video_profile(FFVulkanDecodeShared *ctx, enum AVCodecID codec_id)
-{
-    const VkVideoProfileListInfoKHR *profile_list;
-
-    VkStructureType profile_struct_type =
-        codec_id == AV_CODEC_ID_H264 ? VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR :
-        codec_id == AV_CODEC_ID_HEVC ? VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR :
-#if CONFIG_VP9_VULKAN_HWACCEL
-        codec_id == AV_CODEC_ID_VP9  ? VK_STRUCTURE_TYPE_VIDEO_DECODE_VP9_PROFILE_INFO_KHR :
-#endif
-        codec_id == AV_CODEC_ID_AV1  ? VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR :
-                                       VK_STRUCTURE_TYPE_MAX_ENUM;
-    if (profile_struct_type == VK_STRUCTURE_TYPE_MAX_ENUM)
-        return NULL;
-
-    profile_list = ff_vk_find_struct(ctx->s.hwfc->create_pnext,
-                                     VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
-    if (!profile_list)
-        return NULL;
-
-    for (int i = 0; i < profile_list->profileCount; i++)
-        if (ff_vk_find_struct(profile_list->pProfiles[i].pNext, profile_struct_type))
-            return &profile_list->pProfiles[i];
-
-    return NULL;
-}
-
-int ff_vk_update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
-{
-    int err;
-    FFVulkanDecodeContext *src_ctx = src->internal->hwaccel_priv_data;
-    FFVulkanDecodeContext *dst_ctx = dst->internal->hwaccel_priv_data;
-
-    av_refstruct_replace(&dst_ctx->shared_ctx, src_ctx->shared_ctx);
-
-    err = av_buffer_replace(&dst_ctx->session_params, src_ctx->session_params);
-    if (err < 0)
-        return err;
-
-    dst_ctx->dedicated_dpb = src_ctx->dedicated_dpb;
-    dst_ctx->external_fg = src_ctx->external_fg;
-
-    return 0;
-}
-
-int ff_vk_params_invalidate(AVCodecContext *avctx, int t, const uint8_t *b, uint32_t s)
-{
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    av_buffer_unref(&dec->session_params);
-    return 0;
-}
-
-static AVFrame *vk_get_dpb_pool(FFVulkanDecodeShared *ctx)
-{
-    int err;
-    AVFrame *avf = av_frame_alloc();
-    if (!avf)
-        return NULL;
-
-    err = av_hwframe_get_buffer(ctx->common.dpb_hwfc_ref, avf, 0x0);
-    if (err < 0)
-        av_frame_free(&avf);
-
-    return avf;
-}
-
-static void init_frame(FFVulkanDecodeContext *dec, FFVulkanDecodePicture *vkpic)
-{
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-
-    vkpic->dpb_frame     = NULL;
-    for (int i = 0; i < AV_NUM_DATA_POINTERS; i++) {
-        vkpic->view.ref[i]  = VK_NULL_HANDLE;
-        vkpic->view.out[i]  = VK_NULL_HANDLE;
-        vkpic->view.dst[i]  = VK_NULL_HANDLE;
-    }
-
-    vkpic->destroy_image_view = vk->DestroyImageView;
-    vkpic->wait_semaphores = vk->WaitSemaphores;
-    vkpic->invalidate_memory_ranges = vk->InvalidateMappedMemoryRanges;
-}
-
-int ff_vk_decode_prepare_frame(FFVulkanDecodeContext *dec, AVFrame *pic,
-                               FFVulkanDecodePicture *vkpic, int is_current,
-                               int alloc_dpb)
-{
-    int err;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-
-    vkpic->slices_size = 0;
-
-    /* If the decoder made a blank frame to make up for a missing ref, or the
-     * frame is the current frame so it's missing one, create a re-representation */
-    if (vkpic->view.ref[0])
-        return 0;
-
-    init_frame(dec, vkpic);
-
-    if (ctx->common.layered_dpb && alloc_dpb) {
-        vkpic->view.ref[0] = ctx->common.layered_view;
-        vkpic->view.aspect_ref[0] = ctx->common.layered_aspect;
-    } else if (alloc_dpb) {
-        AVHWFramesContext *dpb_frames = (AVHWFramesContext *)ctx->common.dpb_hwfc_ref->data;
-        AVVulkanFramesContext *dpb_hwfc = dpb_frames->hwctx;
-
-        vkpic->dpb_frame = vk_get_dpb_pool(ctx);
-        if (!vkpic->dpb_frame)
-            return AVERROR(ENOMEM);
-
-        err = ff_vk_create_view(&ctx->s, &ctx->common,
-                                &vkpic->view.ref[0], &vkpic->view.aspect_ref[0],
-                                (AVVkFrame *)vkpic->dpb_frame->data[0],
-                                dpb_hwfc->format[0], !is_current);
-        if (err < 0)
-            return err;
-
-        vkpic->view.dst[0] = vkpic->view.ref[0];
-    }
-
-    if (!alloc_dpb || is_current) {
-        AVHWFramesContext *frames = (AVHWFramesContext *)pic->hw_frames_ctx->data;
-        AVVulkanFramesContext *hwfc = frames->hwctx;
-
-        err = ff_vk_create_view(&ctx->s, &ctx->common,
-                                &vkpic->view.out[0], &vkpic->view.aspect[0],
-                                (AVVkFrame *)pic->data[0],
-                                hwfc->format[0], !is_current);
-        if (err < 0)
-            return err;
-
-        if (!alloc_dpb) {
-            vkpic->view.ref[0] = vkpic->view.out[0];
-            vkpic->view.aspect_ref[0] = vkpic->view.aspect[0];
-        }
-    }
-
-    return 0;
-}
-
-int ff_vk_decode_prepare_frame_sdr(FFVulkanDecodeContext *dec, AVFrame *pic,
-                                   FFVulkanDecodePicture *vkpic, int is_current,
-                                   enum FFVkShaderRepFormat rep_fmt, int alloc_dpb)
-{
-    int err;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-    AVHWFramesContext *frames = (AVHWFramesContext *)pic->hw_frames_ctx->data;
-
-    vkpic->slices_size = 0;
-
-    if (vkpic->view.ref[0])
-        return 0;
-
-    init_frame(dec, vkpic);
-
-    for (int i = 0; i < av_pix_fmt_count_planes(frames->sw_format); i++) {
-        if (alloc_dpb) {
-            vkpic->dpb_frame = vk_get_dpb_pool(ctx);
-            if (!vkpic->dpb_frame)
-                return AVERROR(ENOMEM);
-
-            err = ff_vk_create_imageview(&ctx->s,
-                                         &vkpic->view.ref[i], &vkpic->view.aspect_ref[i],
-                                         vkpic->dpb_frame, i, rep_fmt);
-            if (err < 0)
-                return err;
-
-            vkpic->view.dst[i] = vkpic->view.ref[i];
-        }
-
-        if (!alloc_dpb || is_current) {
-            err = ff_vk_create_imageview(&ctx->s,
-                                         &vkpic->view.out[i], &vkpic->view.aspect[i],
-                                         pic, i, rep_fmt);
-            if (err < 0)
-                return err;
-
-            if (!alloc_dpb) {
-                vkpic->view.ref[i] = vkpic->view.out[i];
-                vkpic->view.aspect_ref[i] = vkpic->view.aspect[i];
-            }
-        }
-    }
-
-    return 0;
-}
-
-int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp,
-                           const uint8_t *data, size_t size, int add_startcode,
-                           uint32_t *nb_slices, const uint32_t **offsets)
-{
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-
-    static const uint8_t startcode_prefix[3] = { 0x0, 0x0, 0x1 };
-    const size_t startcode_len = add_startcode ? sizeof(startcode_prefix) : 0;
-    const int nb = nb_slices ? *nb_slices : 0;
-    uint8_t *slices;
-    uint32_t *slice_off;
-    FFVkBuffer *vkbuf;
-
-    size_t new_size = vp->slices_size + startcode_len + size +
-                      ctx->caps.minBitstreamBufferSizeAlignment;
-    new_size = FFALIGN(new_size, ctx->caps.minBitstreamBufferSizeAlignment);
-
-    if (offsets) {
-        slice_off = av_fast_realloc(dec->slice_off, &dec->slice_off_max,
-                                    (nb + 1)*sizeof(slice_off));
-        if (!slice_off)
-            return AVERROR(ENOMEM);
-
-        *offsets = dec->slice_off = slice_off;
-
-        slice_off[nb] = vp->slices_size;
-    }
-
-    vkbuf = vp->slices_buf ? (FFVkBuffer *)vp->slices_buf->data : NULL;
-    if (!vkbuf || vkbuf->size < new_size) {
-        int err;
-        AVBufferRef *new_ref;
-        FFVkBuffer *new_buf;
-
-        /* No point in requesting anything smaller. */
-        size_t buf_size = FFMAX(new_size, 1024*1024);
-
-        /* Align buffer to nearest power of two. Makes fragmentation management
-         * easier, and gives us ample headroom. */
-        buf_size = 2 << av_log2(buf_size);
-
-        err = ff_vk_get_pooled_buffer(&ctx->s, &ctx->buf_pool, &new_ref,
-                                      DECODER_IS_SDR(avctx->codec_id) ?
-                                      (VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
-                                       VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) :
-                                      VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR,
-                                      ctx->s.hwfc->create_pnext, buf_size,
-                                      VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
-                                      (DECODER_IS_SDR(avctx->codec_id) ?
-                                       VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT : 0x0));
-        if (err < 0)
-            return err;
-
-        new_buf = (FFVkBuffer *)new_ref->data;
-
-        /* Copy data from the old buffer */
-        if (vkbuf) {
-            memcpy(new_buf->mapped_mem, vkbuf->mapped_mem, vp->slices_size);
-            av_buffer_unref(&vp->slices_buf);
-        }
-
-        vp->slices_buf = new_ref;
-        vkbuf = new_buf;
-    }
-    slices = vkbuf->mapped_mem;
-
-    /* Startcode */
-    memcpy(slices + vp->slices_size, startcode_prefix, startcode_len);
-
-    /* Slice data */
-    memcpy(slices + vp->slices_size + startcode_len, data, size);
-
-    if (nb_slices)
-        *nb_slices = nb + 1;
-
-    vp->slices_size += startcode_len + size;
-
-    return 0;
-}
-
-void ff_vk_decode_flush(AVCodecContext *avctx)
-{
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-    VkVideoBeginCodingInfoKHR decode_start = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
-        .videoSession = ctx->common.session,
-        .videoSessionParameters = ctx->empty_session_params,
-    };
-    VkVideoCodingControlInfoKHR decode_ctrl = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR,
-        .flags = VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR,
-    };
-    VkVideoEndCodingInfoKHR decode_end = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR,
-    };
-
-    VkCommandBuffer cmd_buf;
-    FFVkExecContext *exec;
-
-    /* Non-video queues do not need to be reset */
-    if (!(get_codecdesc(avctx->codec_id)->decode_op))
-        return;
-
-    exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
-    ff_vk_exec_start(&ctx->s, exec);
-    cmd_buf = exec->buf;
-
-    vk->CmdBeginVideoCodingKHR(cmd_buf, &decode_start);
-    vk->CmdControlVideoCodingKHR(cmd_buf, &decode_ctrl);
-    vk->CmdEndVideoCodingKHR(cmd_buf, &decode_end);
-    ff_vk_exec_submit(&ctx->s, exec);
-}
-
-int ff_vk_decode_frame(AVCodecContext *avctx,
-                       AVFrame *pic,    FFVulkanDecodePicture *vp,
-                       AVFrame *rpic[], FFVulkanDecodePicture *rvkp[])
-{
-    int err;
-    VkResult ret;
-    VkCommandBuffer cmd_buf;
-    FFVkBuffer *sd_buf;
-
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-
-    /* Output */
-    AVVkFrame *vkf = (AVVkFrame *)pic->buf[0]->data;
-
-    /* Quirks */
-    const int layered_dpb = ctx->common.layered_dpb;
-
-    VkVideoBeginCodingInfoKHR decode_start = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
-        .videoSession = ctx->common.session,
-        .videoSessionParameters = dec->session_params ?
-                                  *((VkVideoSessionParametersKHR *)dec->session_params->data) :
-                                  VK_NULL_HANDLE,
-        .referenceSlotCount = vp->decode_info.referenceSlotCount,
-        .pReferenceSlots = vp->decode_info.pReferenceSlots,
-    };
-    VkVideoEndCodingInfoKHR decode_end = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR,
-    };
-
-    VkImageMemoryBarrier2 img_bar[37];
-    int nb_img_bar = 0;
-    size_t data_size = FFALIGN(vp->slices_size,
-                               ctx->caps.minBitstreamBufferSizeAlignment);
-
-    FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
-
-    /* The current decoding reference has to be bound as an inactive reference */
-    VkVideoReferenceSlotInfoKHR *cur_vk_ref;
-    cur_vk_ref = (void *)&decode_start.pReferenceSlots[decode_start.referenceSlotCount];
-    cur_vk_ref[0] = vp->ref_slot;
-    cur_vk_ref[0].slotIndex = -1;
-    decode_start.referenceSlotCount++;
-
-    sd_buf = (FFVkBuffer *)vp->slices_buf->data;
-
-    /* Flush if needed */
-    if (!(sd_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
-        VkMappedMemoryRange flush_buf = {
-            .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
-            .memory = sd_buf->mem,
-            .offset = 0,
-            .size = FFALIGN(vp->slices_size,
-                            ctx->s.props.properties.limits.nonCoherentAtomSize),
-        };
-
-        ret = vk->FlushMappedMemoryRanges(ctx->s.hwctx->act_dev, 1, &flush_buf);
-        if (ret != VK_SUCCESS) {
-            av_log(avctx, AV_LOG_ERROR, "Failed to flush memory: %s\n",
-                   ff_vk_ret2str(ret));
-            return AVERROR_EXTERNAL;
-        }
-    }
-
-    vp->decode_info.srcBuffer       = sd_buf->buf;
-    vp->decode_info.srcBufferOffset = 0;
-    vp->decode_info.srcBufferRange  = data_size;
-
-    /* Start command buffer recording */
-    err = ff_vk_exec_start(&ctx->s, exec);
-    if (err < 0)
-        return err;
-    cmd_buf = exec->buf;
-
-    /* Slices */
-    err = ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0);
-    if (err < 0)
-        return err;
-    vp->slices_buf = NULL; /* Owned by the exec buffer from now on */
-
-    /* Parameters */
-    err = ff_vk_exec_add_dep_buf(&ctx->s, exec, &dec->session_params, 1, 1);
-    if (err < 0)
-        return err;
-
-    err = ff_vk_exec_add_dep_frame(&ctx->s, exec, pic,
-                                   VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
-                                   VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
-    if (err < 0)
-        return err;
-
-    err = ff_vk_exec_mirror_sem_value(&ctx->s, exec, &vp->sem, &vp->sem_value,
-                                      pic);
-    if (err < 0)
-        return err;
-
-    /* Output image - change layout, as it comes from a pool */
-    img_bar[nb_img_bar] = (VkImageMemoryBarrier2) {
-        .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
-        .pNext = NULL,
-        .srcStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
-        .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
-        .srcAccessMask = VK_ACCESS_2_NONE,
-        .dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR,
-        .oldLayout = vkf->layout[0],
-        .newLayout = (layered_dpb || vp->dpb_frame) ?
-                     VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR :
-                     VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, /* Spec, 07252 utter madness */
-        .srcQueueFamilyIndex = vkf->queue_family[0],
-        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .image = vkf->img[0],
-        .subresourceRange = (VkImageSubresourceRange) {
-            .aspectMask = vp->view.aspect[0],
-            .layerCount = 1,
-            .levelCount = 1,
-        },
-    };
-    ff_vk_exec_update_frame(&ctx->s, exec, pic,
-                            &img_bar[nb_img_bar], &nb_img_bar);
-
-    /* Reference for the current image, if existing and not layered */
-    if (vp->dpb_frame) {
-        err = ff_vk_exec_add_dep_frame(&ctx->s, exec, vp->dpb_frame,
-                                       VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
-                                       VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
-        if (err < 0)
-            return err;
-    }
-
-    if (!layered_dpb) {
-        /* All references (apart from the current) for non-layered refs */
-
-        for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
-            AVFrame *ref_frame = rpic[i];
-            FFVulkanDecodePicture *rvp = rvkp[i];
-            AVFrame *ref = rvp->dpb_frame ? rvp->dpb_frame : ref_frame;
-
-            err = ff_vk_exec_add_dep_frame(&ctx->s, exec, ref,
-                                           VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
-                                           VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
-            if (err < 0)
-                return err;
-
-            if (err == 0) {
-                err = ff_vk_exec_mirror_sem_value(&ctx->s, exec,
-                                                  &rvp->sem, &rvp->sem_value,
-                                                  ref);
-                if (err < 0)
-                    return err;
-            }
-
-            if (!rvp->dpb_frame) {
-                AVVkFrame *rvkf = (AVVkFrame *)ref->data[0];
-
-                img_bar[nb_img_bar] = (VkImageMemoryBarrier2) {
-                    .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
-                    .pNext = NULL,
-                    .srcStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
-                    .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
-                    .srcAccessMask = VK_ACCESS_2_NONE,
-                    .dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR |
-                                     VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR,
-                    .oldLayout = rvkf->layout[0],
-                    .newLayout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR,
-                    .srcQueueFamilyIndex = rvkf->queue_family[0],
-                    .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-                    .image = rvkf->img[0],
-                    .subresourceRange = (VkImageSubresourceRange) {
-                        .aspectMask = rvp->view.aspect_ref[0],
-                        .layerCount = 1,
-                        .levelCount = 1,
-                    },
-                };
-                ff_vk_exec_update_frame(&ctx->s, exec, ref,
-                                        &img_bar[nb_img_bar], &nb_img_bar);
-            }
-        }
-    } else if (vp->decode_info.referenceSlotCount ||
-               vp->view.out[0] != vp->view.ref[0]) {
-        /* Single barrier for a single layered ref */
-        err = ff_vk_exec_add_dep_frame(&ctx->s, exec, ctx->common.layered_frame,
-                                       VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
-                                       VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
-        if (err < 0)
-            return err;
-    }
-
-    /* Change image layout */
-    vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-            .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT,
-            .pImageMemoryBarriers = img_bar,
-            .imageMemoryBarrierCount = nb_img_bar,
-        });
-
-    /* Start, use parameters, decode and end decoding */
-    vk->CmdBeginVideoCodingKHR(cmd_buf, &decode_start);
-    vk->CmdDecodeVideoKHR(cmd_buf, &vp->decode_info);
-    vk->CmdEndVideoCodingKHR(cmd_buf, &decode_end);
-
-    /* End recording and submit for execution */
-    return ff_vk_exec_submit(&ctx->s, exec);
-}
-
-void ff_vk_decode_free_frame(AVHWDeviceContext *dev_ctx, FFVulkanDecodePicture *vp)
-{
-    AVVulkanDeviceContext *hwctx = dev_ctx->hwctx;
-
-    VkSemaphoreWaitInfo sem_wait = (VkSemaphoreWaitInfo) {
-        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
-        .pSemaphores = &vp->sem,
-        .pValues = &vp->sem_value,
-        .semaphoreCount = 1,
-    };
-
-    /* We do not have to lock the frame here because we're not interested
-     * in the actual current semaphore value, but only that it's later than
-     * the time we submitted the image for decoding. */
-    if (vp->sem)
-        vp->wait_semaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
-
-    /* Free slices data */
-    av_buffer_unref(&vp->slices_buf);
-
-    /* Destroy image view (out) */
-    for (int i = 0; i < AV_NUM_DATA_POINTERS; i++) {
-        if (vp->view.out[i] && vp->view.out[i] != vp->view.dst[i])
-            vp->destroy_image_view(hwctx->act_dev, vp->view.out[i], hwctx->alloc);
-
-        /* Destroy image view (ref, unlayered) */
-        if (vp->view.dst[i])
-            vp->destroy_image_view(hwctx->act_dev, vp->view.dst[i], hwctx->alloc);
-    }
-
-    av_frame_free(&vp->dpb_frame);
-}
-
-static void free_common(AVRefStructOpaque unused, void *obj)
-{
-    FFVulkanDecodeShared *ctx = obj;
-    FFVulkanContext *s = &ctx->s;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-
-    /* Wait on and free execution pool */
-    ff_vk_exec_pool_free(&ctx->s, &ctx->exec_pool);
-
-    /* This also frees all references from this pool */
-    av_frame_free(&ctx->common.layered_frame);
-
-    /* Destroy parameters */
-    if (ctx->empty_session_params)
-        vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
-                                             ctx->empty_session_params,
-                                             s->hwctx->alloc);
-
-    av_buffer_pool_uninit(&ctx->buf_pool);
-
-    ff_vk_video_common_uninit(s, &ctx->common);
-
-    if (ctx->sd_ctx_free)
-        ctx->sd_ctx_free(ctx);
-
-    ff_vk_uninit(s);
-}
-
-static int vulkan_decode_bootstrap(AVCodecContext *avctx, AVBufferRef *frames_ref)
-{
-    int err;
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    const FFVulkanDecodeDescriptor *vk_desc = get_codecdesc(avctx->codec_id);
-    AVHWFramesContext *frames = (AVHWFramesContext *)frames_ref->data;
-    AVHWDeviceContext *device = (AVHWDeviceContext *)frames->device_ref->data;
-    AVVulkanDeviceContext *hwctx = device->hwctx;
-    FFVulkanDecodeShared *ctx;
-
-    if (dec->shared_ctx)
-        return 0;
-
-    dec->shared_ctx = av_refstruct_alloc_ext(sizeof(*ctx), 0, NULL,
-                                             free_common);
-    if (!dec->shared_ctx)
-        return AVERROR(ENOMEM);
-
-    ctx = dec->shared_ctx;
-
-    ctx->s.extensions = ff_vk_extensions_to_mask(hwctx->enabled_dev_extensions,
-                                                 hwctx->nb_enabled_dev_extensions);
-
-    if (vk_desc->queue_flags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) {
-        if (!(ctx->s.extensions & FF_VK_EXT_VIDEO_DECODE_QUEUE)) {
-            av_log(avctx, AV_LOG_ERROR, "Device does not support the %s extension!\n",
-                   VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME);
-            av_refstruct_unref(&dec->shared_ctx);
-            return AVERROR(ENOSYS);
-        }
-    }
-
-    err = ff_vk_load_functions(device, &ctx->s.vkfn, ctx->s.extensions, 1, 1);
-    if (err < 0) {
-        av_refstruct_unref(&dec->shared_ctx);
-        return err;
-    }
-
-    return 0;
-}
-
-static VkResult vulkan_setup_profile(AVCodecContext *avctx,
-                                     FFVulkanDecodeProfileData *prof,
-                                     AVVulkanDeviceContext *hwctx,
-                                     FFVulkanFunctions *vk,
-                                     const FFVulkanDecodeDescriptor *vk_desc,
-                                     VkVideoDecodeH264CapabilitiesKHR *h264_caps,
-                                     VkVideoDecodeH265CapabilitiesKHR *h265_caps,
-#if CONFIG_VP9_VULKAN_HWACCEL
-                                     VkVideoDecodeVP9CapabilitiesKHR *vp9_caps,
-#endif
-                                     VkVideoDecodeAV1CapabilitiesKHR *av1_caps,
-                                     VkVideoCapabilitiesKHR *caps,
-                                     VkVideoDecodeCapabilitiesKHR *dec_caps,
-                                     int cur_profile)
-{
-    VkVideoDecodeUsageInfoKHR *usage = &prof->usage;
-    VkVideoProfileInfoKHR *profile = &prof->profile;
-    VkVideoProfileListInfoKHR *profile_list = &prof->profile_list;
-
-    VkVideoDecodeH264ProfileInfoKHR *h264_profile = &prof->h264_profile;
-    VkVideoDecodeH265ProfileInfoKHR *h265_profile = &prof->h265_profile;
-#if CONFIG_VP9_VULKAN_HWACCEL
-    VkVideoDecodeVP9ProfileInfoKHR *vp9_profile  = &prof->vp9_profile;
-#endif
-    VkVideoDecodeAV1ProfileInfoKHR *av1_profile  = &prof->av1_profile;
-
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt);
-    if (!desc)
-        return AVERROR(EINVAL);
-
-    if (avctx->codec_id == AV_CODEC_ID_H264) {
-        dec_caps->pNext = h264_caps;
-        usage->pNext = h264_profile;
-        h264_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR;
-
-        /* Vulkan transmits all the constrant_set flags, rather than wanting them
-         * merged in the profile IDC */
-        h264_profile->stdProfileIdc = cur_profile & ~(AV_PROFILE_H264_CONSTRAINED |
-                                                      AV_PROFILE_H264_INTRA);
-
-        h264_profile->pictureLayout = avctx->field_order == AV_FIELD_UNKNOWN ||
-                                      avctx->field_order == AV_FIELD_PROGRESSIVE ?
-                                      VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR :
-                                      VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR;
-    } else if (avctx->codec_id == AV_CODEC_ID_H265) {
-        dec_caps->pNext = h265_caps;
-        usage->pNext = h265_profile;
-        h265_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR;
-        h265_profile->stdProfileIdc = cur_profile;
-#if CONFIG_VP9_VULKAN_HWACCEL
-    } else if (avctx->codec_id == AV_CODEC_ID_VP9) {
-        dec_caps->pNext = vp9_caps;
-        usage->pNext = vp9_profile;
-        vp9_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_VP9_PROFILE_INFO_KHR;
-        vp9_profile->stdProfile = cur_profile;
-#endif
-    } else if (avctx->codec_id == AV_CODEC_ID_AV1) {
-        dec_caps->pNext = av1_caps;
-        usage->pNext = av1_profile;
-        av1_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR;
-        av1_profile->stdProfile = cur_profile;
-        av1_profile->filmGrainSupport = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN);
-    }
-
-    usage->sType           = VK_STRUCTURE_TYPE_VIDEO_DECODE_USAGE_INFO_KHR;
-    usage->videoUsageHints = VK_VIDEO_DECODE_USAGE_DEFAULT_KHR;
-
-    profile->sType               = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR;
-    profile->pNext               = usage;
-    profile->videoCodecOperation = vk_desc->decode_op;
-    profile->chromaSubsampling   = ff_vk_subsampling_from_av_desc(desc);
-    profile->lumaBitDepth        = ff_vk_depth_from_av_depth(desc->comp[0].depth);
-    profile->chromaBitDepth      = profile->lumaBitDepth;
-
-    profile_list->sType        = VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR;
-    profile_list->profileCount = 1;
-    profile_list->pProfiles    = profile;
-
-    /* Get the capabilities of the decoder for the given profile */
-    caps->sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR;
-    caps->pNext = dec_caps;
-    dec_caps->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR;
-    /* dec_caps->pNext already filled in */
-
-    return vk->GetPhysicalDeviceVideoCapabilitiesKHR(hwctx->phys_dev, profile,
-                                                     caps);
-}
-
-static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ref,
-                                     enum AVPixelFormat *pix_fmt, VkFormat *vk_fmt,
-                                     FFVulkanDecodeProfileData *prof,
-                                     int *dpb_dedicate)
-{
-    VkResult ret;
-    int max_level, base_profile, cur_profile;
-    const FFVulkanDecodeDescriptor *vk_desc = get_codecdesc(avctx->codec_id);
-    AVHWFramesContext *frames = (AVHWFramesContext *)frames_ref->data;
-    AVHWDeviceContext *device = (AVHWDeviceContext *)frames->device_ref->data;
-    AVVulkanDeviceContext *hwctx = device->hwctx;
-    enum AVPixelFormat source_format;
-    enum AVPixelFormat best_format;
-    VkFormat best_vkfmt;
-
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-
-    VkVideoCapabilitiesKHR *caps = &ctx->caps;
-    VkVideoDecodeCapabilitiesKHR *dec_caps = &ctx->dec_caps;
-
-    VkVideoDecodeH264CapabilitiesKHR h264_caps = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR,
-    };
-    VkVideoDecodeH265CapabilitiesKHR h265_caps = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_KHR,
-    };
-#if CONFIG_VP9_VULKAN_HWACCEL
-    VkVideoDecodeVP9CapabilitiesKHR vp9_caps = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_VP9_CAPABILITIES_KHR,
-    };
-#endif
-    VkVideoDecodeAV1CapabilitiesKHR av1_caps = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_CAPABILITIES_KHR,
-    };
-
-    VkPhysicalDeviceVideoFormatInfoKHR fmt_info = {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR,
-        .pNext = &prof->profile_list,
-    };
-    VkVideoFormatPropertiesKHR *ret_info;
-    uint32_t nb_out_fmts = 0;
-
-    if (!(vk_desc->decode_extension & ctx->s.extensions)) {
-        av_log(avctx, AV_LOG_ERROR, "Device does not support decoding %s!\n",
-               avcodec_get_name(avctx->codec_id));
-        return AVERROR(ENOSYS);
-    }
-
-    cur_profile = avctx->profile;
-    base_profile = avctx->codec_id == AV_CODEC_ID_H264 ? AV_PROFILE_H264_CONSTRAINED_BASELINE :
-                   avctx->codec_id == AV_CODEC_ID_H265 ? AV_PROFILE_HEVC_MAIN :
-#if CONFIG_VP9_VULKAN_HWACCEL
-                   avctx->codec_id == AV_CODEC_ID_VP9  ? STD_VIDEO_VP9_PROFILE_0 :
-#endif
-                   avctx->codec_id == AV_CODEC_ID_AV1  ? STD_VIDEO_AV1_PROFILE_MAIN :
-                   0;
-
-    ret = vulkan_setup_profile(avctx, prof, hwctx, vk, vk_desc,
-                               &h264_caps,
-                               &h265_caps,
-#if CONFIG_VP9_VULKAN_HWACCEL
-                               &vp9_caps,
-#endif
-                               &av1_caps,
-                               caps,
-                               dec_caps,
-                               cur_profile);
-    if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR &&
-        avctx->flags & AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH &&
-        avctx->profile != base_profile) {
-        av_log(avctx, AV_LOG_VERBOSE, "%s profile %s not supported, attempting "
-               "again with profile %s\n",
-               avcodec_get_name(avctx->codec_id),
-               avcodec_profile_name(avctx->codec_id, cur_profile),
-               avcodec_profile_name(avctx->codec_id, base_profile));
-        cur_profile = base_profile;
-        ret = vulkan_setup_profile(avctx, prof, hwctx, vk, vk_desc,
-                                   &h264_caps,
-                                   &h265_caps,
-#if CONFIG_VP9_VULKAN_HWACCEL
-                                   &vp9_caps,
-#endif
-                                   &av1_caps,
-                                   caps,
-                                   dec_caps,
-                                   cur_profile);
-    }
-
-    if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR) {
-        av_log(avctx, AV_LOG_VERBOSE, "Unable to initialize video session: "
-               "%s profile \"%s\" not supported!\n",
-               avcodec_get_name(avctx->codec_id),
-               avcodec_profile_name(avctx->codec_id, cur_profile));
-        return AVERROR(EINVAL);
-    } else if (ret == VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR) {
-        av_log(avctx, AV_LOG_VERBOSE, "Unable to initialize video session: "
-               "format (%s) not supported!\n",
-               av_get_pix_fmt_name(avctx->sw_pix_fmt));
-        return AVERROR(EINVAL);
-    } else if (ret == VK_ERROR_FEATURE_NOT_PRESENT ||
-               ret == VK_ERROR_FORMAT_NOT_SUPPORTED) {
-        return AVERROR(EINVAL);
-    } else if (ret != VK_SUCCESS) {
-        return AVERROR_EXTERNAL;
-    }
-
-    max_level = avctx->codec_id == AV_CODEC_ID_H264 ? ff_vk_h264_level_to_av(h264_caps.maxLevelIdc) :
-                avctx->codec_id == AV_CODEC_ID_H265 ? ff_vk_h265_level_to_av(h265_caps.maxLevelIdc) :
-#if CONFIG_VP9_VULKAN_HWACCEL
-                avctx->codec_id == AV_CODEC_ID_VP9  ? vp9_caps.maxLevel :
-#endif
-                avctx->codec_id == AV_CODEC_ID_AV1  ? av1_caps.maxLevel :
-                0;
-
-    av_log(avctx, AV_LOG_VERBOSE, "Decoder capabilities for %s profile \"%s\":\n",
-           avcodec_get_name(avctx->codec_id),
-           avcodec_profile_name(avctx->codec_id, cur_profile));
-    av_log(avctx, AV_LOG_VERBOSE, "    Maximum level: %i (stream %i)\n",
-           max_level, avctx->level);
-    av_log(avctx, AV_LOG_VERBOSE, "    Width: from %i to %i\n",
-           caps->minCodedExtent.width, caps->maxCodedExtent.width);
-    av_log(avctx, AV_LOG_VERBOSE, "    Height: from %i to %i\n",
-           caps->minCodedExtent.height, caps->maxCodedExtent.height);
-    av_log(avctx, AV_LOG_VERBOSE, "    Width alignment: %i\n",
-           caps->pictureAccessGranularity.width);
-    av_log(avctx, AV_LOG_VERBOSE, "    Height alignment: %i\n",
-           caps->pictureAccessGranularity.height);
-    av_log(avctx, AV_LOG_VERBOSE, "    Bitstream offset alignment: %"PRIu64"\n",
-           caps->minBitstreamBufferOffsetAlignment);
-    av_log(avctx, AV_LOG_VERBOSE, "    Bitstream size alignment: %"PRIu64"\n",
-           caps->minBitstreamBufferSizeAlignment);
-    av_log(avctx, AV_LOG_VERBOSE, "    Maximum references: %u\n",
-           caps->maxDpbSlots);
-    av_log(avctx, AV_LOG_VERBOSE, "    Maximum active references: %u\n",
-           caps->maxActiveReferencePictures);
-    av_log(avctx, AV_LOG_VERBOSE, "    Codec header name: '%s' (driver), '%s' (compiled)\n",
-           caps->stdHeaderVersion.extensionName,
-           vk_desc->ext_props.extensionName);
-    av_log(avctx, AV_LOG_VERBOSE, "    Codec header version: %i.%i.%i (driver), %i.%i.%i (compiled)\n",
-           CODEC_VER(caps->stdHeaderVersion.specVersion),
-           CODEC_VER(vk_desc->ext_props.specVersion));
-    av_log(avctx, AV_LOG_VERBOSE, "    Decode modes:%s%s%s\n",
-           dec_caps->flags ? "" :
-               " invalid",
-           dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR ?
-               " reuse_dst_dpb" : "",
-           dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR ?
-               " dedicated_dpb" : "");
-    av_log(avctx, AV_LOG_VERBOSE, "    Capability flags:%s%s%s\n",
-           caps->flags ? "" :
-               " none",
-           caps->flags & VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR ?
-               " protected" : "",
-           caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR ?
-               " separate_references" : "");
-
-    /* Check if decoding is possible with the given parameters */
-    if (avctx->coded_width  < caps->minCodedExtent.width   ||
-        avctx->coded_height < caps->minCodedExtent.height  ||
-        avctx->coded_width  > caps->maxCodedExtent.width   ||
-        avctx->coded_height > caps->maxCodedExtent.height)
-        return AVERROR(EINVAL);
-
-    if (!(avctx->hwaccel_flags & AV_HWACCEL_FLAG_IGNORE_LEVEL) &&
-        avctx->level > max_level)
-        return AVERROR(EINVAL);
-
-    /* Some basic sanity checking */
-    if (!(dec_caps->flags & (VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR |
-                             VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR))) {
-        av_log(avctx, AV_LOG_ERROR, "Buggy driver signals invalid decoding mode: neither "
-               "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR nor "
-               "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR are set!\n");
-        return AVERROR_EXTERNAL;
-    } else if ((dec_caps->flags & (VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR |
-                                   VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR) ==
-                                   VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR) &&
-               !(caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR)) {
-        av_log(avctx, AV_LOG_ERROR, "Cannot initialize Vulkan decoding session, buggy driver: "
-               "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR set "
-               "but VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR is unset!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    dec->dedicated_dpb = !(dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR);
-    ctx->common.layered_dpb = !dec->dedicated_dpb ? 0 :
-                              !(caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR);
-
-    if (dec->dedicated_dpb) {
-        fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR;
-    } else {
-        fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR |
-                              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 */
-    ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(hwctx->phys_dev,
-                                                        &fmt_info,
-                                                        &nb_out_fmts, NULL);
-    if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
-        (!nb_out_fmts && ret == VK_SUCCESS)) {
-        return AVERROR(EINVAL);
-    } else if (ret != VK_SUCCESS) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-
-    ret_info = av_mallocz(sizeof(*ret_info)*nb_out_fmts);
-    if (!ret_info)
-        return AVERROR(ENOMEM);
-
-    for (int i = 0; i < nb_out_fmts; i++)
-        ret_info[i].sType = VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR;
-
-    ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(hwctx->phys_dev,
-                                                        &fmt_info,
-                                                        &nb_out_fmts, ret_info);
-    if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
-        (!nb_out_fmts && ret == VK_SUCCESS)) {
-        av_free(ret_info);
-        return AVERROR(EINVAL);
-    } else if (ret != VK_SUCCESS) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
-               ff_vk_ret2str(ret));
-        av_free(ret_info);
-        return AVERROR_EXTERNAL;
-    }
-
-    /* Find a format to use */
-    *pix_fmt = best_format = AV_PIX_FMT_NONE;
-    *vk_fmt  = best_vkfmt = VK_FORMAT_UNDEFINED;
-    source_format = avctx->sw_pix_fmt;
-
-    av_log(avctx, AV_LOG_DEBUG, "Choosing best pixel format for decoding from %i:\n", nb_out_fmts);
-    for (int i = 0; i < nb_out_fmts; i++) {
-        enum AVPixelFormat tmp = ff_vk_pix_fmt_from_vkfmt(ret_info[i].format);
-        if (tmp == AV_PIX_FMT_NONE) {
-            av_log(avctx, AV_LOG_WARNING, "Invalid/unknown Vulkan format %i!\n", ret_info[i].format);
-            continue;
-        }
-
-        best_format = av_find_best_pix_fmt_of_2(tmp, best_format, source_format, 0, NULL);
-        if (tmp == best_format)
-            best_vkfmt = ret_info[i].format;
-
-        av_log(avctx, AV_LOG_DEBUG, "    %s%s (Vulkan ID: %i)\n",
-               av_get_pix_fmt_name(tmp), tmp == best_format ? "*" : "",
-               ret_info[i].format);
-    }
-
-    av_free(ret_info);
-
-    if (best_format == AV_PIX_FMT_NONE) {
-        av_log(avctx, AV_LOG_ERROR, "No valid/compatible pixel format found for decoding!\n");
-        return AVERROR(EINVAL);
-    } else {
-        av_log(avctx, AV_LOG_VERBOSE, "Chosen frame pixfmt: %s (Vulkan ID: %i)\n",
-               av_get_pix_fmt_name(best_format), best_vkfmt);
-    }
-
-    *pix_fmt = best_format;
-    *vk_fmt = best_vkfmt;
-
-    *dpb_dedicate = dec->dedicated_dpb;
-
-    return 0;
-}
-
-static void free_profile_data(AVHWFramesContext *hwfc)
-{
-    av_free(hwfc->user_opaque);
-}
-
-int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
-{
-    VkFormat vkfmt = VK_FORMAT_UNDEFINED;
-    int err, dedicated_dpb;
-    AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data;
-    AVVulkanFramesContext *hwfc = frames_ctx->hwctx;
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeProfileData *prof = NULL;
-
-    err = vulkan_decode_bootstrap(avctx, hw_frames_ctx);
-    if (err < 0)
-        return err;
-
-    frames_ctx->sw_format = avctx->sw_pix_fmt;
-
-    if (!DECODER_IS_SDR(avctx->codec_id)) {
-        prof = av_mallocz(sizeof(FFVulkanDecodeProfileData));
-        if (!prof)
-            return AVERROR(ENOMEM);
-
-        err = vulkan_decode_get_profile(avctx, hw_frames_ctx,
-                                        &frames_ctx->sw_format, &vkfmt,
-                                        prof, &dedicated_dpb);
-        if (err < 0) {
-            av_free(prof);
-            return err;
-        }
-
-        frames_ctx->user_opaque = prof;
-        frames_ctx->free        = free_profile_data;
-
-        hwfc->create_pnext = &prof->profile_list;
-    } else {
-        switch (frames_ctx->sw_format) {
-        case AV_PIX_FMT_GBRAP16:
-            /* This should be more efficient for downloading and using */
-            frames_ctx->sw_format = AV_PIX_FMT_RGBA64;
-            break;
-        case AV_PIX_FMT_GBRP10:
-            /* This saves memory bandwidth when downloading */
-            frames_ctx->sw_format = AV_PIX_FMT_X2BGR10;
-            break;
-        case AV_PIX_FMT_BGR0:
-            /* mpv has issues with bgr0 mapping, so just remap it */
-            frames_ctx->sw_format = AV_PIX_FMT_RGB0;
-            break;
-        default:
-            break;
-        }
-    }
-
-    frames_ctx->width  = avctx->coded_width;
-    frames_ctx->height = avctx->coded_height;
-    frames_ctx->format = AV_PIX_FMT_VULKAN;
-
-    hwfc->format[0]    = vkfmt;
-    hwfc->tiling       = VK_IMAGE_TILING_OPTIMAL;
-    hwfc->usage        = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
-                         VK_IMAGE_USAGE_STORAGE_BIT      |
-                         VK_IMAGE_USAGE_SAMPLED_BIT;
-
-    if (prof) {
-        FFVulkanDecodeShared *ctx;
-
-        hwfc->usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR;
-        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;
-}
-
-static void vk_decode_free_params(void *opaque, uint8_t *data)
-{
-    FFVulkanDecodeShared *ctx = opaque;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-    VkVideoSessionParametersKHR *par = (VkVideoSessionParametersKHR *)data;
-    vk->DestroyVideoSessionParametersKHR(ctx->s.hwctx->act_dev, *par,
-                                         ctx->s.hwctx->alloc);
-    av_free(par);
-}
-
-int ff_vk_decode_create_params(AVBufferRef **par_ref, void *logctx, FFVulkanDecodeShared *ctx,
-                               const VkVideoSessionParametersCreateInfoKHR *session_params_create)
-{
-    VkVideoSessionParametersKHR *par = av_malloc(sizeof(*par));
-    const FFVulkanFunctions *vk = &ctx->s.vkfn;
-    VkResult ret;
-
-    if (!par)
-        return AVERROR(ENOMEM);
-
-    /* Create session parameters */
-    ret = vk->CreateVideoSessionParametersKHR(ctx->s.hwctx->act_dev, session_params_create,
-                                              ctx->s.hwctx->alloc, par);
-    if (ret != VK_SUCCESS) {
-        av_log(logctx, AV_LOG_ERROR, "Unable to create Vulkan video session parameters: %s!\n",
-               ff_vk_ret2str(ret));
-        av_free(par);
-        return AVERROR_EXTERNAL;
-    }
-    *par_ref = av_buffer_create((uint8_t *)par, sizeof(*par),
-                                vk_decode_free_params, ctx, 0);
-    if (!*par_ref) {
-        vk_decode_free_params(ctx, (uint8_t *)par);
-        return AVERROR(ENOMEM);
-    }
-
-    return 0;
-}
-
-int ff_vk_decode_uninit(AVCodecContext *avctx)
-{
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-
-    av_freep(&dec->hevc_headers);
-    av_buffer_unref(&dec->session_params);
-    av_refstruct_unref(&dec->shared_ctx);
-    av_freep(&dec->slice_off);
-    return 0;
-}
-
-static int create_empty_session_parameters(AVCodecContext *avctx,
-                                           FFVulkanDecodeShared *ctx)
-{
-    VkResult ret;
-    FFVulkanContext *s = &ctx->s;
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    VkVideoDecodeH264SessionParametersCreateInfoKHR h264_params = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR,
-    };
-    VkVideoDecodeH265SessionParametersCreateInfoKHR h265_params = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR,
-    };
-    StdVideoAV1SequenceHeader av1_empty_seq = { 0 };
-    VkVideoDecodeAV1SessionParametersCreateInfoKHR av1_params = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR,
-        .pStdSequenceHeader = &av1_empty_seq,
-    };
-    VkVideoSessionParametersCreateInfoKHR session_params_create = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
-        .pNext = avctx->codec_id == AV_CODEC_ID_H264 ? (void *)&h264_params :
-                 avctx->codec_id == AV_CODEC_ID_HEVC ? (void *)&h265_params :
-                 avctx->codec_id == AV_CODEC_ID_AV1  ? (void *)&av1_params  :
-                 NULL,
-        .videoSession = ctx->common.session,
-    };
-
-    if (avctx->codec_id == AV_CODEC_ID_VP9)
-        return 0;
-
-    ret = vk->CreateVideoSessionParametersKHR(s->hwctx->act_dev, &session_params_create,
-                                              s->hwctx->alloc, &ctx->empty_session_params);
-    if (ret != VK_SUCCESS) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to create empty Vulkan video session parameters: %s!\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-
-    return 0;
-}
-
-int ff_vk_decode_init(AVCodecContext *avctx)
-{
-    int err;
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx;
-    FFVulkanContext *s;
-    int async_depth;
-    const VkVideoProfileInfoKHR *profile;
-    const FFVulkanDecodeDescriptor *vk_desc;
-    const VkPhysicalDeviceDriverProperties *driver_props;
-
-    VkVideoSessionCreateInfoKHR session_create = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR,
-    };
-
-    err = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_VULKAN);
-    if (err < 0)
-        return err;
-
-    /* Initialize contexts */
-    ctx = dec->shared_ctx;
-    s = &ctx->s;
-
-    err = ff_vk_init(s, avctx, NULL, avctx->hw_frames_ctx);
-    if (err < 0)
-        return err;
-
-    vk_desc = get_codecdesc(avctx->codec_id);
-
-    profile = get_video_profile(ctx, avctx->codec_id);
-    if ((vk_desc->queue_flags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) && !profile) {
-        av_log(avctx, AV_LOG_ERROR, "Video profile missing from frames context!");
-        return AVERROR(EINVAL);
-    }
-
-    /* Create queue context */
-    vk_desc = get_codecdesc(avctx->codec_id);
-    ctx->qf = ff_vk_qf_find(s, vk_desc->queue_flags, vk_desc->decode_op);
-    if (!ctx->qf) {
-        av_log(avctx, AV_LOG_ERROR, "Decoding of %s is not supported by this device\n",
-               avcodec_get_name(avctx->codec_id));
-        return err;
-    }
-
-    session_create.queueFamilyIndex = ctx->qf->idx;
-    session_create.maxCodedExtent = ctx->caps.maxCodedExtent;
-    session_create.maxDpbSlots = ctx->caps.maxDpbSlots;
-    session_create.maxActiveReferencePictures = ctx->caps.maxActiveReferencePictures;
-    session_create.pictureFormat = s->hwfc->format[0];
-    session_create.referencePictureFormat = session_create.pictureFormat;
-    session_create.pStdHeaderVersion = &vk_desc->ext_props;
-    session_create.pVideoProfile = profile;
-#ifdef VK_KHR_video_maintenance2
-    if (ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)
-        session_create.flags = VK_VIDEO_SESSION_CREATE_INLINE_SESSION_PARAMETERS_BIT_KHR;
-#endif
-
-    /* Create decode exec context for this specific main thread.
-     * 2 async contexts per thread was experimentally determined to be optimal
-     * for a majority of streams. */
-    async_depth = 2*ctx->qf->num;
-    /* We don't need more than 2 per thread context */
-    async_depth = FFMIN(async_depth, 2*avctx->thread_count);
-    /* Make sure there are enough async contexts for each thread */
-    async_depth = FFMAX(async_depth, avctx->thread_count);
-
-    err = ff_vk_exec_pool_init(s, ctx->qf, &ctx->exec_pool,
-                               async_depth, 0, 0, 0, profile);
-    if (err < 0)
-        goto fail;
-
-    if (!DECODER_IS_SDR(avctx->codec_id)) {
-        err = ff_vk_video_common_init(avctx, s, &ctx->common, &session_create);
-        if (err < 0)
-            goto fail;
-    }
-
-    /* If doing an out-of-place decoding, create a DPB pool */
-    if (dec->dedicated_dpb || avctx->codec_id == AV_CODEC_ID_AV1) {
-        AVHWFramesContext *dpb_frames;
-        AVVulkanFramesContext *dpb_hwfc;
-
-        ctx->common.dpb_hwfc_ref = av_hwframe_ctx_alloc(s->frames->device_ref);
-        if (!ctx->common.dpb_hwfc_ref) {
-            err = AVERROR(ENOMEM);
-            goto fail;
-        }
-
-        dpb_frames = (AVHWFramesContext *)ctx->common.dpb_hwfc_ref->data;
-        dpb_frames->format    = s->frames->format;
-        dpb_frames->sw_format = s->frames->sw_format;
-        dpb_frames->width     = avctx->coded_width;
-        dpb_frames->height    = avctx->coded_height;
-
-        dpb_hwfc = dpb_frames->hwctx;
-        dpb_hwfc->create_pnext = (void *)ff_vk_find_struct(ctx->s.hwfc->create_pnext,
-                                                           VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
-        dpb_hwfc->format[0]    = s->hwfc->format[0];
-        dpb_hwfc->tiling       = VK_IMAGE_TILING_OPTIMAL;
-        dpb_hwfc->usage        = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR |
-                                 VK_IMAGE_USAGE_SAMPLED_BIT; /* Shuts validator up. */
-
-        if (ctx->common.layered_dpb)
-            dpb_hwfc->nb_layers = ctx->caps.maxDpbSlots;
-
-        err = av_hwframe_ctx_init(ctx->common.dpb_hwfc_ref);
-        if (err < 0)
-            goto fail;
-
-        if (ctx->common.layered_dpb) {
-            ctx->common.layered_frame = vk_get_dpb_pool(ctx);
-            if (!ctx->common.layered_frame) {
-                err = AVERROR(ENOMEM);
-                goto fail;
-            }
-
-            err = ff_vk_create_view(&ctx->s, &ctx->common,
-                                    &ctx->common.layered_view,
-                                    &ctx->common.layered_aspect,
-                                    (AVVkFrame *)ctx->common.layered_frame->data[0],
-                                    s->hwfc->format[0], 1);
-            if (err < 0)
-                goto fail;
-        }
-    }
-
-    if (!DECODER_IS_SDR(avctx->codec_id)) {
-        if (!(ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)) {
-            err = create_empty_session_parameters(avctx, ctx);
-            if (err < 0)
-                return err;
-        }
-    } else {
-        /* For SDR decoders, this alignment value will be 0. Since this will make
-         * add_slice() malfunction, set it to a sane default value. */
-        ctx->caps.minBitstreamBufferSizeAlignment = AV_INPUT_BUFFER_PADDING_SIZE;
-    }
-
-    driver_props = &dec->shared_ctx->s.driver_props;
-    if (driver_props->driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
-        driver_props->conformanceVersion.major == 1 &&
-        driver_props->conformanceVersion.minor == 3 &&
-        driver_props->conformanceVersion.subminor == 8 &&
-        driver_props->conformanceVersion.patch < 3)
-        dec->quirk_av1_offset = 1;
-
-    ff_vk_decode_flush(avctx);
-
-    av_log(avctx, AV_LOG_VERBOSE, "Vulkan decoder initialization successful\n");
-
-    return 0;
-
-fail:
-    ff_vk_decode_uninit(avctx);
-
-    return err;
-}
-- 
2.49.1


From d09000c8bea2533dd3527bc965f823b109e2ec59 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:29:31 +0000
Subject: [PATCH 066/118] Changing vulkan file directory

---
 libavcodec/vulkan/vulkan_decode.c | 1399 +++++++++++++++++++++++++++++
 1 file changed, 1399 insertions(+)
 create mode 100644 libavcodec/vulkan/vulkan_decode.c

diff --git a/libavcodec/vulkan/vulkan_decode.c b/libavcodec/vulkan/vulkan_decode.c
new file mode 100644
index 0000000000..fc934ca72d
--- /dev/null
+++ b/libavcodec/vulkan/vulkan_decode.c
@@ -0,0 +1,1399 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/refstruct.h"
+#include "vulkan_video.h"
+#include "vulkan_decode.h"
+#include "libavcodec/config_components.h"
+#include "libavutil/avassert.h"
+#include "libavutil/mem.h"
+#include "../../libavutil/vulkan/vulkan_loader.h"
+
+#define DECODER_IS_SDR(codec_id) \
+    (((codec_id) == AV_CODEC_ID_FFV1) || \
+     ((codec_id) == AV_CODEC_ID_PRORES_RAW))
+
+#if CONFIG_H264_VULKAN_HWACCEL
+extern const FFVulkanDecodeDescriptor ff_vk_dec_h264_desc;
+#endif
+#if CONFIG_HEVC_VULKAN_HWACCEL
+extern const FFVulkanDecodeDescriptor ff_vk_dec_hevc_desc;
+#endif
+#if CONFIG_VP9_VULKAN_HWACCEL
+extern const FFVulkanDecodeDescriptor ff_vk_dec_vp9_desc;
+#endif
+#if CONFIG_AV1_VULKAN_HWACCEL
+extern const FFVulkanDecodeDescriptor ff_vk_dec_av1_desc;
+#endif
+#if CONFIG_FFV1_VULKAN_HWACCEL
+extern const FFVulkanDecodeDescriptor ff_vk_dec_ffv1_desc;
+#endif
+#if CONFIG_PRORES_RAW_VULKAN_HWACCEL
+extern const FFVulkanDecodeDescriptor ff_vk_dec_prores_raw_desc;
+#endif
+
+static const FFVulkanDecodeDescriptor *dec_descs[] = {
+#if CONFIG_H264_VULKAN_HWACCEL
+    &ff_vk_dec_h264_desc,
+#endif
+#if CONFIG_HEVC_VULKAN_HWACCEL
+    &ff_vk_dec_hevc_desc,
+#endif
+#if CONFIG_VP9_VULKAN_HWACCEL
+    &ff_vk_dec_vp9_desc,
+#endif
+#if CONFIG_AV1_VULKAN_HWACCEL
+    &ff_vk_dec_av1_desc,
+#endif
+#if CONFIG_FFV1_VULKAN_HWACCEL
+    &ff_vk_dec_ffv1_desc,
+#endif
+#if CONFIG_PRORES_RAW_VULKAN_HWACCEL
+    &ff_vk_dec_prores_raw_desc,
+#endif
+};
+
+typedef struct FFVulkanDecodeProfileData {
+     VkVideoDecodeH264ProfileInfoKHR h264_profile;
+     VkVideoDecodeH265ProfileInfoKHR h265_profile;
+#if CONFIG_VP9_VULKAN_HWACCEL
+     VkVideoDecodeVP9ProfileInfoKHR vp9_profile;
+#endif
+     VkVideoDecodeAV1ProfileInfoKHR av1_profile;
+
+    VkVideoDecodeUsageInfoKHR usage;
+    VkVideoProfileInfoKHR profile;
+    VkVideoProfileListInfoKHR profile_list;
+} FFVulkanDecodeProfileData;
+
+static const FFVulkanDecodeDescriptor *get_codecdesc(enum AVCodecID codec_id)
+{
+    for (size_t i = 0; i < FF_ARRAY_ELEMS(dec_descs); i++)
+        if (dec_descs[i]->codec_id == codec_id)
+            return dec_descs[i];
+    av_assert1(!"no codec descriptor");
+    return NULL;
+}
+
+static const VkVideoProfileInfoKHR *get_video_profile(FFVulkanDecodeShared *ctx, enum AVCodecID codec_id)
+{
+    const VkVideoProfileListInfoKHR *profile_list;
+
+    VkStructureType profile_struct_type =
+        codec_id == AV_CODEC_ID_H264 ? VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR :
+        codec_id == AV_CODEC_ID_HEVC ? VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR :
+#if CONFIG_VP9_VULKAN_HWACCEL
+        codec_id == AV_CODEC_ID_VP9  ? VK_STRUCTURE_TYPE_VIDEO_DECODE_VP9_PROFILE_INFO_KHR :
+#endif
+        codec_id == AV_CODEC_ID_AV1  ? VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR :
+                                       VK_STRUCTURE_TYPE_MAX_ENUM;
+    if (profile_struct_type == VK_STRUCTURE_TYPE_MAX_ENUM)
+        return NULL;
+
+    profile_list = ff_vk_find_struct(ctx->s.hwfc->create_pnext,
+                                     VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
+    if (!profile_list)
+        return NULL;
+
+    for (int i = 0; i < profile_list->profileCount; i++)
+        if (ff_vk_find_struct(profile_list->pProfiles[i].pNext, profile_struct_type))
+            return &profile_list->pProfiles[i];
+
+    return NULL;
+}
+
+int ff_vk_update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
+{
+    int err;
+    FFVulkanDecodeContext *src_ctx = src->internal->hwaccel_priv_data;
+    FFVulkanDecodeContext *dst_ctx = dst->internal->hwaccel_priv_data;
+
+    av_refstruct_replace(&dst_ctx->shared_ctx, src_ctx->shared_ctx);
+
+    err = av_buffer_replace(&dst_ctx->session_params, src_ctx->session_params);
+    if (err < 0)
+        return err;
+
+    dst_ctx->dedicated_dpb = src_ctx->dedicated_dpb;
+    dst_ctx->external_fg = src_ctx->external_fg;
+
+    return 0;
+}
+
+int ff_vk_params_invalidate(AVCodecContext *avctx, int t, const uint8_t *b, uint32_t s)
+{
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    av_buffer_unref(&dec->session_params);
+    return 0;
+}
+
+static AVFrame *vk_get_dpb_pool(FFVulkanDecodeShared *ctx)
+{
+    int err;
+    AVFrame *avf = av_frame_alloc();
+    if (!avf)
+        return NULL;
+
+    err = av_hwframe_get_buffer(ctx->common.dpb_hwfc_ref, avf, 0x0);
+    if (err < 0)
+        av_frame_free(&avf);
+
+    return avf;
+}
+
+static void init_frame(FFVulkanDecodeContext *dec, FFVulkanDecodePicture *vkpic)
+{
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+
+    vkpic->dpb_frame     = NULL;
+    for (int i = 0; i < AV_NUM_DATA_POINTERS; i++) {
+        vkpic->view.ref[i]  = VK_NULL_HANDLE;
+        vkpic->view.out[i]  = VK_NULL_HANDLE;
+        vkpic->view.dst[i]  = VK_NULL_HANDLE;
+    }
+
+    vkpic->destroy_image_view = vk->DestroyImageView;
+    vkpic->wait_semaphores = vk->WaitSemaphores;
+    vkpic->invalidate_memory_ranges = vk->InvalidateMappedMemoryRanges;
+}
+
+int ff_vk_decode_prepare_frame(FFVulkanDecodeContext *dec, AVFrame *pic,
+                               FFVulkanDecodePicture *vkpic, int is_current,
+                               int alloc_dpb)
+{
+    int err;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+
+    vkpic->slices_size = 0;
+
+    /* If the decoder made a blank frame to make up for a missing ref, or the
+     * frame is the current frame so it's missing one, create a re-representation */
+    if (vkpic->view.ref[0])
+        return 0;
+
+    init_frame(dec, vkpic);
+
+    if (ctx->common.layered_dpb && alloc_dpb) {
+        vkpic->view.ref[0] = ctx->common.layered_view;
+        vkpic->view.aspect_ref[0] = ctx->common.layered_aspect;
+    } else if (alloc_dpb) {
+        AVHWFramesContext *dpb_frames = (AVHWFramesContext *)ctx->common.dpb_hwfc_ref->data;
+        AVVulkanFramesContext *dpb_hwfc = dpb_frames->hwctx;
+
+        vkpic->dpb_frame = vk_get_dpb_pool(ctx);
+        if (!vkpic->dpb_frame)
+            return AVERROR(ENOMEM);
+
+        err = ff_vk_create_view(&ctx->s, &ctx->common,
+                                &vkpic->view.ref[0], &vkpic->view.aspect_ref[0],
+                                (AVVkFrame *)vkpic->dpb_frame->data[0],
+                                dpb_hwfc->format[0], !is_current);
+        if (err < 0)
+            return err;
+
+        vkpic->view.dst[0] = vkpic->view.ref[0];
+    }
+
+    if (!alloc_dpb || is_current) {
+        AVHWFramesContext *frames = (AVHWFramesContext *)pic->hw_frames_ctx->data;
+        AVVulkanFramesContext *hwfc = frames->hwctx;
+
+        err = ff_vk_create_view(&ctx->s, &ctx->common,
+                                &vkpic->view.out[0], &vkpic->view.aspect[0],
+                                (AVVkFrame *)pic->data[0],
+                                hwfc->format[0], !is_current);
+        if (err < 0)
+            return err;
+
+        if (!alloc_dpb) {
+            vkpic->view.ref[0] = vkpic->view.out[0];
+            vkpic->view.aspect_ref[0] = vkpic->view.aspect[0];
+        }
+    }
+
+    return 0;
+}
+
+int ff_vk_decode_prepare_frame_sdr(FFVulkanDecodeContext *dec, AVFrame *pic,
+                                   FFVulkanDecodePicture *vkpic, int is_current,
+                                   enum FFVkShaderRepFormat rep_fmt, int alloc_dpb)
+{
+    int err;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+    AVHWFramesContext *frames = (AVHWFramesContext *)pic->hw_frames_ctx->data;
+
+    vkpic->slices_size = 0;
+
+    if (vkpic->view.ref[0])
+        return 0;
+
+    init_frame(dec, vkpic);
+
+    for (int i = 0; i < av_pix_fmt_count_planes(frames->sw_format); i++) {
+        if (alloc_dpb) {
+            vkpic->dpb_frame = vk_get_dpb_pool(ctx);
+            if (!vkpic->dpb_frame)
+                return AVERROR(ENOMEM);
+
+            err = ff_vk_create_imageview(&ctx->s,
+                                         &vkpic->view.ref[i], &vkpic->view.aspect_ref[i],
+                                         vkpic->dpb_frame, i, rep_fmt);
+            if (err < 0)
+                return err;
+
+            vkpic->view.dst[i] = vkpic->view.ref[i];
+        }
+
+        if (!alloc_dpb || is_current) {
+            err = ff_vk_create_imageview(&ctx->s,
+                                         &vkpic->view.out[i], &vkpic->view.aspect[i],
+                                         pic, i, rep_fmt);
+            if (err < 0)
+                return err;
+
+            if (!alloc_dpb) {
+                vkpic->view.ref[i] = vkpic->view.out[i];
+                vkpic->view.aspect_ref[i] = vkpic->view.aspect[i];
+            }
+        }
+    }
+
+    return 0;
+}
+
+int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp,
+                           const uint8_t *data, size_t size, int add_startcode,
+                           uint32_t *nb_slices, const uint32_t **offsets)
+{
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+
+    static const uint8_t startcode_prefix[3] = { 0x0, 0x0, 0x1 };
+    const size_t startcode_len = add_startcode ? sizeof(startcode_prefix) : 0;
+    const int nb = nb_slices ? *nb_slices : 0;
+    uint8_t *slices;
+    uint32_t *slice_off;
+    FFVkBuffer *vkbuf;
+
+    size_t new_size = vp->slices_size + startcode_len + size +
+                      ctx->caps.minBitstreamBufferSizeAlignment;
+    new_size = FFALIGN(new_size, ctx->caps.minBitstreamBufferSizeAlignment);
+
+    if (offsets) {
+        slice_off = av_fast_realloc(dec->slice_off, &dec->slice_off_max,
+                                    (nb + 1)*sizeof(slice_off));
+        if (!slice_off)
+            return AVERROR(ENOMEM);
+
+        *offsets = dec->slice_off = slice_off;
+
+        slice_off[nb] = vp->slices_size;
+    }
+
+    vkbuf = vp->slices_buf ? (FFVkBuffer *)vp->slices_buf->data : NULL;
+    if (!vkbuf || vkbuf->size < new_size) {
+        int err;
+        AVBufferRef *new_ref;
+        FFVkBuffer *new_buf;
+
+        /* No point in requesting anything smaller. */
+        size_t buf_size = FFMAX(new_size, 1024*1024);
+
+        /* Align buffer to nearest power of two. Makes fragmentation management
+         * easier, and gives us ample headroom. */
+        buf_size = 2 << av_log2(buf_size);
+
+        err = ff_vk_get_pooled_buffer(&ctx->s, &ctx->buf_pool, &new_ref,
+                                      DECODER_IS_SDR(avctx->codec_id) ?
+                                      (VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
+                                       VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) :
+                                      VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR,
+                                      ctx->s.hwfc->create_pnext, buf_size,
+                                      VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+                                      (DECODER_IS_SDR(avctx->codec_id) ?
+                                       VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT : 0x0));
+        if (err < 0)
+            return err;
+
+        new_buf = (FFVkBuffer *)new_ref->data;
+
+        /* Copy data from the old buffer */
+        if (vkbuf) {
+            memcpy(new_buf->mapped_mem, vkbuf->mapped_mem, vp->slices_size);
+            av_buffer_unref(&vp->slices_buf);
+        }
+
+        vp->slices_buf = new_ref;
+        vkbuf = new_buf;
+    }
+    slices = vkbuf->mapped_mem;
+
+    /* Startcode */
+    memcpy(slices + vp->slices_size, startcode_prefix, startcode_len);
+
+    /* Slice data */
+    memcpy(slices + vp->slices_size + startcode_len, data, size);
+
+    if (nb_slices)
+        *nb_slices = nb + 1;
+
+    vp->slices_size += startcode_len + size;
+
+    return 0;
+}
+
+void ff_vk_decode_flush(AVCodecContext *avctx)
+{
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+    VkVideoBeginCodingInfoKHR decode_start = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
+        .videoSession = ctx->common.session,
+        .videoSessionParameters = ctx->empty_session_params,
+    };
+    VkVideoCodingControlInfoKHR decode_ctrl = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR,
+        .flags = VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR,
+    };
+    VkVideoEndCodingInfoKHR decode_end = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR,
+    };
+
+    VkCommandBuffer cmd_buf;
+    FFVkExecContext *exec;
+
+    /* Non-video queues do not need to be reset */
+    if (!(get_codecdesc(avctx->codec_id)->decode_op))
+        return;
+
+    exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
+    ff_vk_exec_start(&ctx->s, exec);
+    cmd_buf = exec->buf;
+
+    vk->CmdBeginVideoCodingKHR(cmd_buf, &decode_start);
+    vk->CmdControlVideoCodingKHR(cmd_buf, &decode_ctrl);
+    vk->CmdEndVideoCodingKHR(cmd_buf, &decode_end);
+    ff_vk_exec_submit(&ctx->s, exec);
+}
+
+int ff_vk_decode_frame(AVCodecContext *avctx,
+                       AVFrame *pic,    FFVulkanDecodePicture *vp,
+                       AVFrame *rpic[], FFVulkanDecodePicture *rvkp[])
+{
+    int err;
+    VkResult ret;
+    VkCommandBuffer cmd_buf;
+    FFVkBuffer *sd_buf;
+
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+
+    /* Output */
+    AVVkFrame *vkf = (AVVkFrame *)pic->buf[0]->data;
+
+    /* Quirks */
+    const int layered_dpb = ctx->common.layered_dpb;
+
+    VkVideoBeginCodingInfoKHR decode_start = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
+        .videoSession = ctx->common.session,
+        .videoSessionParameters = dec->session_params ?
+                                  *((VkVideoSessionParametersKHR *)dec->session_params->data) :
+                                  VK_NULL_HANDLE,
+        .referenceSlotCount = vp->decode_info.referenceSlotCount,
+        .pReferenceSlots = vp->decode_info.pReferenceSlots,
+    };
+    VkVideoEndCodingInfoKHR decode_end = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR,
+    };
+
+    VkImageMemoryBarrier2 img_bar[37];
+    int nb_img_bar = 0;
+    size_t data_size = FFALIGN(vp->slices_size,
+                               ctx->caps.minBitstreamBufferSizeAlignment);
+
+    FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
+
+    /* The current decoding reference has to be bound as an inactive reference */
+    VkVideoReferenceSlotInfoKHR *cur_vk_ref;
+    cur_vk_ref = (void *)&decode_start.pReferenceSlots[decode_start.referenceSlotCount];
+    cur_vk_ref[0] = vp->ref_slot;
+    cur_vk_ref[0].slotIndex = -1;
+    decode_start.referenceSlotCount++;
+
+    sd_buf = (FFVkBuffer *)vp->slices_buf->data;
+
+    /* Flush if needed */
+    if (!(sd_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
+        VkMappedMemoryRange flush_buf = {
+            .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+            .memory = sd_buf->mem,
+            .offset = 0,
+            .size = FFALIGN(vp->slices_size,
+                            ctx->s.props.properties.limits.nonCoherentAtomSize),
+        };
+
+        ret = vk->FlushMappedMemoryRanges(ctx->s.hwctx->act_dev, 1, &flush_buf);
+        if (ret != VK_SUCCESS) {
+            av_log(avctx, AV_LOG_ERROR, "Failed to flush memory: %s\n",
+                   ff_vk_ret2str(ret));
+            return AVERROR_EXTERNAL;
+        }
+    }
+
+    vp->decode_info.srcBuffer       = sd_buf->buf;
+    vp->decode_info.srcBufferOffset = 0;
+    vp->decode_info.srcBufferRange  = data_size;
+
+    /* Start command buffer recording */
+    err = ff_vk_exec_start(&ctx->s, exec);
+    if (err < 0)
+        return err;
+    cmd_buf = exec->buf;
+
+    /* Slices */
+    err = ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0);
+    if (err < 0)
+        return err;
+    vp->slices_buf = NULL; /* Owned by the exec buffer from now on */
+
+    /* Parameters */
+    err = ff_vk_exec_add_dep_buf(&ctx->s, exec, &dec->session_params, 1, 1);
+    if (err < 0)
+        return err;
+
+    err = ff_vk_exec_add_dep_frame(&ctx->s, exec, pic,
+                                   VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
+                                   VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
+    if (err < 0)
+        return err;
+
+    err = ff_vk_exec_mirror_sem_value(&ctx->s, exec, &vp->sem, &vp->sem_value,
+                                      pic);
+    if (err < 0)
+        return err;
+
+    /* Output image - change layout, as it comes from a pool */
+    img_bar[nb_img_bar] = (VkImageMemoryBarrier2) {
+        .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
+        .pNext = NULL,
+        .srcStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
+        .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
+        .srcAccessMask = VK_ACCESS_2_NONE,
+        .dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR,
+        .oldLayout = vkf->layout[0],
+        .newLayout = (layered_dpb || vp->dpb_frame) ?
+                     VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR :
+                     VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, /* Spec, 07252 utter madness */
+        .srcQueueFamilyIndex = vkf->queue_family[0],
+        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .image = vkf->img[0],
+        .subresourceRange = (VkImageSubresourceRange) {
+            .aspectMask = vp->view.aspect[0],
+            .layerCount = 1,
+            .levelCount = 1,
+        },
+    };
+    ff_vk_exec_update_frame(&ctx->s, exec, pic,
+                            &img_bar[nb_img_bar], &nb_img_bar);
+
+    /* Reference for the current image, if existing and not layered */
+    if (vp->dpb_frame) {
+        err = ff_vk_exec_add_dep_frame(&ctx->s, exec, vp->dpb_frame,
+                                       VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
+                                       VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
+        if (err < 0)
+            return err;
+    }
+
+    if (!layered_dpb) {
+        /* All references (apart from the current) for non-layered refs */
+
+        for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
+            AVFrame *ref_frame = rpic[i];
+            FFVulkanDecodePicture *rvp = rvkp[i];
+            AVFrame *ref = rvp->dpb_frame ? rvp->dpb_frame : ref_frame;
+
+            err = ff_vk_exec_add_dep_frame(&ctx->s, exec, ref,
+                                           VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
+                                           VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
+            if (err < 0)
+                return err;
+
+            if (err == 0) {
+                err = ff_vk_exec_mirror_sem_value(&ctx->s, exec,
+                                                  &rvp->sem, &rvp->sem_value,
+                                                  ref);
+                if (err < 0)
+                    return err;
+            }
+
+            if (!rvp->dpb_frame) {
+                AVVkFrame *rvkf = (AVVkFrame *)ref->data[0];
+
+                img_bar[nb_img_bar] = (VkImageMemoryBarrier2) {
+                    .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
+                    .pNext = NULL,
+                    .srcStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
+                    .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
+                    .srcAccessMask = VK_ACCESS_2_NONE,
+                    .dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR |
+                                     VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR,
+                    .oldLayout = rvkf->layout[0],
+                    .newLayout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR,
+                    .srcQueueFamilyIndex = rvkf->queue_family[0],
+                    .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                    .image = rvkf->img[0],
+                    .subresourceRange = (VkImageSubresourceRange) {
+                        .aspectMask = rvp->view.aspect_ref[0],
+                        .layerCount = 1,
+                        .levelCount = 1,
+                    },
+                };
+                ff_vk_exec_update_frame(&ctx->s, exec, ref,
+                                        &img_bar[nb_img_bar], &nb_img_bar);
+            }
+        }
+    } else if (vp->decode_info.referenceSlotCount ||
+               vp->view.out[0] != vp->view.ref[0]) {
+        /* Single barrier for a single layered ref */
+        err = ff_vk_exec_add_dep_frame(&ctx->s, exec, ctx->common.layered_frame,
+                                       VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
+                                       VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
+        if (err < 0)
+            return err;
+    }
+
+    /* Change image layout */
+    vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+            .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT,
+            .pImageMemoryBarriers = img_bar,
+            .imageMemoryBarrierCount = nb_img_bar,
+        });
+
+    /* Start, use parameters, decode and end decoding */
+    vk->CmdBeginVideoCodingKHR(cmd_buf, &decode_start);
+    vk->CmdDecodeVideoKHR(cmd_buf, &vp->decode_info);
+    vk->CmdEndVideoCodingKHR(cmd_buf, &decode_end);
+
+    /* End recording and submit for execution */
+    return ff_vk_exec_submit(&ctx->s, exec);
+}
+
+void ff_vk_decode_free_frame(AVHWDeviceContext *dev_ctx, FFVulkanDecodePicture *vp)
+{
+    AVVulkanDeviceContext *hwctx = dev_ctx->hwctx;
+
+    VkSemaphoreWaitInfo sem_wait = (VkSemaphoreWaitInfo) {
+        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
+        .pSemaphores = &vp->sem,
+        .pValues = &vp->sem_value,
+        .semaphoreCount = 1,
+    };
+
+    /* We do not have to lock the frame here because we're not interested
+     * in the actual current semaphore value, but only that it's later than
+     * the time we submitted the image for decoding. */
+    if (vp->sem)
+        vp->wait_semaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
+
+    /* Free slices data */
+    av_buffer_unref(&vp->slices_buf);
+
+    /* Destroy image view (out) */
+    for (int i = 0; i < AV_NUM_DATA_POINTERS; i++) {
+        if (vp->view.out[i] && vp->view.out[i] != vp->view.dst[i])
+            vp->destroy_image_view(hwctx->act_dev, vp->view.out[i], hwctx->alloc);
+
+        /* Destroy image view (ref, unlayered) */
+        if (vp->view.dst[i])
+            vp->destroy_image_view(hwctx->act_dev, vp->view.dst[i], hwctx->alloc);
+    }
+
+    av_frame_free(&vp->dpb_frame);
+}
+
+static void free_common(AVRefStructOpaque unused, void *obj)
+{
+    FFVulkanDecodeShared *ctx = obj;
+    FFVulkanContext *s = &ctx->s;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+
+    /* Wait on and free execution pool */
+    ff_vk_exec_pool_free(&ctx->s, &ctx->exec_pool);
+
+    /* This also frees all references from this pool */
+    av_frame_free(&ctx->common.layered_frame);
+
+    /* Destroy parameters */
+    if (ctx->empty_session_params)
+        vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
+                                             ctx->empty_session_params,
+                                             s->hwctx->alloc);
+
+    av_buffer_pool_uninit(&ctx->buf_pool);
+
+    ff_vk_video_common_uninit(s, &ctx->common);
+
+    if (ctx->sd_ctx_free)
+        ctx->sd_ctx_free(ctx);
+
+    ff_vk_uninit(s);
+}
+
+static int vulkan_decode_bootstrap(AVCodecContext *avctx, AVBufferRef *frames_ref)
+{
+    int err;
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    const FFVulkanDecodeDescriptor *vk_desc = get_codecdesc(avctx->codec_id);
+    AVHWFramesContext *frames = (AVHWFramesContext *)frames_ref->data;
+    AVHWDeviceContext *device = (AVHWDeviceContext *)frames->device_ref->data;
+    AVVulkanDeviceContext *hwctx = device->hwctx;
+    FFVulkanDecodeShared *ctx;
+
+    if (dec->shared_ctx)
+        return 0;
+
+    dec->shared_ctx = av_refstruct_alloc_ext(sizeof(*ctx), 0, NULL,
+                                             free_common);
+    if (!dec->shared_ctx)
+        return AVERROR(ENOMEM);
+
+    ctx = dec->shared_ctx;
+
+    ctx->s.extensions = ff_vk_extensions_to_mask(hwctx->enabled_dev_extensions,
+                                                 hwctx->nb_enabled_dev_extensions);
+
+    if (vk_desc->queue_flags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) {
+        if (!(ctx->s.extensions & FF_VK_EXT_VIDEO_DECODE_QUEUE)) {
+            av_log(avctx, AV_LOG_ERROR, "Device does not support the %s extension!\n",
+                   VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME);
+            av_refstruct_unref(&dec->shared_ctx);
+            return AVERROR(ENOSYS);
+        }
+    }
+
+    err = ff_vk_load_functions(device, &ctx->s.vkfn, ctx->s.extensions, 1, 1);
+    if (err < 0) {
+        av_refstruct_unref(&dec->shared_ctx);
+        return err;
+    }
+
+    return 0;
+}
+
+static VkResult vulkan_setup_profile(AVCodecContext *avctx,
+                                     FFVulkanDecodeProfileData *prof,
+                                     AVVulkanDeviceContext *hwctx,
+                                     FFVulkanFunctions *vk,
+                                     const FFVulkanDecodeDescriptor *vk_desc,
+                                     VkVideoDecodeH264CapabilitiesKHR *h264_caps,
+                                     VkVideoDecodeH265CapabilitiesKHR *h265_caps,
+#if CONFIG_VP9_VULKAN_HWACCEL
+                                     VkVideoDecodeVP9CapabilitiesKHR *vp9_caps,
+#endif
+                                     VkVideoDecodeAV1CapabilitiesKHR *av1_caps,
+                                     VkVideoCapabilitiesKHR *caps,
+                                     VkVideoDecodeCapabilitiesKHR *dec_caps,
+                                     int cur_profile)
+{
+    VkVideoDecodeUsageInfoKHR *usage = &prof->usage;
+    VkVideoProfileInfoKHR *profile = &prof->profile;
+    VkVideoProfileListInfoKHR *profile_list = &prof->profile_list;
+
+    VkVideoDecodeH264ProfileInfoKHR *h264_profile = &prof->h264_profile;
+    VkVideoDecodeH265ProfileInfoKHR *h265_profile = &prof->h265_profile;
+#if CONFIG_VP9_VULKAN_HWACCEL
+    VkVideoDecodeVP9ProfileInfoKHR *vp9_profile  = &prof->vp9_profile;
+#endif
+    VkVideoDecodeAV1ProfileInfoKHR *av1_profile  = &prof->av1_profile;
+
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt);
+    if (!desc)
+        return AVERROR(EINVAL);
+
+    if (avctx->codec_id == AV_CODEC_ID_H264) {
+        dec_caps->pNext = h264_caps;
+        usage->pNext = h264_profile;
+        h264_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR;
+
+        /* Vulkan transmits all the constrant_set flags, rather than wanting them
+         * merged in the profile IDC */
+        h264_profile->stdProfileIdc = cur_profile & ~(AV_PROFILE_H264_CONSTRAINED |
+                                                      AV_PROFILE_H264_INTRA);
+
+        h264_profile->pictureLayout = avctx->field_order == AV_FIELD_UNKNOWN ||
+                                      avctx->field_order == AV_FIELD_PROGRESSIVE ?
+                                      VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR :
+                                      VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR;
+    } else if (avctx->codec_id == AV_CODEC_ID_H265) {
+        dec_caps->pNext = h265_caps;
+        usage->pNext = h265_profile;
+        h265_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR;
+        h265_profile->stdProfileIdc = cur_profile;
+#if CONFIG_VP9_VULKAN_HWACCEL
+    } else if (avctx->codec_id == AV_CODEC_ID_VP9) {
+        dec_caps->pNext = vp9_caps;
+        usage->pNext = vp9_profile;
+        vp9_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_VP9_PROFILE_INFO_KHR;
+        vp9_profile->stdProfile = cur_profile;
+#endif
+    } else if (avctx->codec_id == AV_CODEC_ID_AV1) {
+        dec_caps->pNext = av1_caps;
+        usage->pNext = av1_profile;
+        av1_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR;
+        av1_profile->stdProfile = cur_profile;
+        av1_profile->filmGrainSupport = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN);
+    }
+
+    usage->sType           = VK_STRUCTURE_TYPE_VIDEO_DECODE_USAGE_INFO_KHR;
+    usage->videoUsageHints = VK_VIDEO_DECODE_USAGE_DEFAULT_KHR;
+
+    profile->sType               = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR;
+    profile->pNext               = usage;
+    profile->videoCodecOperation = vk_desc->decode_op;
+    profile->chromaSubsampling   = ff_vk_subsampling_from_av_desc(desc);
+    profile->lumaBitDepth        = ff_vk_depth_from_av_depth(desc->comp[0].depth);
+    profile->chromaBitDepth      = profile->lumaBitDepth;
+
+    profile_list->sType        = VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR;
+    profile_list->profileCount = 1;
+    profile_list->pProfiles    = profile;
+
+    /* Get the capabilities of the decoder for the given profile */
+    caps->sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR;
+    caps->pNext = dec_caps;
+    dec_caps->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR;
+    /* dec_caps->pNext already filled in */
+
+    return vk->GetPhysicalDeviceVideoCapabilitiesKHR(hwctx->phys_dev, profile,
+                                                     caps);
+}
+
+static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ref,
+                                     enum AVPixelFormat *pix_fmt, VkFormat *vk_fmt,
+                                     FFVulkanDecodeProfileData *prof,
+                                     int *dpb_dedicate)
+{
+    VkResult ret;
+    int max_level, base_profile, cur_profile;
+    const FFVulkanDecodeDescriptor *vk_desc = get_codecdesc(avctx->codec_id);
+    AVHWFramesContext *frames = (AVHWFramesContext *)frames_ref->data;
+    AVHWDeviceContext *device = (AVHWDeviceContext *)frames->device_ref->data;
+    AVVulkanDeviceContext *hwctx = device->hwctx;
+    enum AVPixelFormat source_format;
+    enum AVPixelFormat best_format;
+    VkFormat best_vkfmt;
+
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+
+    VkVideoCapabilitiesKHR *caps = &ctx->caps;
+    VkVideoDecodeCapabilitiesKHR *dec_caps = &ctx->dec_caps;
+
+    VkVideoDecodeH264CapabilitiesKHR h264_caps = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR,
+    };
+    VkVideoDecodeH265CapabilitiesKHR h265_caps = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_KHR,
+    };
+#if CONFIG_VP9_VULKAN_HWACCEL
+    VkVideoDecodeVP9CapabilitiesKHR vp9_caps = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_VP9_CAPABILITIES_KHR,
+    };
+#endif
+    VkVideoDecodeAV1CapabilitiesKHR av1_caps = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_CAPABILITIES_KHR,
+    };
+
+    VkPhysicalDeviceVideoFormatInfoKHR fmt_info = {
+        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR,
+        .pNext = &prof->profile_list,
+    };
+    VkVideoFormatPropertiesKHR *ret_info;
+    uint32_t nb_out_fmts = 0;
+
+    if (!(vk_desc->decode_extension & ctx->s.extensions)) {
+        av_log(avctx, AV_LOG_ERROR, "Device does not support decoding %s!\n",
+               avcodec_get_name(avctx->codec_id));
+        return AVERROR(ENOSYS);
+    }
+
+    cur_profile = avctx->profile;
+    base_profile = avctx->codec_id == AV_CODEC_ID_H264 ? AV_PROFILE_H264_CONSTRAINED_BASELINE :
+                   avctx->codec_id == AV_CODEC_ID_H265 ? AV_PROFILE_HEVC_MAIN :
+#if CONFIG_VP9_VULKAN_HWACCEL
+                   avctx->codec_id == AV_CODEC_ID_VP9  ? STD_VIDEO_VP9_PROFILE_0 :
+#endif
+                   avctx->codec_id == AV_CODEC_ID_AV1  ? STD_VIDEO_AV1_PROFILE_MAIN :
+                   0;
+
+    ret = vulkan_setup_profile(avctx, prof, hwctx, vk, vk_desc,
+                               &h264_caps,
+                               &h265_caps,
+#if CONFIG_VP9_VULKAN_HWACCEL
+                               &vp9_caps,
+#endif
+                               &av1_caps,
+                               caps,
+                               dec_caps,
+                               cur_profile);
+    if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR &&
+        avctx->flags & AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH &&
+        avctx->profile != base_profile) {
+        av_log(avctx, AV_LOG_VERBOSE, "%s profile %s not supported, attempting "
+               "again with profile %s\n",
+               avcodec_get_name(avctx->codec_id),
+               avcodec_profile_name(avctx->codec_id, cur_profile),
+               avcodec_profile_name(avctx->codec_id, base_profile));
+        cur_profile = base_profile;
+        ret = vulkan_setup_profile(avctx, prof, hwctx, vk, vk_desc,
+                                   &h264_caps,
+                                   &h265_caps,
+#if CONFIG_VP9_VULKAN_HWACCEL
+                                   &vp9_caps,
+#endif
+                                   &av1_caps,
+                                   caps,
+                                   dec_caps,
+                                   cur_profile);
+    }
+
+    if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR) {
+        av_log(avctx, AV_LOG_VERBOSE, "Unable to initialize video session: "
+               "%s profile \"%s\" not supported!\n",
+               avcodec_get_name(avctx->codec_id),
+               avcodec_profile_name(avctx->codec_id, cur_profile));
+        return AVERROR(EINVAL);
+    } else if (ret == VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR) {
+        av_log(avctx, AV_LOG_VERBOSE, "Unable to initialize video session: "
+               "format (%s) not supported!\n",
+               av_get_pix_fmt_name(avctx->sw_pix_fmt));
+        return AVERROR(EINVAL);
+    } else if (ret == VK_ERROR_FEATURE_NOT_PRESENT ||
+               ret == VK_ERROR_FORMAT_NOT_SUPPORTED) {
+        return AVERROR(EINVAL);
+    } else if (ret != VK_SUCCESS) {
+        return AVERROR_EXTERNAL;
+    }
+
+    max_level = avctx->codec_id == AV_CODEC_ID_H264 ? ff_vk_h264_level_to_av(h264_caps.maxLevelIdc) :
+                avctx->codec_id == AV_CODEC_ID_H265 ? ff_vk_h265_level_to_av(h265_caps.maxLevelIdc) :
+#if CONFIG_VP9_VULKAN_HWACCEL
+                avctx->codec_id == AV_CODEC_ID_VP9  ? vp9_caps.maxLevel :
+#endif
+                avctx->codec_id == AV_CODEC_ID_AV1  ? av1_caps.maxLevel :
+                0;
+
+    av_log(avctx, AV_LOG_VERBOSE, "Decoder capabilities for %s profile \"%s\":\n",
+           avcodec_get_name(avctx->codec_id),
+           avcodec_profile_name(avctx->codec_id, cur_profile));
+    av_log(avctx, AV_LOG_VERBOSE, "    Maximum level: %i (stream %i)\n",
+           max_level, avctx->level);
+    av_log(avctx, AV_LOG_VERBOSE, "    Width: from %i to %i\n",
+           caps->minCodedExtent.width, caps->maxCodedExtent.width);
+    av_log(avctx, AV_LOG_VERBOSE, "    Height: from %i to %i\n",
+           caps->minCodedExtent.height, caps->maxCodedExtent.height);
+    av_log(avctx, AV_LOG_VERBOSE, "    Width alignment: %i\n",
+           caps->pictureAccessGranularity.width);
+    av_log(avctx, AV_LOG_VERBOSE, "    Height alignment: %i\n",
+           caps->pictureAccessGranularity.height);
+    av_log(avctx, AV_LOG_VERBOSE, "    Bitstream offset alignment: %"PRIu64"\n",
+           caps->minBitstreamBufferOffsetAlignment);
+    av_log(avctx, AV_LOG_VERBOSE, "    Bitstream size alignment: %"PRIu64"\n",
+           caps->minBitstreamBufferSizeAlignment);
+    av_log(avctx, AV_LOG_VERBOSE, "    Maximum references: %u\n",
+           caps->maxDpbSlots);
+    av_log(avctx, AV_LOG_VERBOSE, "    Maximum active references: %u\n",
+           caps->maxActiveReferencePictures);
+    av_log(avctx, AV_LOG_VERBOSE, "    Codec header name: '%s' (driver), '%s' (compiled)\n",
+           caps->stdHeaderVersion.extensionName,
+           vk_desc->ext_props.extensionName);
+    av_log(avctx, AV_LOG_VERBOSE, "    Codec header version: %i.%i.%i (driver), %i.%i.%i (compiled)\n",
+           CODEC_VER(caps->stdHeaderVersion.specVersion),
+           CODEC_VER(vk_desc->ext_props.specVersion));
+    av_log(avctx, AV_LOG_VERBOSE, "    Decode modes:%s%s%s\n",
+           dec_caps->flags ? "" :
+               " invalid",
+           dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR ?
+               " reuse_dst_dpb" : "",
+           dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR ?
+               " dedicated_dpb" : "");
+    av_log(avctx, AV_LOG_VERBOSE, "    Capability flags:%s%s%s\n",
+           caps->flags ? "" :
+               " none",
+           caps->flags & VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR ?
+               " protected" : "",
+           caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR ?
+               " separate_references" : "");
+
+    /* Check if decoding is possible with the given parameters */
+    if (avctx->coded_width  < caps->minCodedExtent.width   ||
+        avctx->coded_height < caps->minCodedExtent.height  ||
+        avctx->coded_width  > caps->maxCodedExtent.width   ||
+        avctx->coded_height > caps->maxCodedExtent.height)
+        return AVERROR(EINVAL);
+
+    if (!(avctx->hwaccel_flags & AV_HWACCEL_FLAG_IGNORE_LEVEL) &&
+        avctx->level > max_level)
+        return AVERROR(EINVAL);
+
+    /* Some basic sanity checking */
+    if (!(dec_caps->flags & (VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR |
+                             VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR))) {
+        av_log(avctx, AV_LOG_ERROR, "Buggy driver signals invalid decoding mode: neither "
+               "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR nor "
+               "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR are set!\n");
+        return AVERROR_EXTERNAL;
+    } else if ((dec_caps->flags & (VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR |
+                                   VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR) ==
+                                   VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR) &&
+               !(caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR)) {
+        av_log(avctx, AV_LOG_ERROR, "Cannot initialize Vulkan decoding session, buggy driver: "
+               "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR set "
+               "but VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR is unset!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    dec->dedicated_dpb = !(dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR);
+    ctx->common.layered_dpb = !dec->dedicated_dpb ? 0 :
+                              !(caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR);
+
+    if (dec->dedicated_dpb) {
+        fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR;
+    } else {
+        fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR |
+                              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 */
+    ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(hwctx->phys_dev,
+                                                        &fmt_info,
+                                                        &nb_out_fmts, NULL);
+    if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
+        (!nb_out_fmts && ret == VK_SUCCESS)) {
+        return AVERROR(EINVAL);
+    } else if (ret != VK_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+
+    ret_info = av_mallocz(sizeof(*ret_info)*nb_out_fmts);
+    if (!ret_info)
+        return AVERROR(ENOMEM);
+
+    for (int i = 0; i < nb_out_fmts; i++)
+        ret_info[i].sType = VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR;
+
+    ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(hwctx->phys_dev,
+                                                        &fmt_info,
+                                                        &nb_out_fmts, ret_info);
+    if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
+        (!nb_out_fmts && ret == VK_SUCCESS)) {
+        av_free(ret_info);
+        return AVERROR(EINVAL);
+    } else if (ret != VK_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
+               ff_vk_ret2str(ret));
+        av_free(ret_info);
+        return AVERROR_EXTERNAL;
+    }
+
+    /* Find a format to use */
+    *pix_fmt = best_format = AV_PIX_FMT_NONE;
+    *vk_fmt  = best_vkfmt = VK_FORMAT_UNDEFINED;
+    source_format = avctx->sw_pix_fmt;
+
+    av_log(avctx, AV_LOG_DEBUG, "Choosing best pixel format for decoding from %i:\n", nb_out_fmts);
+    for (int i = 0; i < nb_out_fmts; i++) {
+        enum AVPixelFormat tmp = ff_vk_pix_fmt_from_vkfmt(ret_info[i].format);
+        if (tmp == AV_PIX_FMT_NONE) {
+            av_log(avctx, AV_LOG_WARNING, "Invalid/unknown Vulkan format %i!\n", ret_info[i].format);
+            continue;
+        }
+
+        best_format = av_find_best_pix_fmt_of_2(tmp, best_format, source_format, 0, NULL);
+        if (tmp == best_format)
+            best_vkfmt = ret_info[i].format;
+
+        av_log(avctx, AV_LOG_DEBUG, "    %s%s (Vulkan ID: %i)\n",
+               av_get_pix_fmt_name(tmp), tmp == best_format ? "*" : "",
+               ret_info[i].format);
+    }
+
+    av_free(ret_info);
+
+    if (best_format == AV_PIX_FMT_NONE) {
+        av_log(avctx, AV_LOG_ERROR, "No valid/compatible pixel format found for decoding!\n");
+        return AVERROR(EINVAL);
+    } else {
+        av_log(avctx, AV_LOG_VERBOSE, "Chosen frame pixfmt: %s (Vulkan ID: %i)\n",
+               av_get_pix_fmt_name(best_format), best_vkfmt);
+    }
+
+    *pix_fmt = best_format;
+    *vk_fmt = best_vkfmt;
+
+    *dpb_dedicate = dec->dedicated_dpb;
+
+    return 0;
+}
+
+static void free_profile_data(AVHWFramesContext *hwfc)
+{
+    av_free(hwfc->user_opaque);
+}
+
+int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
+{
+    VkFormat vkfmt = VK_FORMAT_UNDEFINED;
+    int err, dedicated_dpb;
+    AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data;
+    AVVulkanFramesContext *hwfc = frames_ctx->hwctx;
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeProfileData *prof = NULL;
+
+    err = vulkan_decode_bootstrap(avctx, hw_frames_ctx);
+    if (err < 0)
+        return err;
+
+    frames_ctx->sw_format = avctx->sw_pix_fmt;
+
+    if (!DECODER_IS_SDR(avctx->codec_id)) {
+        prof = av_mallocz(sizeof(FFVulkanDecodeProfileData));
+        if (!prof)
+            return AVERROR(ENOMEM);
+
+        err = vulkan_decode_get_profile(avctx, hw_frames_ctx,
+                                        &frames_ctx->sw_format, &vkfmt,
+                                        prof, &dedicated_dpb);
+        if (err < 0) {
+            av_free(prof);
+            return err;
+        }
+
+        frames_ctx->user_opaque = prof;
+        frames_ctx->free        = free_profile_data;
+
+        hwfc->create_pnext = &prof->profile_list;
+    } else {
+        switch (frames_ctx->sw_format) {
+        case AV_PIX_FMT_GBRAP16:
+            /* This should be more efficient for downloading and using */
+            frames_ctx->sw_format = AV_PIX_FMT_RGBA64;
+            break;
+        case AV_PIX_FMT_GBRP10:
+            /* This saves memory bandwidth when downloading */
+            frames_ctx->sw_format = AV_PIX_FMT_X2BGR10;
+            break;
+        case AV_PIX_FMT_BGR0:
+            /* mpv has issues with bgr0 mapping, so just remap it */
+            frames_ctx->sw_format = AV_PIX_FMT_RGB0;
+            break;
+        default:
+            break;
+        }
+    }
+
+    frames_ctx->width  = avctx->coded_width;
+    frames_ctx->height = avctx->coded_height;
+    frames_ctx->format = AV_PIX_FMT_VULKAN;
+
+    hwfc->format[0]    = vkfmt;
+    hwfc->tiling       = VK_IMAGE_TILING_OPTIMAL;
+    hwfc->usage        = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+                         VK_IMAGE_USAGE_STORAGE_BIT      |
+                         VK_IMAGE_USAGE_SAMPLED_BIT;
+
+    if (prof) {
+        FFVulkanDecodeShared *ctx;
+
+        hwfc->usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR;
+        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;
+}
+
+static void vk_decode_free_params(void *opaque, uint8_t *data)
+{
+    FFVulkanDecodeShared *ctx = opaque;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+    VkVideoSessionParametersKHR *par = (VkVideoSessionParametersKHR *)data;
+    vk->DestroyVideoSessionParametersKHR(ctx->s.hwctx->act_dev, *par,
+                                         ctx->s.hwctx->alloc);
+    av_free(par);
+}
+
+int ff_vk_decode_create_params(AVBufferRef **par_ref, void *logctx, FFVulkanDecodeShared *ctx,
+                               const VkVideoSessionParametersCreateInfoKHR *session_params_create)
+{
+    VkVideoSessionParametersKHR *par = av_malloc(sizeof(*par));
+    const FFVulkanFunctions *vk = &ctx->s.vkfn;
+    VkResult ret;
+
+    if (!par)
+        return AVERROR(ENOMEM);
+
+    /* Create session parameters */
+    ret = vk->CreateVideoSessionParametersKHR(ctx->s.hwctx->act_dev, session_params_create,
+                                              ctx->s.hwctx->alloc, par);
+    if (ret != VK_SUCCESS) {
+        av_log(logctx, AV_LOG_ERROR, "Unable to create Vulkan video session parameters: %s!\n",
+               ff_vk_ret2str(ret));
+        av_free(par);
+        return AVERROR_EXTERNAL;
+    }
+    *par_ref = av_buffer_create((uint8_t *)par, sizeof(*par),
+                                vk_decode_free_params, ctx, 0);
+    if (!*par_ref) {
+        vk_decode_free_params(ctx, (uint8_t *)par);
+        return AVERROR(ENOMEM);
+    }
+
+    return 0;
+}
+
+int ff_vk_decode_uninit(AVCodecContext *avctx)
+{
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+
+    av_freep(&dec->hevc_headers);
+    av_buffer_unref(&dec->session_params);
+    av_refstruct_unref(&dec->shared_ctx);
+    av_freep(&dec->slice_off);
+    return 0;
+}
+
+static int create_empty_session_parameters(AVCodecContext *avctx,
+                                           FFVulkanDecodeShared *ctx)
+{
+    VkResult ret;
+    FFVulkanContext *s = &ctx->s;
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    VkVideoDecodeH264SessionParametersCreateInfoKHR h264_params = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR,
+    };
+    VkVideoDecodeH265SessionParametersCreateInfoKHR h265_params = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR,
+    };
+    StdVideoAV1SequenceHeader av1_empty_seq = { 0 };
+    VkVideoDecodeAV1SessionParametersCreateInfoKHR av1_params = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR,
+        .pStdSequenceHeader = &av1_empty_seq,
+    };
+    VkVideoSessionParametersCreateInfoKHR session_params_create = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
+        .pNext = avctx->codec_id == AV_CODEC_ID_H264 ? (void *)&h264_params :
+                 avctx->codec_id == AV_CODEC_ID_HEVC ? (void *)&h265_params :
+                 avctx->codec_id == AV_CODEC_ID_AV1  ? (void *)&av1_params  :
+                 NULL,
+        .videoSession = ctx->common.session,
+    };
+
+    if (avctx->codec_id == AV_CODEC_ID_VP9)
+        return 0;
+
+    ret = vk->CreateVideoSessionParametersKHR(s->hwctx->act_dev, &session_params_create,
+                                              s->hwctx->alloc, &ctx->empty_session_params);
+    if (ret != VK_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to create empty Vulkan video session parameters: %s!\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+int ff_vk_decode_init(AVCodecContext *avctx)
+{
+    int err;
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx;
+    FFVulkanContext *s;
+    int async_depth;
+    const VkVideoProfileInfoKHR *profile;
+    const FFVulkanDecodeDescriptor *vk_desc;
+    const VkPhysicalDeviceDriverProperties *driver_props;
+
+    VkVideoSessionCreateInfoKHR session_create = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR,
+    };
+
+    err = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_VULKAN);
+    if (err < 0)
+        return err;
+
+    /* Initialize contexts */
+    ctx = dec->shared_ctx;
+    s = &ctx->s;
+
+    err = ff_vk_init(s, avctx, NULL, avctx->hw_frames_ctx);
+    if (err < 0)
+        return err;
+
+    vk_desc = get_codecdesc(avctx->codec_id);
+
+    profile = get_video_profile(ctx, avctx->codec_id);
+    if ((vk_desc->queue_flags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) && !profile) {
+        av_log(avctx, AV_LOG_ERROR, "Video profile missing from frames context!");
+        return AVERROR(EINVAL);
+    }
+
+    /* Create queue context */
+    vk_desc = get_codecdesc(avctx->codec_id);
+    ctx->qf = ff_vk_qf_find(s, vk_desc->queue_flags, vk_desc->decode_op);
+    if (!ctx->qf) {
+        av_log(avctx, AV_LOG_ERROR, "Decoding of %s is not supported by this device\n",
+               avcodec_get_name(avctx->codec_id));
+        return err;
+    }
+
+    session_create.queueFamilyIndex = ctx->qf->idx;
+    session_create.maxCodedExtent = ctx->caps.maxCodedExtent;
+    session_create.maxDpbSlots = ctx->caps.maxDpbSlots;
+    session_create.maxActiveReferencePictures = ctx->caps.maxActiveReferencePictures;
+    session_create.pictureFormat = s->hwfc->format[0];
+    session_create.referencePictureFormat = session_create.pictureFormat;
+    session_create.pStdHeaderVersion = &vk_desc->ext_props;
+    session_create.pVideoProfile = profile;
+#ifdef VK_KHR_video_maintenance2
+    if (ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)
+        session_create.flags = VK_VIDEO_SESSION_CREATE_INLINE_SESSION_PARAMETERS_BIT_KHR;
+#endif
+
+    /* Create decode exec context for this specific main thread.
+     * 2 async contexts per thread was experimentally determined to be optimal
+     * for a majority of streams. */
+    async_depth = 2*ctx->qf->num;
+    /* We don't need more than 2 per thread context */
+    async_depth = FFMIN(async_depth, 2*avctx->thread_count);
+    /* Make sure there are enough async contexts for each thread */
+    async_depth = FFMAX(async_depth, avctx->thread_count);
+
+    err = ff_vk_exec_pool_init(s, ctx->qf, &ctx->exec_pool,
+                               async_depth, 0, 0, 0, profile);
+    if (err < 0)
+        goto fail;
+
+    if (!DECODER_IS_SDR(avctx->codec_id)) {
+        err = ff_vk_video_common_init(avctx, s, &ctx->common, &session_create);
+        if (err < 0)
+            goto fail;
+    }
+
+    /* If doing an out-of-place decoding, create a DPB pool */
+    if (dec->dedicated_dpb || avctx->codec_id == AV_CODEC_ID_AV1) {
+        AVHWFramesContext *dpb_frames;
+        AVVulkanFramesContext *dpb_hwfc;
+
+        ctx->common.dpb_hwfc_ref = av_hwframe_ctx_alloc(s->frames->device_ref);
+        if (!ctx->common.dpb_hwfc_ref) {
+            err = AVERROR(ENOMEM);
+            goto fail;
+        }
+
+        dpb_frames = (AVHWFramesContext *)ctx->common.dpb_hwfc_ref->data;
+        dpb_frames->format    = s->frames->format;
+        dpb_frames->sw_format = s->frames->sw_format;
+        dpb_frames->width     = avctx->coded_width;
+        dpb_frames->height    = avctx->coded_height;
+
+        dpb_hwfc = dpb_frames->hwctx;
+        dpb_hwfc->create_pnext = (void *)ff_vk_find_struct(ctx->s.hwfc->create_pnext,
+                                                           VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
+        dpb_hwfc->format[0]    = s->hwfc->format[0];
+        dpb_hwfc->tiling       = VK_IMAGE_TILING_OPTIMAL;
+        dpb_hwfc->usage        = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR |
+                                 VK_IMAGE_USAGE_SAMPLED_BIT; /* Shuts validator up. */
+
+        if (ctx->common.layered_dpb)
+            dpb_hwfc->nb_layers = ctx->caps.maxDpbSlots;
+
+        err = av_hwframe_ctx_init(ctx->common.dpb_hwfc_ref);
+        if (err < 0)
+            goto fail;
+
+        if (ctx->common.layered_dpb) {
+            ctx->common.layered_frame = vk_get_dpb_pool(ctx);
+            if (!ctx->common.layered_frame) {
+                err = AVERROR(ENOMEM);
+                goto fail;
+            }
+
+            err = ff_vk_create_view(&ctx->s, &ctx->common,
+                                    &ctx->common.layered_view,
+                                    &ctx->common.layered_aspect,
+                                    (AVVkFrame *)ctx->common.layered_frame->data[0],
+                                    s->hwfc->format[0], 1);
+            if (err < 0)
+                goto fail;
+        }
+    }
+
+    if (!DECODER_IS_SDR(avctx->codec_id)) {
+        if (!(ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)) {
+            err = create_empty_session_parameters(avctx, ctx);
+            if (err < 0)
+                return err;
+        }
+    } else {
+        /* For SDR decoders, this alignment value will be 0. Since this will make
+         * add_slice() malfunction, set it to a sane default value. */
+        ctx->caps.minBitstreamBufferSizeAlignment = AV_INPUT_BUFFER_PADDING_SIZE;
+    }
+
+    driver_props = &dec->shared_ctx->s.driver_props;
+    if (driver_props->driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
+        driver_props->conformanceVersion.major == 1 &&
+        driver_props->conformanceVersion.minor == 3 &&
+        driver_props->conformanceVersion.subminor == 8 &&
+        driver_props->conformanceVersion.patch < 3)
+        dec->quirk_av1_offset = 1;
+
+    ff_vk_decode_flush(avctx);
+
+    av_log(avctx, AV_LOG_VERBOSE, "Vulkan decoder initialization successful\n");
+
+    return 0;
+
+fail:
+    ff_vk_decode_uninit(avctx);
+
+    return err;
+}
-- 
2.49.1


From 76fc9208cb8884e23b6d31f3d2fa9891be6ab22f Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:30:00 +0000
Subject: [PATCH 067/118] Changing vulkan file directory

---
 libavcodec/vulkan_decode.h | 189 -------------------------------------
 1 file changed, 189 deletions(-)
 delete mode 100644 libavcodec/vulkan_decode.h

diff --git a/libavcodec/vulkan_decode.h b/libavcodec/vulkan_decode.h
deleted file mode 100644
index e32468f317..0000000000
--- a/libavcodec/vulkan_decode.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVCODEC_VULKAN_DECODE_H
-#define AVCODEC_VULKAN_DECODE_H
-
-#include "codec_id.h"
-#include "decode.h"
-#include "hwaccel_internal.h"
-#include "internal.h"
-
-#include "vulkan_video.h"
-
-typedef struct FFVulkanDecodeDescriptor {
-    enum AVCodecID                   codec_id;
-    FFVulkanExtensions               decode_extension;
-    VkQueueFlagBits                  queue_flags;
-    VkVideoCodecOperationFlagBitsKHR decode_op;
-
-    VkExtensionProperties ext_props;
-} FFVulkanDecodeDescriptor;
-
-typedef struct FFVulkanDecodeShared {
-    FFVulkanContext s;
-    FFVkVideoCommon common;
-    AVVulkanDeviceQueueFamily *qf;
-    FFVkExecPool exec_pool;
-
-    AVBufferPool *buf_pool;
-
-    VkVideoCapabilitiesKHR caps;
-    VkVideoDecodeCapabilitiesKHR dec_caps;
-
-    VkVideoSessionParametersKHR empty_session_params;
-
-    /* Software-defined decoder context */
-    void *sd_ctx;
-    void (*sd_ctx_free)(struct FFVulkanDecodeShared *ctx);
-} FFVulkanDecodeShared;
-
-typedef struct FFVulkanDecodeContext {
-    FFVulkanDecodeShared *shared_ctx;
-    AVBufferRef *session_params;
-
-    int dedicated_dpb; /* Oddity  #1 - separate DPB images */
-    int external_fg;   /* Oddity  #2 - hardware can't apply film grain */
-
-    /* Workaround for NVIDIA drivers tested with CTS version 1.3.8 for AV1.
-     * The tests were incorrect as the OrderHints were offset by 1. */
-    int quirk_av1_offset;
-
-    /* Thread-local state below */
-    struct HEVCHeaderSet *hevc_headers;
-    size_t hevc_headers_size;
-
-    uint32_t                       *slice_off;
-    unsigned int                    slice_off_max;
-} FFVulkanDecodeContext;
-
-typedef struct FFVulkanDecodePicture {
-    AVFrame                        *dpb_frame;      /* Only used for out-of-place decoding. */
-
-    struct {
-        VkImageView                     ref[AV_NUM_DATA_POINTERS];        /* Image representation view (reference) */
-        VkImageView                     out[AV_NUM_DATA_POINTERS];        /* Image representation view (output-only) */
-        VkImageView                     dst[AV_NUM_DATA_POINTERS];        /* Set to img_view_out if no layered refs are used */
-        VkImageAspectFlags              aspect[AV_NUM_DATA_POINTERS];     /* Image plane mask bits */
-        VkImageAspectFlags              aspect_ref[AV_NUM_DATA_POINTERS]; /* Only used for out-of-place decoding */
-    } view;
-
-    VkSemaphore                     sem;
-    uint64_t                        sem_value;
-
-    /* Current picture */
-    VkVideoPictureResourceInfoKHR   ref;
-    VkVideoReferenceSlotInfoKHR     ref_slot;
-
-    /* Picture refs. H264 has the maximum number of refs (36) of any supported codec. */
-    VkVideoPictureResourceInfoKHR   refs     [36];
-    VkVideoReferenceSlotInfoKHR     ref_slots[36];
-
-    /* Main decoding struct */
-    VkVideoDecodeInfoKHR            decode_info;
-
-    /* Slice data */
-    AVBufferRef                    *slices_buf;
-    size_t                          slices_size;
-
-    /* Vulkan functions needed for destruction, as no other context is guaranteed to exist */
-    PFN_vkWaitSemaphores            wait_semaphores;
-    PFN_vkDestroyImageView          destroy_image_view;
-    PFN_vkInvalidateMappedMemoryRanges invalidate_memory_ranges;
-} FFVulkanDecodePicture;
-
-/**
- * Initialize decoder.
- */
-int ff_vk_decode_init(AVCodecContext *avctx);
-
-/**
- * Synchronize the contexts between 2 threads.
- */
-int ff_vk_update_thread_context(AVCodecContext *dst, const AVCodecContext *src);
-
-/**
- * Initialize hw_frames_ctx with the parameters needed to decode the stream
- * using the parameters from avctx.
- *
- * NOTE: if avctx->internal->hwaccel_priv_data exists, will partially initialize
- * the context.
- */
-int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx);
-
-/**
- * Removes current session parameters to recreate them
- */
-int ff_vk_params_invalidate(AVCodecContext *avctx, int t, const uint8_t *b, uint32_t s);
-
-/**
- * Prepare a frame, creates the image view, and sets up the dpb fields.
- */
-int ff_vk_decode_prepare_frame(FFVulkanDecodeContext *dec, AVFrame *pic,
-                               FFVulkanDecodePicture *vkpic, int is_current,
-                               int alloc_dpb);
-
-/**
- * Software-defined decoder version of ff_vk_decode_prepare_frame.
- */
-int ff_vk_decode_prepare_frame_sdr(FFVulkanDecodeContext *dec, AVFrame *pic,
-                                   FFVulkanDecodePicture *vkpic, int is_current,
-                                   enum FFVkShaderRepFormat rep_fmt, int alloc_dpb);
-
-/**
- * Add slice data to frame.
- */
-int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp,
-                           const uint8_t *data, size_t size, int add_startcode,
-                           uint32_t *nb_slices, const uint32_t **offsets);
-
-/**
- * Decode a frame.
- */
-int ff_vk_decode_frame(AVCodecContext *avctx,
-                       AVFrame *pic,    FFVulkanDecodePicture *vp,
-                       AVFrame *rpic[], FFVulkanDecodePicture *rvkp[]);
-
-/**
- * Free a frame and its state.
- */
-void ff_vk_decode_free_frame(AVHWDeviceContext *dev_ctx, FFVulkanDecodePicture *vp);
-
-/**
- * Get an FFVkBuffer suitable for decoding from.
- */
-int ff_vk_get_decode_buffer(FFVulkanDecodeContext *ctx, AVBufferRef **buf,
-                            void *create_pNext, size_t size);
-
-/**
- * Create VkVideoSessionParametersKHR wrapped in an AVBufferRef.
- */
-int ff_vk_decode_create_params(AVBufferRef **par_ref, void *logctx, FFVulkanDecodeShared *ctx,
-                               const VkVideoSessionParametersCreateInfoKHR *session_params_create);
-
-/**
- * Flush decoder.
- */
-void ff_vk_decode_flush(AVCodecContext *avctx);
-
-/**
- * Free decoder.
- */
-int ff_vk_decode_uninit(AVCodecContext *avctx);
-
-#endif /* AVCODEC_VULKAN_DECODE_H */
-- 
2.49.1


From ab5c3f473542c3e6db62a446e0352f462c9da19e Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:30:35 +0000
Subject: [PATCH 068/118] Changing vulkan file directory

---
 libavcodec/vulkan/vulkan_decode.h | 189 ++++++++++++++++++++++++++++++
 1 file changed, 189 insertions(+)
 create mode 100644 libavcodec/vulkan/vulkan_decode.h

diff --git a/libavcodec/vulkan/vulkan_decode.h b/libavcodec/vulkan/vulkan_decode.h
new file mode 100644
index 0000000000..59d22096f4
--- /dev/null
+++ b/libavcodec/vulkan/vulkan_decode.h
@@ -0,0 +1,189 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_VULKAN_DECODE_H
+#define AVCODEC_VULKAN_DECODE_H
+
+#include "libavcodec/codec_id.h"
+#include "libavcodec/decode.h"
+#include "libavcodec/hwaccel_internal.h"
+#include "libavcodec/internal.h"
+
+#include "vulkan_video.h"
+
+typedef struct FFVulkanDecodeDescriptor {
+    enum AVCodecID                   codec_id;
+    FFVulkanExtensions               decode_extension;
+    VkQueueFlagBits                  queue_flags;
+    VkVideoCodecOperationFlagBitsKHR decode_op;
+
+    VkExtensionProperties ext_props;
+} FFVulkanDecodeDescriptor;
+
+typedef struct FFVulkanDecodeShared {
+    FFVulkanContext s;
+    FFVkVideoCommon common;
+    AVVulkanDeviceQueueFamily *qf;
+    FFVkExecPool exec_pool;
+
+    AVBufferPool *buf_pool;
+
+    VkVideoCapabilitiesKHR caps;
+    VkVideoDecodeCapabilitiesKHR dec_caps;
+
+    VkVideoSessionParametersKHR empty_session_params;
+
+    /* Software-defined decoder context */
+    void *sd_ctx;
+    void (*sd_ctx_free)(struct FFVulkanDecodeShared *ctx);
+} FFVulkanDecodeShared;
+
+typedef struct FFVulkanDecodeContext {
+    FFVulkanDecodeShared *shared_ctx;
+    AVBufferRef *session_params;
+
+    int dedicated_dpb; /* Oddity  #1 - separate DPB images */
+    int external_fg;   /* Oddity  #2 - hardware can't apply film grain */
+
+    /* Workaround for NVIDIA drivers tested with CTS version 1.3.8 for AV1.
+     * The tests were incorrect as the OrderHints were offset by 1. */
+    int quirk_av1_offset;
+
+    /* Thread-local state below */
+    struct HEVCHeaderSet *hevc_headers;
+    size_t hevc_headers_size;
+
+    uint32_t                       *slice_off;
+    unsigned int                    slice_off_max;
+} FFVulkanDecodeContext;
+
+typedef struct FFVulkanDecodePicture {
+    AVFrame                        *dpb_frame;      /* Only used for out-of-place decoding. */
+
+    struct {
+        VkImageView                     ref[AV_NUM_DATA_POINTERS];        /* Image representation view (reference) */
+        VkImageView                     out[AV_NUM_DATA_POINTERS];        /* Image representation view (output-only) */
+        VkImageView                     dst[AV_NUM_DATA_POINTERS];        /* Set to img_view_out if no layered refs are used */
+        VkImageAspectFlags              aspect[AV_NUM_DATA_POINTERS];     /* Image plane mask bits */
+        VkImageAspectFlags              aspect_ref[AV_NUM_DATA_POINTERS]; /* Only used for out-of-place decoding */
+    } view;
+
+    VkSemaphore                     sem;
+    uint64_t                        sem_value;
+
+    /* Current picture */
+    VkVideoPictureResourceInfoKHR   ref;
+    VkVideoReferenceSlotInfoKHR     ref_slot;
+
+    /* Picture refs. H264 has the maximum number of refs (36) of any supported codec. */
+    VkVideoPictureResourceInfoKHR   refs     [36];
+    VkVideoReferenceSlotInfoKHR     ref_slots[36];
+
+    /* Main decoding struct */
+    VkVideoDecodeInfoKHR            decode_info;
+
+    /* Slice data */
+    AVBufferRef                    *slices_buf;
+    size_t                          slices_size;
+
+    /* Vulkan functions needed for destruction, as no other context is guaranteed to exist */
+    PFN_vkWaitSemaphores            wait_semaphores;
+    PFN_vkDestroyImageView          destroy_image_view;
+    PFN_vkInvalidateMappedMemoryRanges invalidate_memory_ranges;
+} FFVulkanDecodePicture;
+
+/**
+ * Initialize decoder.
+ */
+int ff_vk_decode_init(AVCodecContext *avctx);
+
+/**
+ * Synchronize the contexts between 2 threads.
+ */
+int ff_vk_update_thread_context(AVCodecContext *dst, const AVCodecContext *src);
+
+/**
+ * Initialize hw_frames_ctx with the parameters needed to decode the stream
+ * using the parameters from avctx.
+ *
+ * NOTE: if avctx->internal->hwaccel_priv_data exists, will partially initialize
+ * the context.
+ */
+int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx);
+
+/**
+ * Removes current session parameters to recreate them
+ */
+int ff_vk_params_invalidate(AVCodecContext *avctx, int t, const uint8_t *b, uint32_t s);
+
+/**
+ * Prepare a frame, creates the image view, and sets up the dpb fields.
+ */
+int ff_vk_decode_prepare_frame(FFVulkanDecodeContext *dec, AVFrame *pic,
+                               FFVulkanDecodePicture *vkpic, int is_current,
+                               int alloc_dpb);
+
+/**
+ * Software-defined decoder version of ff_vk_decode_prepare_frame.
+ */
+int ff_vk_decode_prepare_frame_sdr(FFVulkanDecodeContext *dec, AVFrame *pic,
+                                   FFVulkanDecodePicture *vkpic, int is_current,
+                                   enum FFVkShaderRepFormat rep_fmt, int alloc_dpb);
+
+/**
+ * Add slice data to frame.
+ */
+int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp,
+                           const uint8_t *data, size_t size, int add_startcode,
+                           uint32_t *nb_slices, const uint32_t **offsets);
+
+/**
+ * Decode a frame.
+ */
+int ff_vk_decode_frame(AVCodecContext *avctx,
+                       AVFrame *pic,    FFVulkanDecodePicture *vp,
+                       AVFrame *rpic[], FFVulkanDecodePicture *rvkp[]);
+
+/**
+ * Free a frame and its state.
+ */
+void ff_vk_decode_free_frame(AVHWDeviceContext *dev_ctx, FFVulkanDecodePicture *vp);
+
+/**
+ * Get an FFVkBuffer suitable for decoding from.
+ */
+int ff_vk_get_decode_buffer(FFVulkanDecodeContext *ctx, AVBufferRef **buf,
+                            void *create_pNext, size_t size);
+
+/**
+ * Create VkVideoSessionParametersKHR wrapped in an AVBufferRef.
+ */
+int ff_vk_decode_create_params(AVBufferRef **par_ref, void *logctx, FFVulkanDecodeShared *ctx,
+                               const VkVideoSessionParametersCreateInfoKHR *session_params_create);
+
+/**
+ * Flush decoder.
+ */
+void ff_vk_decode_flush(AVCodecContext *avctx);
+
+/**
+ * Free decoder.
+ */
+int ff_vk_decode_uninit(AVCodecContext *avctx);
+
+#endif /* AVCODEC_VULKAN_DECODE_H */
-- 
2.49.1


From 4ad6fd88f38a083b0ba171521f01add728f21596 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:31:02 +0000
Subject: [PATCH 069/118] Changing vulkan file directory

---
 libavcodec/vulkan_encode.c | 1054 ------------------------------------
 1 file changed, 1054 deletions(-)
 delete mode 100644 libavcodec/vulkan_encode.c

diff --git a/libavcodec/vulkan_encode.c b/libavcodec/vulkan_encode.c
deleted file mode 100644
index e5c0496f1c..0000000000
--- a/libavcodec/vulkan_encode.c
+++ /dev/null
@@ -1,1054 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/mem.h"
-#include "libavutil/avassert.h"
-#include "vulkan_encode.h"
-#include "config.h"
-
-#include "libavutil/vulkan_loader.h"
-
-const AVCodecHWConfigInternal *const ff_vulkan_encode_hw_configs[] = {
-    HW_CONFIG_ENCODER_FRAMES(VULKAN, VULKAN),
-    NULL,
-};
-
-av_cold void ff_vulkan_encode_uninit(FFVulkanEncodeContext *ctx)
-{
-    FFVulkanContext *s = &ctx->s;
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    /* Wait on and free execution pool */
-    ff_vk_exec_pool_free(s, &ctx->enc_pool);
-
-    /* Destroy the session params */
-    if (ctx->session_params)
-        vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
-                                             ctx->session_params,
-                                             s->hwctx->alloc);
-
-    ff_hw_base_encode_close(&ctx->base);
-
-    av_buffer_pool_uninit(&ctx->buf_pool);
-
-    ff_vk_video_common_uninit(s, &ctx->common);
-
-    ff_vk_uninit(s);
-}
-
-static int vulkan_encode_init(AVCodecContext *avctx, FFHWBaseEncodePicture *pic)
-{
-    int err;
-    FFVulkanEncodeContext *ctx = avctx->priv_data;
-    FFVulkanEncodePicture *vp = pic->priv;
-
-    AVFrame *f = pic->input_image;
-    AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
-    AVVulkanFramesContext *vkfc = hwfc->hwctx;
-    AVVkFrame *vkf = (AVVkFrame *)f->data[0];
-
-    if (ctx->codec->picture_priv_data_size > 0) {
-        pic->codec_priv = av_mallocz(ctx->codec->picture_priv_data_size);
-        if (!pic->codec_priv)
-            return AVERROR(ENOMEM);
-    }
-
-    /* Input image view */
-    err = ff_vk_create_view(&ctx->s, &ctx->common,
-                            &vp->in.view, &vp->in.aspect,
-                            vkf, vkfc->format[0], 0);
-    if (err < 0)
-        return err;
-
-    /* Reference view */
-    if (!ctx->common.layered_dpb) {
-        AVFrame *rf = pic->recon_image;
-        AVVkFrame *rvkf = (AVVkFrame *)rf->data[0];
-        err = ff_vk_create_view(&ctx->s, &ctx->common,
-                                &vp->dpb.view, &vp->dpb.aspect,
-                                rvkf, ctx->pic_format, 1);
-        if (err < 0)
-            return err;
-    } else {
-        vp->dpb.view = ctx->common.layered_view;
-        vp->dpb.aspect = ctx->common.layered_aspect;
-    }
-
-    return 0;
-}
-
-static int vulkan_encode_free(AVCodecContext *avctx, FFHWBaseEncodePicture *pic)
-{
-    FFVulkanEncodeContext *ctx = avctx->priv_data;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-
-    FFVulkanEncodePicture *vp = pic->priv;
-
-    if (vp->in.view)
-        vk->DestroyImageView(ctx->s.hwctx->act_dev, vp->in.view,
-                             ctx->s.hwctx->alloc);
-
-    if (!ctx->common.layered_dpb && vp->dpb.view)
-        vk->DestroyImageView(ctx->s.hwctx->act_dev, vp->dpb.view,
-                             ctx->s.hwctx->alloc);
-
-    ctx->slots[vp->dpb_slot.slotIndex] = NULL;
-
-    return 0;
-}
-
-static int init_pic_rc(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
-                       VkVideoEncodeRateControlInfoKHR *rc_info,
-                       VkVideoEncodeRateControlLayerInfoKHR *rc_layer /* Goes in ^ */)
-{
-    FFVulkanEncodeContext *ctx = avctx->priv_data;
-
-    *rc_info = (VkVideoEncodeRateControlInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR,
-        .rateControlMode = ctx->opts.rc_mode,
-    };
-
-    if (ctx->opts.rc_mode > VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
-        *rc_layer = (VkVideoEncodeRateControlLayerInfoKHR) {
-            .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_LAYER_INFO_KHR,
-            .averageBitrate = avctx->bit_rate,
-            .maxBitrate = avctx->rc_max_rate ? avctx->rc_max_rate : avctx->bit_rate,
-            .frameRateNumerator = avctx->framerate.num,
-            .frameRateDenominator = avctx->framerate.den,
-        };
-        rc_info->layerCount++;
-        rc_info->pLayers = rc_layer;
-    }
-
-    return ctx->codec->init_pic_rc(avctx, pic, rc_info, rc_layer);
-}
-
-static int vulkan_encode_issue(AVCodecContext *avctx,
-                               FFHWBaseEncodePicture *base_pic)
-{
-    FFVulkanEncodeContext *ctx = avctx->priv_data;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-
-    const size_t size_align = ctx->caps.minBitstreamBufferSizeAlignment;
-
-    FFVulkanEncodePicture *vp = base_pic->priv;
-    AVFrame *src = (AVFrame *)base_pic->input_image;
-    AVVkFrame *vkf = (AVVkFrame *)src->data[0];
-
-    int err, max_pkt_size;
-
-    FFVkBuffer *sd_buf;
-
-    int slot_index = -1;
-    FFVkExecContext *exec;
-    VkCommandBuffer cmd_buf;
-    VkImageMemoryBarrier2 img_bar[37];
-    int nb_img_bar = 0;
-
-    /* Coding start/end */
-    VkVideoBeginCodingInfoKHR encode_start;
-    VkVideoEndCodingInfoKHR encode_end = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR,
-    };
-
-    VkVideoEncodeRateControlLayerInfoKHR rc_layer;
-    VkVideoEncodeRateControlInfoKHR rc_info;
-    VkVideoEncodeQualityLevelInfoKHR q_info;
-    VkVideoCodingControlInfoKHR encode_ctrl;
-
-    VkVideoReferenceSlotInfoKHR ref_slot[37];
-    VkVideoEncodeInfoKHR encode_info;
-
-    /* Create packet data buffer */
-    max_pkt_size = FFALIGN(3 * ctx->base.surface_width * ctx->base.surface_height + (1 << 16),
-                           ctx->caps.minBitstreamBufferSizeAlignment);
-
-    err = ff_vk_get_pooled_buffer(&ctx->s, &ctx->buf_pool, &vp->pkt_buf,
-                                  VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR,
-                                  &ctx->profile_list, max_pkt_size,
-                                  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
-                                  VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
-    if (err < 0)
-        return err;
-
-    sd_buf = (FFVkBuffer *)vp->pkt_buf->data;
-
-    /* Setup rate control */
-    err = init_pic_rc(avctx, base_pic, &rc_info, &rc_layer);
-    if (err < 0)
-        return err;
-
-    q_info = (VkVideoEncodeQualityLevelInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR,
-        .pNext = &rc_info,
-        .qualityLevel = ctx->opts.quality,
-    };
-    encode_ctrl = (VkVideoCodingControlInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR,
-        .pNext = &q_info,
-        .flags = VK_VIDEO_CODING_CONTROL_ENCODE_QUALITY_LEVEL_BIT_KHR |
-                 VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_BIT_KHR |
-                 VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR,
-    };
-
-    for (int i = 0; i < ctx->caps.maxDpbSlots; i++) {
-        if (ctx->slots[i] == NULL) {
-            slot_index = i;
-            ctx->slots[i] = base_pic;
-            break;
-        }
-    }
-    av_assert0(slot_index >= 0);
-
-    /* Current picture's ref slot */
-    vp->dpb_res = (VkVideoPictureResourceInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
-        .pNext = NULL,
-        .codedOffset = { 0 },
-        .codedExtent = (VkExtent2D){ avctx->width, avctx->height },
-        .baseArrayLayer = ctx->common.layered_dpb ? slot_index : 0,
-        .imageViewBinding = vp->dpb.view,
-    };
-
-    vp->dpb_slot = (VkVideoReferenceSlotInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
-        .pNext = NULL,  // Set later
-        .slotIndex = slot_index,
-        .pPictureResource = &vp->dpb_res,
-    };
-
-    encode_info = (VkVideoEncodeInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR,
-        .pNext = NULL, // Set later
-        .flags = 0x0,
-        .srcPictureResource = (VkVideoPictureResourceInfoKHR) {
-            .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
-            .pNext = NULL,
-            .codedOffset = { 0, 0 },
-            .codedExtent = (VkExtent2D){ base_pic->input_image->width,
-                                         base_pic->input_image->height },
-            .baseArrayLayer = 0,
-            .imageViewBinding = vp->in.view,
-        },
-        .pSetupReferenceSlot = &vp->dpb_slot,
-        .referenceSlotCount = 0,
-        .pReferenceSlots = ref_slot,
-        .dstBuffer = sd_buf->buf,
-        .dstBufferOffset = 0,
-        .dstBufferRange = sd_buf->size,
-        .precedingExternallyEncodedBytes = 0,
-    };
-
-    for (int i = 0; i < MAX_REFERENCE_LIST_NUM; i++) {
-        for (int j = 0; j < base_pic->nb_refs[i]; j++) {
-            FFHWBaseEncodePicture *ref = base_pic->refs[i][j];
-            FFVulkanEncodePicture *rvp = ref->priv;
-            ref_slot[encode_info.referenceSlotCount++] = rvp->dpb_slot;
-        }
-    }
-
-    /* Calling vkCmdBeginVideoCodingKHR requires to declare all references
-     * being enabled upfront, including the current frame's output ref. */
-    ref_slot[encode_info.referenceSlotCount] = vp->dpb_slot;
-    ref_slot[encode_info.referenceSlotCount].slotIndex = -1;
-
-    /* Setup picture parameters */
-    err = ctx->codec->init_pic_params(avctx, base_pic,
-                                      &encode_info);
-    if (err < 0)
-        return err;
-
-    encode_start = (VkVideoBeginCodingInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
-        .pNext = !base_pic->force_idr ? &rc_info : NULL,
-        .videoSession = ctx->common.session,
-        .videoSessionParameters = ctx->session_params,
-        .referenceSlotCount = encode_info.referenceSlotCount + 1,
-        .pReferenceSlots = ref_slot,
-    };
-
-    /* Write header */
-    if (base_pic->type == FF_HW_PICTURE_TYPE_IDR) {
-        uint8_t *hdr_dst = sd_buf->mapped_mem + encode_info.dstBufferOffset;
-        size_t data_size = encode_info.dstBufferRange;
-        err = ctx->codec->write_sequence_headers(avctx, base_pic, hdr_dst, &data_size);
-        if (err < 0)
-            goto fail;
-        encode_info.dstBufferOffset += data_size;
-        encode_info.dstBufferRange  -= data_size;
-    }
-
-    /* Write extra units */
-    if (ctx->codec->write_extra_headers) {
-        uint8_t *hdr_dst = sd_buf->mapped_mem + encode_info.dstBufferOffset;
-        size_t data_size = encode_info.dstBufferRange;
-        err = ctx->codec->write_extra_headers(avctx, base_pic, hdr_dst, &data_size);
-        if (err < 0)
-            goto fail;
-        encode_info.dstBufferOffset += data_size;
-        encode_info.dstBufferRange  -= data_size;
-    }
-
-    /* Align buffer offset to the required value with filler units */
-    if (ctx->codec->write_filler) {
-        uint8_t *hdr_dst = sd_buf->mapped_mem + encode_info.dstBufferOffset;
-        size_t data_size = encode_info.dstBufferRange;
-
-        uint32_t offset = encode_info.dstBufferOffset;
-        size_t offset_align = ctx->caps.minBitstreamBufferOffsetAlignment;
-
-        uint32_t filler_data = FFALIGN(offset, offset_align) - offset;
-
-        if (filler_data) {
-            while (filler_data < ctx->codec->filler_header_size)
-                filler_data += offset_align;
-
-            filler_data -= ctx->codec->filler_header_size;
-
-            err = ctx->codec->write_filler(avctx, filler_data,
-                                           hdr_dst, &data_size);
-            if (err < 0)
-                goto fail;
-
-            encode_info.dstBufferOffset += data_size;
-            encode_info.dstBufferRange  -= data_size;
-        }
-    }
-
-    vp->slices_offset = encode_info.dstBufferOffset;
-
-    /* Align buffer size to the nearest lower alignment requirement. */
-    encode_info.dstBufferRange -= size_align;
-    encode_info.dstBufferRange = FFALIGN(encode_info.dstBufferRange,
-                                         size_align);
-
-    /* Start command buffer recording */
-    exec = vp->exec = ff_vk_exec_get(&ctx->s, &ctx->enc_pool);
-    ff_vk_exec_start(&ctx->s, exec);
-    cmd_buf = exec->buf;
-
-    /* Output packet buffer */
-    err = ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->pkt_buf, 1, 1);
-    if (err < 0)
-        goto fail;
-
-    /* Source image */
-    err = ff_vk_exec_add_dep_frame(&ctx->s, exec, src,
-                                   VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                   VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR);
-    if (err < 0)
-        goto fail;
-
-    /* Source image layout conversion */
-    img_bar[nb_img_bar] = (VkImageMemoryBarrier2) {
-        .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
-        .pNext = NULL,
-        .srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-        .srcAccessMask = vkf->access[0],
-        .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR,
-        .dstAccessMask = VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR,
-        .oldLayout = vkf->layout[0],
-        .newLayout = VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR,
-        .srcQueueFamilyIndex = vkf->queue_family[0],
-        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .image = vkf->img[0],
-        .subresourceRange = (VkImageSubresourceRange) {
-            .aspectMask = vp->in.aspect,
-            .layerCount = 1,
-            .levelCount = 1,
-        },
-    };
-    ff_vk_exec_update_frame(&ctx->s, exec, src,
-                            &img_bar[nb_img_bar], &nb_img_bar);
-
-    if (!ctx->common.layered_dpb) {
-        /* Source image's ref slot.
-         * No need to do a layout conversion, since the frames which are allocated
-         * with a DPB usage are automatically converted. */
-        err = ff_vk_exec_add_dep_frame(&ctx->s, exec, base_pic->recon_image,
-                                       VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                       VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR);
-        if (err < 0)
-            return err;
-
-        /* All references */
-        for (int i = 0; i < MAX_REFERENCE_LIST_NUM; i++) {
-            for (int j = 0; j < base_pic->nb_refs[i]; j++) {
-                FFHWBaseEncodePicture *ref = base_pic->refs[i][j];
-                err = ff_vk_exec_add_dep_frame(&ctx->s, exec, ref->recon_image,
-                                               VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                               VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR);
-                if (err < 0)
-                    return err;
-            }
-        }
-    } else {
-        err = ff_vk_exec_add_dep_frame(&ctx->s, exec, ctx->common.layered_frame,
-                                       VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR,
-                                       VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR);
-        if (err < 0)
-            return err;
-    }
-
-    /* Change image layout */
-    vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
-            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-            .pImageMemoryBarriers = img_bar,
-            .imageMemoryBarrierCount = nb_img_bar,
-        });
-
-    /* Start, use parameters */
-    vk->CmdBeginVideoCodingKHR(cmd_buf, &encode_start);
-
-    /* Send control data */
-    if (!ctx->session_reset) {
-        vk->CmdControlVideoCodingKHR(cmd_buf, &encode_ctrl);
-        ctx->session_reset++;
-    }
-
-    /* Encode */
-    vk->CmdBeginQuery(cmd_buf, ctx->enc_pool.query_pool, exec->query_idx + 0, 0);
-    vk->CmdEncodeVideoKHR(cmd_buf, &encode_info);
-    vk->CmdEndQuery(cmd_buf, ctx->enc_pool.query_pool, exec->query_idx + 0);
-
-    /* End encoding */
-    vk->CmdEndVideoCodingKHR(cmd_buf, &encode_end);
-
-    /* End recording and submit for execution */
-    err = ff_vk_exec_submit(&ctx->s, vp->exec);
-    if (err < 0)
-        goto fail;
-
-    /* We don't need to keep the input image any longer, its already ref'd */
-    av_frame_free(&base_pic->input_image);
-
-    return 0;
-
-fail:
-    return err;
-}
-
-static void vulkan_encode_wait(AVCodecContext *avctx,
-                               FFHWBaseEncodePicture *base_pic)
-{
-    FFVulkanEncodeContext *ctx = avctx->priv_data;
-    FFVulkanEncodePicture *vp = base_pic->priv;
-
-    av_assert0(base_pic->encode_issued);
-
-    if (base_pic->encode_complete)
-        return;
-
-    ff_vk_exec_wait(&ctx->s, vp->exec);
-    base_pic->encode_complete = 1;
-}
-
-static int vulkan_encode_output(AVCodecContext *avctx,
-                                FFHWBaseEncodePicture *base_pic, AVPacket *pkt)
-{
-    VkResult ret;
-    FFVulkanEncodePicture *vp = base_pic->priv;
-    FFVulkanEncodeContext *ctx = avctx->priv_data;
-    FFVkBuffer *sd_buf = (FFVkBuffer *)vp->pkt_buf->data;
-    uint32_t *query_data;
-
-    vulkan_encode_wait(avctx, base_pic);
-
-    ret = ff_vk_exec_get_query(&ctx->s, vp->exec, (void **)&query_data, 0);
-    if (ret == VK_NOT_READY) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to perform query: %s!\n",
-               ff_vk_ret2str(ret));
-        return AVERROR(EINVAL);
-    }
-
-    if (ret != VK_NOT_READY && ret != VK_SUCCESS) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to perform query: %s!\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-
-    if (query_data[2] != VK_QUERY_RESULT_STATUS_COMPLETE_KHR) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to encode: %u\n", query_data[2]);
-        return AVERROR_EXTERNAL;
-    }
-
-    /* Invalidate buffer if needed */
-    if (!(sd_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
-        FFVulkanFunctions *vk = &ctx->s.vkfn;
-        VkMappedMemoryRange invalidate_buf;
-
-        int offs = vp->slices_offset;
-        /* If the non-coherent alignment is greater than the bitstream buffer
-         * offset's alignment, and the offs value is not aligned already,
-         * align it to the previous alignment point. */
-        if (ctx->s.props.properties.limits.nonCoherentAtomSize >
-            ctx->caps.minBitstreamBufferOffsetAlignment && offs &&
-            (FFALIGN(offs, ctx->s.props.properties.limits.nonCoherentAtomSize) != offs)) {
-            offs -= ctx->s.props.properties.limits.nonCoherentAtomSize;
-            offs = FFALIGN(FFMAX(offs, 0), ctx->s.props.properties.limits.nonCoherentAtomSize);
-        }
-
-        invalidate_buf = (VkMappedMemoryRange) {
-            .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
-            .memory = sd_buf->mem,
-            .offset = offs,
-            .size = VK_WHOLE_SIZE,
-        };
-
-        vk->FlushMappedMemoryRanges(ctx->s.hwctx->act_dev, 1, &invalidate_buf);
-    }
-
-    pkt->data = sd_buf->mapped_mem;
-    pkt->size = vp->slices_offset + /* base offset */
-                query_data[0]       /* secondary offset */ +
-                query_data[1]       /* size */;
-
-    /* Move reference */
-    pkt->buf = vp->pkt_buf;
-    vp->pkt_buf = NULL;
-
-    av_log(avctx, AV_LOG_DEBUG, "Frame %"PRId64"/%"PRId64 " encoded\n",
-           base_pic->display_order, base_pic->encode_order);
-
-    return ff_hw_base_encode_set_output_property(&ctx->base, avctx,
-                                                 base_pic, pkt,
-                                                 ctx->codec->flags & VK_ENC_FLAG_NO_DELAY);
-}
-
-static const FFHWEncodePictureOperation vulkan_base_encode_ops = {
-    .priv_size = sizeof(FFVulkanEncodePicture),
-    .init   = &vulkan_encode_init,
-    .issue  = &vulkan_encode_issue,
-    .output = &vulkan_encode_output,
-    .free   = &vulkan_encode_free,
-};
-
-int ff_vulkan_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
-{
-    FFVulkanEncodeContext *ctx = avctx->priv_data;
-    return ff_hw_base_encode_receive_packet(&ctx->base, avctx, pkt);
-}
-
-static int vulkan_encode_create_dpb(AVCodecContext *avctx, FFVulkanEncodeContext *ctx)
-{
-    int err;
-    FFHWBaseEncodeContext *base_ctx = &ctx->base;
-    AVVulkanFramesContext *hwfc;
-
-    enum AVPixelFormat dpb_format;
-    err = ff_hw_base_get_recon_format(base_ctx, NULL, &dpb_format);
-    if (err < 0)
-        return err;
-
-    base_ctx->recon_frames_ref = av_hwframe_ctx_alloc(base_ctx->device_ref);
-    if (!base_ctx->recon_frames_ref)
-        return AVERROR(ENOMEM);
-
-    base_ctx->recon_frames = (AVHWFramesContext *)base_ctx->recon_frames_ref->data;
-    hwfc = (AVVulkanFramesContext *)base_ctx->recon_frames->hwctx;
-
-    base_ctx->recon_frames->format    = AV_PIX_FMT_VULKAN;
-    base_ctx->recon_frames->sw_format = dpb_format;
-    base_ctx->recon_frames->width     = avctx->width;
-    base_ctx->recon_frames->height    = avctx->height;
-
-    hwfc->format[0]    = ctx->pic_format;
-    hwfc->create_pnext = &ctx->profile_list;
-    hwfc->tiling       = VK_IMAGE_TILING_OPTIMAL;
-    hwfc->usage        = VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR;
-
-    if (ctx->common.layered_dpb)
-        hwfc->nb_layers = ctx->caps.maxDpbSlots;
-
-    err = av_hwframe_ctx_init(base_ctx->recon_frames_ref);
-    if (err < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Failed to initialise DPB frame context: %s\n",
-               av_err2str(err));
-        return err;
-    }
-
-    if (ctx->common.layered_dpb) {
-        ctx->common.layered_frame = av_frame_alloc();
-        if (!ctx->common.layered_frame)
-            return AVERROR(ENOMEM);
-
-        err = av_hwframe_get_buffer(base_ctx->recon_frames_ref,
-                                    ctx->common.layered_frame, 0);
-        if (err < 0)
-            return AVERROR(ENOMEM);
-
-        err = ff_vk_create_view(&ctx->s, &ctx->common,
-                                &ctx->common.layered_view,
-                                &ctx->common.layered_aspect,
-                                (AVVkFrame *)ctx->common.layered_frame->data[0],
-                                hwfc->format[0], 1);
-        if (err < 0)
-            return err;
-
-        av_buffer_unref(&base_ctx->recon_frames_ref);
-    }
-
-    return 0;
-}
-
-static av_cold int init_rc(AVCodecContext *avctx, FFVulkanEncodeContext *ctx)
-{
-    if (ctx->opts.qp) {
-        ctx->explicit_qp = ctx->opts.qp;
-    } else if (avctx->global_quality > 0) {
-        if (avctx->flags & AV_CODEC_FLAG_QSCALE)
-            ctx->explicit_qp = avctx->global_quality / FF_QP2LAMBDA;
-        else
-            ctx->explicit_qp = avctx->global_quality;
-    }
-
-    if (ctx->opts.rc_mode == FF_VK_RC_MODE_AUTO) {
-        if (ctx->explicit_qp >= 0) {
-            ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
-        } else if (avctx->global_quality > 0) {
-            if (avctx->flags & AV_CODEC_FLAG_QSCALE)
-                ctx->explicit_qp = avctx->global_quality / FF_QP2LAMBDA;
-            else
-                ctx->explicit_qp = avctx->global_quality;
-            ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
-        } else if (avctx->bit_rate) {
-            if (ctx->enc_caps.rateControlModes & VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR)
-                ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR;
-            else if (ctx->enc_caps.rateControlModes & VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR)
-                ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR;
-            else
-                ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR;
-        } else {
-            ctx->explicit_qp = 18;
-            ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
-            av_log(avctx, AV_LOG_WARNING, "No rate control settings specified, using fixed QP = %i\n",
-                   ctx->explicit_qp);
-        }
-    } else if (ctx->opts.rc_mode != VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR &&
-               !avctx->bit_rate) {
-        av_log(avctx, AV_LOG_WARNING, "No bitrate specified!\n");
-        return AVERROR(EINVAL);
-    }
-
-    if (ctx->opts.rc_mode && !(ctx->enc_caps.rateControlModes & ctx->opts.rc_mode)) {
-        static const char *rc_modes[] = {
-            [VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR] = "default",
-            [VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR] = "cqp",
-            [VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR] = "cbr",
-            [VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR] = "vbr",
-        };
-        av_log(avctx, AV_LOG_ERROR, "Unsupported rate control mode %s, supported are:\n",
-               rc_modes[FFMIN(FF_ARRAY_ELEMS(rc_modes), ctx->opts.rc_mode)]);
-        av_log(avctx, AV_LOG_ERROR, "    %s\n", rc_modes[0]);
-        for (int i = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
-                 i <= VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR; i <<= 1) {
-            if (!(ctx->enc_caps.rateControlModes & i))
-                continue;
-            av_log(avctx, AV_LOG_ERROR, "    %s\n", rc_modes[i]);
-        }
-        return AVERROR(ENOTSUP);
-    }
-
-    return 0;
-}
-
-av_cold int ff_vulkan_write_global_header(AVCodecContext *avctx,
-                                          FFVulkanEncodeContext *ctx)
-{
-    int err;
-
-    /* Write extradata if needed */
-    if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
-        uint8_t data[4096];
-        size_t data_len = sizeof(data);
-
-        err = ctx->codec->write_sequence_headers(avctx, NULL, data, &data_len);
-        if (err < 0) {
-            av_log(avctx, AV_LOG_ERROR, "Failed to write sequence header "
-                   "for extradata: %d.\n", err);
-            return err;
-        } else {
-            avctx->extradata_size = data_len;
-            avctx->extradata = av_mallocz(avctx->extradata_size +
-                                          AV_INPUT_BUFFER_PADDING_SIZE);
-            if (!avctx->extradata) {
-                err = AVERROR(ENOMEM);
-                return err;
-            }
-            memcpy(avctx->extradata, data, avctx->extradata_size);
-        }
-    }
-
-    return 0;
-}
-
-av_cold int ff_vulkan_encode_init(AVCodecContext *avctx, FFVulkanEncodeContext *ctx,
-                                  const FFVulkanEncodeDescriptor *vk_desc,
-                                  const FFVulkanCodec *codec,
-                                  void *codec_caps, void *quality_pnext)
-{
-    int i, err;
-    VkResult ret;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-    FFVulkanContext *s = &ctx->s;
-    FFHWBaseEncodeContext *base_ctx = &ctx->base;
-
-    const AVPixFmtDescriptor *desc;
-
-    VkVideoFormatPropertiesKHR *ret_info;
-    uint32_t nb_out_fmts = 0;
-
-    VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR quality_info;
-
-    VkQueryPoolVideoEncodeFeedbackCreateInfoKHR query_create;
-
-    VkVideoSessionCreateInfoKHR session_create = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR,
-    };
-    VkPhysicalDeviceVideoFormatInfoKHR fmt_info = {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR,
-        .pNext = &ctx->profile_list,
-    };
-
-    if (!avctx->hw_frames_ctx) {
-        av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is "
-               "required to associate the encoding device.\n");
-        return AVERROR(EINVAL);
-    }
-
-    ctx->base.op = &vulkan_base_encode_ops;
-    ctx->codec = codec;
-
-    s->frames_ref = av_buffer_ref(avctx->hw_frames_ctx);
-    s->frames = (AVHWFramesContext *)s->frames_ref->data;
-    s->hwfc = s->frames->hwctx;
-
-    s->device = (AVHWDeviceContext *)s->frames->device_ref->data;
-    s->hwctx = s->device->hwctx;
-
-    desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt);
-    if (!desc)
-        return AVERROR(EINVAL);
-
-    s->extensions = ff_vk_extensions_to_mask(s->hwctx->enabled_dev_extensions,
-                                             s->hwctx->nb_enabled_dev_extensions);
-
-    if (!(s->extensions & FF_VK_EXT_VIDEO_ENCODE_QUEUE)) {
-        av_log(avctx, AV_LOG_ERROR, "Device does not support the %s extension!\n",
-               VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME);
-        return AVERROR(ENOSYS);
-    } else if (!(s->extensions & FF_VK_EXT_VIDEO_MAINTENANCE_1)) {
-        av_log(avctx, AV_LOG_ERROR, "Device does not support the %s extension!\n",
-               VK_KHR_VIDEO_MAINTENANCE_1_EXTENSION_NAME);
-        return AVERROR(ENOSYS);
-    } else if (!(s->extensions & vk_desc->encode_extension)) {
-        av_log(avctx, AV_LOG_ERROR, "Device does not support encoding %s!\n",
-               avcodec_get_name(avctx->codec_id));
-        return AVERROR(ENOSYS);
-    }
-
-    /* Load functions */
-    err = ff_vk_load_functions(s->device, vk, s->extensions, 1, 1);
-    if (err < 0)
-        return err;
-
-    /* Create queue context */
-    ctx->qf_enc = ff_vk_qf_find(s, VK_QUEUE_VIDEO_ENCODE_BIT_KHR, vk_desc->encode_op);
-    if (!ctx->qf_enc) {
-        av_log(avctx, AV_LOG_ERROR, "Encoding of %s is not supported by this device\n",
-               avcodec_get_name(avctx->codec_id));
-        return err;
-    }
-
-    /* Load all properties */
-    err = ff_vk_load_props(s);
-    if (err < 0)
-        return err;
-
-    /* Set tuning */
-    ctx->usage_info = (VkVideoEncodeUsageInfoKHR) {
-        .sType             = VK_STRUCTURE_TYPE_VIDEO_ENCODE_USAGE_INFO_KHR,
-        .videoUsageHints   = ctx->opts.usage,
-        .videoContentHints = ctx->opts.content,
-        .tuningMode        = ctx->opts.tune,
-    };
-
-    /* Load up the profile now, needed for caps and to create a query pool */
-    ctx->profile.sType               = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR;
-    ctx->profile.pNext               = &ctx->usage_info;
-    ctx->profile.videoCodecOperation = vk_desc->encode_op;
-    ctx->profile.chromaSubsampling   = ff_vk_subsampling_from_av_desc(desc);
-    ctx->profile.lumaBitDepth        = ff_vk_depth_from_av_depth(desc->comp[0].depth);
-    ctx->profile.chromaBitDepth      = ctx->profile.lumaBitDepth;
-
-    /* Setup a profile */
-    err = codec->init_profile(avctx, &ctx->profile, &ctx->usage_info);
-    if (err < 0)
-        return err;
-
-    ctx->profile_list.sType        = VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR;
-    ctx->profile_list.profileCount = 1;
-    ctx->profile_list.pProfiles    = &ctx->profile;
-
-    /* Get the capabilities of the encoder for the given profile */
-    ctx->enc_caps.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR;
-    ctx->enc_caps.pNext = codec_caps;
-    ctx->caps.sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR;
-    ctx->caps.pNext = &ctx->enc_caps;
-
-    ret = vk->GetPhysicalDeviceVideoCapabilitiesKHR(s->hwctx->phys_dev,
-                                                    &ctx->profile,
-                                                    &ctx->caps);
-    if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to initialize encoding: "
-               "%s profile \"%s\" not supported!\n",
-               avcodec_get_name(avctx->codec_id),
-               avcodec_profile_name(avctx->codec_id, avctx->profile));
-        return AVERROR(EINVAL);
-    } else if (ret == VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to initialize encoding: "
-               "format (%s) not supported!\n",
-               av_get_pix_fmt_name(avctx->sw_pix_fmt));
-        return AVERROR(EINVAL);
-    } else if (ret == VK_ERROR_FEATURE_NOT_PRESENT ||
-               ret == VK_ERROR_FORMAT_NOT_SUPPORTED) {
-        return AVERROR(EINVAL);
-    } else if (ret != VK_SUCCESS) {
-        return AVERROR_EXTERNAL;
-    }
-
-    err = init_rc(avctx, ctx);
-    if (err < 0)
-        return err;
-
-    /* Create command and query pool */
-    query_create = (VkQueryPoolVideoEncodeFeedbackCreateInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR,
-        .pNext = &ctx->profile,
-        .encodeFeedbackFlags = ctx->enc_caps.supportedEncodeFeedbackFlags &
-                               (~VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_HAS_OVERRIDES_BIT_KHR),
-    };
-    err = ff_vk_exec_pool_init(s, ctx->qf_enc, &ctx->enc_pool, base_ctx->async_depth,
-                               1, VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR, 0,
-                               &query_create);
-    if (err < 0)
-        return err;
-
-    if (ctx->opts.quality > ctx->enc_caps.maxQualityLevels) {
-        av_log(avctx, AV_LOG_ERROR, "Invalid quality level %i: allowed range is "
-                                    "0 to %i\n",
-               ctx->opts.quality, ctx->enc_caps.maxQualityLevels);
-        return AVERROR(EINVAL);
-    }
-
-    /* Get quality properties for the profile and quality level */
-    quality_info = (VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR,
-        .pVideoProfile = &ctx->profile,
-        .qualityLevel = ctx->opts.quality,
-    };
-    ctx->quality_props = (VkVideoEncodeQualityLevelPropertiesKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_PROPERTIES_KHR,
-        .pNext = quality_pnext,
-    };
-    ret = vk->GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR(s->hwctx->phys_dev,
-                                                                    &quality_info,
-                                                                    &ctx->quality_props);
-    if (ret != VK_SUCCESS)
-        return AVERROR_EXTERNAL;
-
-    /* Printout informative properties */
-    av_log(avctx, AV_LOG_VERBOSE, "Encoder capabilities for %s profile \"%s\":\n",
-           avcodec_get_name(avctx->codec_id),
-           avcodec_profile_name(avctx->codec_id, avctx->profile));
-    av_log(avctx, AV_LOG_VERBOSE, "    Width: from %i to %i\n",
-           ctx->caps.minCodedExtent.width, ctx->caps.maxCodedExtent.width);
-    av_log(avctx, AV_LOG_VERBOSE, "    Height: from %i to %i\n",
-           ctx->caps.minCodedExtent.height, ctx->caps.maxCodedExtent.height);
-    av_log(avctx, AV_LOG_VERBOSE, "    Width alignment: %i\n",
-           ctx->caps.pictureAccessGranularity.width);
-    av_log(avctx, AV_LOG_VERBOSE, "    Height alignment: %i\n",
-           ctx->caps.pictureAccessGranularity.height);
-    av_log(avctx, AV_LOG_VERBOSE, "    Bitstream offset alignment: %"PRIu64"\n",
-           ctx->caps.minBitstreamBufferOffsetAlignment);
-    av_log(avctx, AV_LOG_VERBOSE, "    Bitstream size alignment: %"PRIu64"\n",
-           ctx->caps.minBitstreamBufferSizeAlignment);
-    av_log(avctx, AV_LOG_VERBOSE, "    Maximum references: %u\n",
-           ctx->caps.maxDpbSlots);
-    av_log(avctx, AV_LOG_VERBOSE, "    Maximum active references: %u\n",
-           ctx->caps.maxActiveReferencePictures);
-    av_log(avctx, AV_LOG_VERBOSE, "    Codec header version: %i.%i.%i (driver), %i.%i.%i (compiled)\n",
-           CODEC_VER(ctx->caps.stdHeaderVersion.specVersion),
-           CODEC_VER(vk_desc->ext_props.specVersion));
-    av_log(avctx, AV_LOG_VERBOSE, "    Encoder max quality: %i\n",
-           ctx->enc_caps.maxQualityLevels);
-    av_log(avctx, AV_LOG_VERBOSE, "    Encoder image width alignment: %i\n",
-           ctx->enc_caps.encodeInputPictureGranularity.width);
-    av_log(avctx, AV_LOG_VERBOSE, "    Encoder image height alignment: %i\n",
-           ctx->enc_caps.encodeInputPictureGranularity.height);
-    av_log(avctx, AV_LOG_VERBOSE, "    Capability flags:%s%s%s\n",
-           ctx->caps.flags ? "" :
-               " none",
-           ctx->caps.flags & VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR ?
-               " protected" : "",
-           ctx->caps.flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR ?
-               " separate_references" : "");
-
-    /* Setup width/height alignment */
-    base_ctx->surface_width = avctx->coded_width =
-        FFALIGN(avctx->width, ctx->enc_caps.encodeInputPictureGranularity.width);
-    base_ctx->surface_height = avctx->coded_height =
-        FFALIGN(avctx->height, ctx->enc_caps.encodeInputPictureGranularity.height);
-
-    /* Setup slice width/height */
-    base_ctx->slice_block_width = ctx->enc_caps.encodeInputPictureGranularity.width;
-    base_ctx->slice_block_height = ctx->enc_caps.encodeInputPictureGranularity.height;
-
-    /* Check if encoding is possible with the given parameters */
-    if (avctx->coded_width  < ctx->caps.minCodedExtent.width   ||
-        avctx->coded_height < ctx->caps.minCodedExtent.height  ||
-        avctx->coded_width  > ctx->caps.maxCodedExtent.width   ||
-        avctx->coded_height > ctx->caps.maxCodedExtent.height) {
-        av_log(avctx, AV_LOG_ERROR, "Input of %ix%i too large for encoder limits: %ix%i max\n",
-               avctx->coded_width, avctx->coded_height,
-               ctx->caps.minCodedExtent.width, ctx->caps.minCodedExtent.height);
-        return AVERROR(EINVAL);
-    }
-
-    fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR;
-
-    ctx->common.layered_dpb = !(ctx->caps.flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR);
-
-    /* Get the supported image formats */
-    ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(s->hwctx->phys_dev,
-                                                        &fmt_info,
-                                                        &nb_out_fmts, NULL);
-    if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
-        (!nb_out_fmts && ret == VK_SUCCESS)) {
-        return AVERROR(EINVAL);
-    } else if (ret != VK_SUCCESS) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-
-    ret_info = av_mallocz(sizeof(*ret_info)*nb_out_fmts);
-    if (!ret_info)
-        return AVERROR(ENOMEM);
-
-    for (int i = 0; i < nb_out_fmts; i++)
-        ret_info[i].sType = VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR;
-
-    ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(s->hwctx->phys_dev,
-                                                        &fmt_info,
-                                                        &nb_out_fmts, ret_info);
-    if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
-        (!nb_out_fmts && ret == VK_SUCCESS)) {
-        av_free(ret_info);
-        return AVERROR(EINVAL);
-    } else if (ret != VK_SUCCESS) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
-               ff_vk_ret2str(ret));
-        av_free(ret_info);
-        return AVERROR_EXTERNAL;
-    }
-
-    av_log(avctx, AV_LOG_VERBOSE, "Supported input formats:\n");
-    for (i = 0; i < nb_out_fmts; i++)
-        av_log(avctx, AV_LOG_VERBOSE, "    %i: %i\n", i, ret_info[i].format);
-
-    for (i = 0; i < nb_out_fmts; i++) {
-        if (ff_vk_pix_fmt_from_vkfmt(ret_info[i].format) == s->frames->sw_format) {
-            ctx->pic_format = ret_info[i].format;
-            break;
-        }
-    }
-
-    av_free(ret_info);
-
-    if (i == nb_out_fmts) {
-        av_log(avctx, AV_LOG_ERROR, "Pixel format %s of input frames not supported!\n",
-               av_get_pix_fmt_name(s->frames->sw_format));
-        return AVERROR(EINVAL);
-    }
-
-    /* Create session */
-    session_create.pVideoProfile = &ctx->profile;
-    session_create.flags = 0x0;
-    session_create.queueFamilyIndex = ctx->qf_enc->idx;
-    session_create.maxCodedExtent = ctx->caps.maxCodedExtent;
-    session_create.maxDpbSlots = ctx->caps.maxDpbSlots;
-    session_create.maxActiveReferencePictures = ctx->caps.maxActiveReferencePictures;
-    session_create.pictureFormat = ctx->pic_format;
-    session_create.referencePictureFormat = session_create.pictureFormat;
-    session_create.pStdHeaderVersion = &vk_desc->ext_props;
-
-    err = ff_vk_video_common_init(avctx, s, &ctx->common, &session_create);
-    if (err < 0)
-        return err;
-
-    err = ff_hw_base_encode_init(avctx, &ctx->base);
-    if (err < 0)
-        return err;
-
-    err = vulkan_encode_create_dpb(avctx, ctx);
-    if (err < 0)
-        return err;
-
-    base_ctx->async_encode = 1;
-    base_ctx->encode_fifo = av_fifo_alloc2(base_ctx->async_depth,
-                                           sizeof(FFVulkanEncodePicture *), 0);
-    if (!base_ctx->encode_fifo)
-        return AVERROR(ENOMEM);
-
-    return 0;
-}
-
-int ff_vulkan_encode_create_session_params(AVCodecContext *avctx, FFVulkanEncodeContext *ctx,
-                                           void *codec_params_pnext)
-{
-    VkResult ret;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-    FFVulkanContext *s = &ctx->s;
-
-    VkVideoEncodeQualityLevelInfoKHR q_info;
-    VkVideoSessionParametersCreateInfoKHR session_params_create;
-
-    q_info = (VkVideoEncodeQualityLevelInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR,
-        .pNext = codec_params_pnext,
-        .qualityLevel = ctx->opts.quality,
-    };
-    session_params_create = (VkVideoSessionParametersCreateInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
-        .pNext = &q_info,
-        .videoSession = ctx->common.session,
-        .videoSessionParametersTemplate = VK_NULL_HANDLE,
-    };
-
-    /* Create session parameters */
-    ret = vk->CreateVideoSessionParametersKHR(s->hwctx->act_dev, &session_params_create,
-                                              s->hwctx->alloc, &ctx->session_params);
-    if (ret != VK_SUCCESS) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to create Vulkan video session parameters: %s!\n",
-               ff_vk_ret2str(ret));
-        return AVERROR_EXTERNAL;
-    }
-
-    return 0;
-}
-- 
2.49.1


From e99f7e3241aab66af067a3eb3dc8125d1f63c163 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:31:28 +0000
Subject: [PATCH 070/118] Changing vulkan file directory

---
 libavcodec/vulkan/vulkan_encode.c | 1054 +++++++++++++++++++++++++++++
 1 file changed, 1054 insertions(+)
 create mode 100644 libavcodec/vulkan/vulkan_encode.c

diff --git a/libavcodec/vulkan/vulkan_encode.c b/libavcodec/vulkan/vulkan_encode.c
new file mode 100644
index 0000000000..849504131c
--- /dev/null
+++ b/libavcodec/vulkan/vulkan_encode.c
@@ -0,0 +1,1054 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/mem.h"
+#include "libavutil/avassert.h"
+#include "vulkan_encode.h"
+#include "libavutil/config.h"
+
+#include "../../libavutil/vulkan/vulkan_loader.h"
+
+const AVCodecHWConfigInternal *const ff_vulkan_encode_hw_configs[] = {
+    HW_CONFIG_ENCODER_FRAMES(VULKAN, VULKAN),
+    NULL,
+};
+
+av_cold void ff_vulkan_encode_uninit(FFVulkanEncodeContext *ctx)
+{
+    FFVulkanContext *s = &ctx->s;
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    /* Wait on and free execution pool */
+    ff_vk_exec_pool_free(s, &ctx->enc_pool);
+
+    /* Destroy the session params */
+    if (ctx->session_params)
+        vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
+                                             ctx->session_params,
+                                             s->hwctx->alloc);
+
+    ff_hw_base_encode_close(&ctx->base);
+
+    av_buffer_pool_uninit(&ctx->buf_pool);
+
+    ff_vk_video_common_uninit(s, &ctx->common);
+
+    ff_vk_uninit(s);
+}
+
+static int vulkan_encode_init(AVCodecContext *avctx, FFHWBaseEncodePicture *pic)
+{
+    int err;
+    FFVulkanEncodeContext *ctx = avctx->priv_data;
+    FFVulkanEncodePicture *vp = pic->priv;
+
+    AVFrame *f = pic->input_image;
+    AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
+    AVVulkanFramesContext *vkfc = hwfc->hwctx;
+    AVVkFrame *vkf = (AVVkFrame *)f->data[0];
+
+    if (ctx->codec->picture_priv_data_size > 0) {
+        pic->codec_priv = av_mallocz(ctx->codec->picture_priv_data_size);
+        if (!pic->codec_priv)
+            return AVERROR(ENOMEM);
+    }
+
+    /* Input image view */
+    err = ff_vk_create_view(&ctx->s, &ctx->common,
+                            &vp->in.view, &vp->in.aspect,
+                            vkf, vkfc->format[0], 0);
+    if (err < 0)
+        return err;
+
+    /* Reference view */
+    if (!ctx->common.layered_dpb) {
+        AVFrame *rf = pic->recon_image;
+        AVVkFrame *rvkf = (AVVkFrame *)rf->data[0];
+        err = ff_vk_create_view(&ctx->s, &ctx->common,
+                                &vp->dpb.view, &vp->dpb.aspect,
+                                rvkf, ctx->pic_format, 1);
+        if (err < 0)
+            return err;
+    } else {
+        vp->dpb.view = ctx->common.layered_view;
+        vp->dpb.aspect = ctx->common.layered_aspect;
+    }
+
+    return 0;
+}
+
+static int vulkan_encode_free(AVCodecContext *avctx, FFHWBaseEncodePicture *pic)
+{
+    FFVulkanEncodeContext *ctx = avctx->priv_data;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+
+    FFVulkanEncodePicture *vp = pic->priv;
+
+    if (vp->in.view)
+        vk->DestroyImageView(ctx->s.hwctx->act_dev, vp->in.view,
+                             ctx->s.hwctx->alloc);
+
+    if (!ctx->common.layered_dpb && vp->dpb.view)
+        vk->DestroyImageView(ctx->s.hwctx->act_dev, vp->dpb.view,
+                             ctx->s.hwctx->alloc);
+
+    ctx->slots[vp->dpb_slot.slotIndex] = NULL;
+
+    return 0;
+}
+
+static int init_pic_rc(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
+                       VkVideoEncodeRateControlInfoKHR *rc_info,
+                       VkVideoEncodeRateControlLayerInfoKHR *rc_layer /* Goes in ^ */)
+{
+    FFVulkanEncodeContext *ctx = avctx->priv_data;
+
+    *rc_info = (VkVideoEncodeRateControlInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR,
+        .rateControlMode = ctx->opts.rc_mode,
+    };
+
+    if (ctx->opts.rc_mode > VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
+        *rc_layer = (VkVideoEncodeRateControlLayerInfoKHR) {
+            .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_LAYER_INFO_KHR,
+            .averageBitrate = avctx->bit_rate,
+            .maxBitrate = avctx->rc_max_rate ? avctx->rc_max_rate : avctx->bit_rate,
+            .frameRateNumerator = avctx->framerate.num,
+            .frameRateDenominator = avctx->framerate.den,
+        };
+        rc_info->layerCount++;
+        rc_info->pLayers = rc_layer;
+    }
+
+    return ctx->codec->init_pic_rc(avctx, pic, rc_info, rc_layer);
+}
+
+static int vulkan_encode_issue(AVCodecContext *avctx,
+                               FFHWBaseEncodePicture *base_pic)
+{
+    FFVulkanEncodeContext *ctx = avctx->priv_data;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+
+    const size_t size_align = ctx->caps.minBitstreamBufferSizeAlignment;
+
+    FFVulkanEncodePicture *vp = base_pic->priv;
+    AVFrame *src = (AVFrame *)base_pic->input_image;
+    AVVkFrame *vkf = (AVVkFrame *)src->data[0];
+
+    int err, max_pkt_size;
+
+    FFVkBuffer *sd_buf;
+
+    int slot_index = -1;
+    FFVkExecContext *exec;
+    VkCommandBuffer cmd_buf;
+    VkImageMemoryBarrier2 img_bar[37];
+    int nb_img_bar = 0;
+
+    /* Coding start/end */
+    VkVideoBeginCodingInfoKHR encode_start;
+    VkVideoEndCodingInfoKHR encode_end = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR,
+    };
+
+    VkVideoEncodeRateControlLayerInfoKHR rc_layer;
+    VkVideoEncodeRateControlInfoKHR rc_info;
+    VkVideoEncodeQualityLevelInfoKHR q_info;
+    VkVideoCodingControlInfoKHR encode_ctrl;
+
+    VkVideoReferenceSlotInfoKHR ref_slot[37];
+    VkVideoEncodeInfoKHR encode_info;
+
+    /* Create packet data buffer */
+    max_pkt_size = FFALIGN(3 * ctx->base.surface_width * ctx->base.surface_height + (1 << 16),
+                           ctx->caps.minBitstreamBufferSizeAlignment);
+
+    err = ff_vk_get_pooled_buffer(&ctx->s, &ctx->buf_pool, &vp->pkt_buf,
+                                  VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR,
+                                  &ctx->profile_list, max_pkt_size,
+                                  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+                                  VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
+    if (err < 0)
+        return err;
+
+    sd_buf = (FFVkBuffer *)vp->pkt_buf->data;
+
+    /* Setup rate control */
+    err = init_pic_rc(avctx, base_pic, &rc_info, &rc_layer);
+    if (err < 0)
+        return err;
+
+    q_info = (VkVideoEncodeQualityLevelInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR,
+        .pNext = &rc_info,
+        .qualityLevel = ctx->opts.quality,
+    };
+    encode_ctrl = (VkVideoCodingControlInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR,
+        .pNext = &q_info,
+        .flags = VK_VIDEO_CODING_CONTROL_ENCODE_QUALITY_LEVEL_BIT_KHR |
+                 VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_BIT_KHR |
+                 VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR,
+    };
+
+    for (int i = 0; i < ctx->caps.maxDpbSlots; i++) {
+        if (ctx->slots[i] == NULL) {
+            slot_index = i;
+            ctx->slots[i] = base_pic;
+            break;
+        }
+    }
+    av_assert0(slot_index >= 0);
+
+    /* Current picture's ref slot */
+    vp->dpb_res = (VkVideoPictureResourceInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
+        .pNext = NULL,
+        .codedOffset = { 0 },
+        .codedExtent = (VkExtent2D){ avctx->width, avctx->height },
+        .baseArrayLayer = ctx->common.layered_dpb ? slot_index : 0,
+        .imageViewBinding = vp->dpb.view,
+    };
+
+    vp->dpb_slot = (VkVideoReferenceSlotInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
+        .pNext = NULL,  // Set later
+        .slotIndex = slot_index,
+        .pPictureResource = &vp->dpb_res,
+    };
+
+    encode_info = (VkVideoEncodeInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR,
+        .pNext = NULL, // Set later
+        .flags = 0x0,
+        .srcPictureResource = (VkVideoPictureResourceInfoKHR) {
+            .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
+            .pNext = NULL,
+            .codedOffset = { 0, 0 },
+            .codedExtent = (VkExtent2D){ base_pic->input_image->width,
+                                         base_pic->input_image->height },
+            .baseArrayLayer = 0,
+            .imageViewBinding = vp->in.view,
+        },
+        .pSetupReferenceSlot = &vp->dpb_slot,
+        .referenceSlotCount = 0,
+        .pReferenceSlots = ref_slot,
+        .dstBuffer = sd_buf->buf,
+        .dstBufferOffset = 0,
+        .dstBufferRange = sd_buf->size,
+        .precedingExternallyEncodedBytes = 0,
+    };
+
+    for (int i = 0; i < MAX_REFERENCE_LIST_NUM; i++) {
+        for (int j = 0; j < base_pic->nb_refs[i]; j++) {
+            FFHWBaseEncodePicture *ref = base_pic->refs[i][j];
+            FFVulkanEncodePicture *rvp = ref->priv;
+            ref_slot[encode_info.referenceSlotCount++] = rvp->dpb_slot;
+        }
+    }
+
+    /* Calling vkCmdBeginVideoCodingKHR requires to declare all references
+     * being enabled upfront, including the current frame's output ref. */
+    ref_slot[encode_info.referenceSlotCount] = vp->dpb_slot;
+    ref_slot[encode_info.referenceSlotCount].slotIndex = -1;
+
+    /* Setup picture parameters */
+    err = ctx->codec->init_pic_params(avctx, base_pic,
+                                      &encode_info);
+    if (err < 0)
+        return err;
+
+    encode_start = (VkVideoBeginCodingInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
+        .pNext = !base_pic->force_idr ? &rc_info : NULL,
+        .videoSession = ctx->common.session,
+        .videoSessionParameters = ctx->session_params,
+        .referenceSlotCount = encode_info.referenceSlotCount + 1,
+        .pReferenceSlots = ref_slot,
+    };
+
+    /* Write header */
+    if (base_pic->type == FF_HW_PICTURE_TYPE_IDR) {
+        uint8_t *hdr_dst = sd_buf->mapped_mem + encode_info.dstBufferOffset;
+        size_t data_size = encode_info.dstBufferRange;
+        err = ctx->codec->write_sequence_headers(avctx, base_pic, hdr_dst, &data_size);
+        if (err < 0)
+            goto fail;
+        encode_info.dstBufferOffset += data_size;
+        encode_info.dstBufferRange  -= data_size;
+    }
+
+    /* Write extra units */
+    if (ctx->codec->write_extra_headers) {
+        uint8_t *hdr_dst = sd_buf->mapped_mem + encode_info.dstBufferOffset;
+        size_t data_size = encode_info.dstBufferRange;
+        err = ctx->codec->write_extra_headers(avctx, base_pic, hdr_dst, &data_size);
+        if (err < 0)
+            goto fail;
+        encode_info.dstBufferOffset += data_size;
+        encode_info.dstBufferRange  -= data_size;
+    }
+
+    /* Align buffer offset to the required value with filler units */
+    if (ctx->codec->write_filler) {
+        uint8_t *hdr_dst = sd_buf->mapped_mem + encode_info.dstBufferOffset;
+        size_t data_size = encode_info.dstBufferRange;
+
+        uint32_t offset = encode_info.dstBufferOffset;
+        size_t offset_align = ctx->caps.minBitstreamBufferOffsetAlignment;
+
+        uint32_t filler_data = FFALIGN(offset, offset_align) - offset;
+
+        if (filler_data) {
+            while (filler_data < ctx->codec->filler_header_size)
+                filler_data += offset_align;
+
+            filler_data -= ctx->codec->filler_header_size;
+
+            err = ctx->codec->write_filler(avctx, filler_data,
+                                           hdr_dst, &data_size);
+            if (err < 0)
+                goto fail;
+
+            encode_info.dstBufferOffset += data_size;
+            encode_info.dstBufferRange  -= data_size;
+        }
+    }
+
+    vp->slices_offset = encode_info.dstBufferOffset;
+
+    /* Align buffer size to the nearest lower alignment requirement. */
+    encode_info.dstBufferRange -= size_align;
+    encode_info.dstBufferRange = FFALIGN(encode_info.dstBufferRange,
+                                         size_align);
+
+    /* Start command buffer recording */
+    exec = vp->exec = ff_vk_exec_get(&ctx->s, &ctx->enc_pool);
+    ff_vk_exec_start(&ctx->s, exec);
+    cmd_buf = exec->buf;
+
+    /* Output packet buffer */
+    err = ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->pkt_buf, 1, 1);
+    if (err < 0)
+        goto fail;
+
+    /* Source image */
+    err = ff_vk_exec_add_dep_frame(&ctx->s, exec, src,
+                                   VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                   VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR);
+    if (err < 0)
+        goto fail;
+
+    /* Source image layout conversion */
+    img_bar[nb_img_bar] = (VkImageMemoryBarrier2) {
+        .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
+        .pNext = NULL,
+        .srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+        .srcAccessMask = vkf->access[0],
+        .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR,
+        .dstAccessMask = VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR,
+        .oldLayout = vkf->layout[0],
+        .newLayout = VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR,
+        .srcQueueFamilyIndex = vkf->queue_family[0],
+        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .image = vkf->img[0],
+        .subresourceRange = (VkImageSubresourceRange) {
+            .aspectMask = vp->in.aspect,
+            .layerCount = 1,
+            .levelCount = 1,
+        },
+    };
+    ff_vk_exec_update_frame(&ctx->s, exec, src,
+                            &img_bar[nb_img_bar], &nb_img_bar);
+
+    if (!ctx->common.layered_dpb) {
+        /* Source image's ref slot.
+         * No need to do a layout conversion, since the frames which are allocated
+         * with a DPB usage are automatically converted. */
+        err = ff_vk_exec_add_dep_frame(&ctx->s, exec, base_pic->recon_image,
+                                       VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                       VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR);
+        if (err < 0)
+            return err;
+
+        /* All references */
+        for (int i = 0; i < MAX_REFERENCE_LIST_NUM; i++) {
+            for (int j = 0; j < base_pic->nb_refs[i]; j++) {
+                FFHWBaseEncodePicture *ref = base_pic->refs[i][j];
+                err = ff_vk_exec_add_dep_frame(&ctx->s, exec, ref->recon_image,
+                                               VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                               VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR);
+                if (err < 0)
+                    return err;
+            }
+        }
+    } else {
+        err = ff_vk_exec_add_dep_frame(&ctx->s, exec, ctx->common.layered_frame,
+                                       VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR,
+                                       VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR);
+        if (err < 0)
+            return err;
+    }
+
+    /* Change image layout */
+    vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
+            .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+            .pImageMemoryBarriers = img_bar,
+            .imageMemoryBarrierCount = nb_img_bar,
+        });
+
+    /* Start, use parameters */
+    vk->CmdBeginVideoCodingKHR(cmd_buf, &encode_start);
+
+    /* Send control data */
+    if (!ctx->session_reset) {
+        vk->CmdControlVideoCodingKHR(cmd_buf, &encode_ctrl);
+        ctx->session_reset++;
+    }
+
+    /* Encode */
+    vk->CmdBeginQuery(cmd_buf, ctx->enc_pool.query_pool, exec->query_idx + 0, 0);
+    vk->CmdEncodeVideoKHR(cmd_buf, &encode_info);
+    vk->CmdEndQuery(cmd_buf, ctx->enc_pool.query_pool, exec->query_idx + 0);
+
+    /* End encoding */
+    vk->CmdEndVideoCodingKHR(cmd_buf, &encode_end);
+
+    /* End recording and submit for execution */
+    err = ff_vk_exec_submit(&ctx->s, vp->exec);
+    if (err < 0)
+        goto fail;
+
+    /* We don't need to keep the input image any longer, its already ref'd */
+    av_frame_free(&base_pic->input_image);
+
+    return 0;
+
+fail:
+    return err;
+}
+
+static void vulkan_encode_wait(AVCodecContext *avctx,
+                               FFHWBaseEncodePicture *base_pic)
+{
+    FFVulkanEncodeContext *ctx = avctx->priv_data;
+    FFVulkanEncodePicture *vp = base_pic->priv;
+
+    av_assert0(base_pic->encode_issued);
+
+    if (base_pic->encode_complete)
+        return;
+
+    ff_vk_exec_wait(&ctx->s, vp->exec);
+    base_pic->encode_complete = 1;
+}
+
+static int vulkan_encode_output(AVCodecContext *avctx,
+                                FFHWBaseEncodePicture *base_pic, AVPacket *pkt)
+{
+    VkResult ret;
+    FFVulkanEncodePicture *vp = base_pic->priv;
+    FFVulkanEncodeContext *ctx = avctx->priv_data;
+    FFVkBuffer *sd_buf = (FFVkBuffer *)vp->pkt_buf->data;
+    uint32_t *query_data;
+
+    vulkan_encode_wait(avctx, base_pic);
+
+    ret = ff_vk_exec_get_query(&ctx->s, vp->exec, (void **)&query_data, 0);
+    if (ret == VK_NOT_READY) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to perform query: %s!\n",
+               ff_vk_ret2str(ret));
+        return AVERROR(EINVAL);
+    }
+
+    if (ret != VK_NOT_READY && ret != VK_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to perform query: %s!\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+
+    if (query_data[2] != VK_QUERY_RESULT_STATUS_COMPLETE_KHR) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to encode: %u\n", query_data[2]);
+        return AVERROR_EXTERNAL;
+    }
+
+    /* Invalidate buffer if needed */
+    if (!(sd_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
+        FFVulkanFunctions *vk = &ctx->s.vkfn;
+        VkMappedMemoryRange invalidate_buf;
+
+        int offs = vp->slices_offset;
+        /* If the non-coherent alignment is greater than the bitstream buffer
+         * offset's alignment, and the offs value is not aligned already,
+         * align it to the previous alignment point. */
+        if (ctx->s.props.properties.limits.nonCoherentAtomSize >
+            ctx->caps.minBitstreamBufferOffsetAlignment && offs &&
+            (FFALIGN(offs, ctx->s.props.properties.limits.nonCoherentAtomSize) != offs)) {
+            offs -= ctx->s.props.properties.limits.nonCoherentAtomSize;
+            offs = FFALIGN(FFMAX(offs, 0), ctx->s.props.properties.limits.nonCoherentAtomSize);
+        }
+
+        invalidate_buf = (VkMappedMemoryRange) {
+            .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+            .memory = sd_buf->mem,
+            .offset = offs,
+            .size = VK_WHOLE_SIZE,
+        };
+
+        vk->FlushMappedMemoryRanges(ctx->s.hwctx->act_dev, 1, &invalidate_buf);
+    }
+
+    pkt->data = sd_buf->mapped_mem;
+    pkt->size = vp->slices_offset + /* base offset */
+                query_data[0]       /* secondary offset */ +
+                query_data[1]       /* size */;
+
+    /* Move reference */
+    pkt->buf = vp->pkt_buf;
+    vp->pkt_buf = NULL;
+
+    av_log(avctx, AV_LOG_DEBUG, "Frame %"PRId64"/%"PRId64 " encoded\n",
+           base_pic->display_order, base_pic->encode_order);
+
+    return ff_hw_base_encode_set_output_property(&ctx->base, avctx,
+                                                 base_pic, pkt,
+                                                 ctx->codec->flags & VK_ENC_FLAG_NO_DELAY);
+}
+
+static const FFHWEncodePictureOperation vulkan_base_encode_ops = {
+    .priv_size = sizeof(FFVulkanEncodePicture),
+    .init   = &vulkan_encode_init,
+    .issue  = &vulkan_encode_issue,
+    .output = &vulkan_encode_output,
+    .free   = &vulkan_encode_free,
+};
+
+int ff_vulkan_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
+{
+    FFVulkanEncodeContext *ctx = avctx->priv_data;
+    return ff_hw_base_encode_receive_packet(&ctx->base, avctx, pkt);
+}
+
+static int vulkan_encode_create_dpb(AVCodecContext *avctx, FFVulkanEncodeContext *ctx)
+{
+    int err;
+    FFHWBaseEncodeContext *base_ctx = &ctx->base;
+    AVVulkanFramesContext *hwfc;
+
+    enum AVPixelFormat dpb_format;
+    err = ff_hw_base_get_recon_format(base_ctx, NULL, &dpb_format);
+    if (err < 0)
+        return err;
+
+    base_ctx->recon_frames_ref = av_hwframe_ctx_alloc(base_ctx->device_ref);
+    if (!base_ctx->recon_frames_ref)
+        return AVERROR(ENOMEM);
+
+    base_ctx->recon_frames = (AVHWFramesContext *)base_ctx->recon_frames_ref->data;
+    hwfc = (AVVulkanFramesContext *)base_ctx->recon_frames->hwctx;
+
+    base_ctx->recon_frames->format    = AV_PIX_FMT_VULKAN;
+    base_ctx->recon_frames->sw_format = dpb_format;
+    base_ctx->recon_frames->width     = avctx->width;
+    base_ctx->recon_frames->height    = avctx->height;
+
+    hwfc->format[0]    = ctx->pic_format;
+    hwfc->create_pnext = &ctx->profile_list;
+    hwfc->tiling       = VK_IMAGE_TILING_OPTIMAL;
+    hwfc->usage        = VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR;
+
+    if (ctx->common.layered_dpb)
+        hwfc->nb_layers = ctx->caps.maxDpbSlots;
+
+    err = av_hwframe_ctx_init(base_ctx->recon_frames_ref);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to initialise DPB frame context: %s\n",
+               av_err2str(err));
+        return err;
+    }
+
+    if (ctx->common.layered_dpb) {
+        ctx->common.layered_frame = av_frame_alloc();
+        if (!ctx->common.layered_frame)
+            return AVERROR(ENOMEM);
+
+        err = av_hwframe_get_buffer(base_ctx->recon_frames_ref,
+                                    ctx->common.layered_frame, 0);
+        if (err < 0)
+            return AVERROR(ENOMEM);
+
+        err = ff_vk_create_view(&ctx->s, &ctx->common,
+                                &ctx->common.layered_view,
+                                &ctx->common.layered_aspect,
+                                (AVVkFrame *)ctx->common.layered_frame->data[0],
+                                hwfc->format[0], 1);
+        if (err < 0)
+            return err;
+
+        av_buffer_unref(&base_ctx->recon_frames_ref);
+    }
+
+    return 0;
+}
+
+static av_cold int init_rc(AVCodecContext *avctx, FFVulkanEncodeContext *ctx)
+{
+    if (ctx->opts.qp) {
+        ctx->explicit_qp = ctx->opts.qp;
+    } else if (avctx->global_quality > 0) {
+        if (avctx->flags & AV_CODEC_FLAG_QSCALE)
+            ctx->explicit_qp = avctx->global_quality / FF_QP2LAMBDA;
+        else
+            ctx->explicit_qp = avctx->global_quality;
+    }
+
+    if (ctx->opts.rc_mode == FF_VK_RC_MODE_AUTO) {
+        if (ctx->explicit_qp >= 0) {
+            ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
+        } else if (avctx->global_quality > 0) {
+            if (avctx->flags & AV_CODEC_FLAG_QSCALE)
+                ctx->explicit_qp = avctx->global_quality / FF_QP2LAMBDA;
+            else
+                ctx->explicit_qp = avctx->global_quality;
+            ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
+        } else if (avctx->bit_rate) {
+            if (ctx->enc_caps.rateControlModes & VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR)
+                ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR;
+            else if (ctx->enc_caps.rateControlModes & VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR)
+                ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR;
+            else
+                ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR;
+        } else {
+            ctx->explicit_qp = 18;
+            ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
+            av_log(avctx, AV_LOG_WARNING, "No rate control settings specified, using fixed QP = %i\n",
+                   ctx->explicit_qp);
+        }
+    } else if (ctx->opts.rc_mode != VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR &&
+               !avctx->bit_rate) {
+        av_log(avctx, AV_LOG_WARNING, "No bitrate specified!\n");
+        return AVERROR(EINVAL);
+    }
+
+    if (ctx->opts.rc_mode && !(ctx->enc_caps.rateControlModes & ctx->opts.rc_mode)) {
+        static const char *rc_modes[] = {
+            [VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR] = "default",
+            [VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR] = "cqp",
+            [VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR] = "cbr",
+            [VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR] = "vbr",
+        };
+        av_log(avctx, AV_LOG_ERROR, "Unsupported rate control mode %s, supported are:\n",
+               rc_modes[FFMIN(FF_ARRAY_ELEMS(rc_modes), ctx->opts.rc_mode)]);
+        av_log(avctx, AV_LOG_ERROR, "    %s\n", rc_modes[0]);
+        for (int i = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
+                 i <= VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR; i <<= 1) {
+            if (!(ctx->enc_caps.rateControlModes & i))
+                continue;
+            av_log(avctx, AV_LOG_ERROR, "    %s\n", rc_modes[i]);
+        }
+        return AVERROR(ENOTSUP);
+    }
+
+    return 0;
+}
+
+av_cold int ff_vulkan_write_global_header(AVCodecContext *avctx,
+                                          FFVulkanEncodeContext *ctx)
+{
+    int err;
+
+    /* Write extradata if needed */
+    if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
+        uint8_t data[4096];
+        size_t data_len = sizeof(data);
+
+        err = ctx->codec->write_sequence_headers(avctx, NULL, data, &data_len);
+        if (err < 0) {
+            av_log(avctx, AV_LOG_ERROR, "Failed to write sequence header "
+                   "for extradata: %d.\n", err);
+            return err;
+        } else {
+            avctx->extradata_size = data_len;
+            avctx->extradata = av_mallocz(avctx->extradata_size +
+                                          AV_INPUT_BUFFER_PADDING_SIZE);
+            if (!avctx->extradata) {
+                err = AVERROR(ENOMEM);
+                return err;
+            }
+            memcpy(avctx->extradata, data, avctx->extradata_size);
+        }
+    }
+
+    return 0;
+}
+
+av_cold int ff_vulkan_encode_init(AVCodecContext *avctx, FFVulkanEncodeContext *ctx,
+                                  const FFVulkanEncodeDescriptor *vk_desc,
+                                  const FFVulkanCodec *codec,
+                                  void *codec_caps, void *quality_pnext)
+{
+    int i, err;
+    VkResult ret;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+    FFVulkanContext *s = &ctx->s;
+    FFHWBaseEncodeContext *base_ctx = &ctx->base;
+
+    const AVPixFmtDescriptor *desc;
+
+    VkVideoFormatPropertiesKHR *ret_info;
+    uint32_t nb_out_fmts = 0;
+
+    VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR quality_info;
+
+    VkQueryPoolVideoEncodeFeedbackCreateInfoKHR query_create;
+
+    VkVideoSessionCreateInfoKHR session_create = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR,
+    };
+    VkPhysicalDeviceVideoFormatInfoKHR fmt_info = {
+        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR,
+        .pNext = &ctx->profile_list,
+    };
+
+    if (!avctx->hw_frames_ctx) {
+        av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is "
+               "required to associate the encoding device.\n");
+        return AVERROR(EINVAL);
+    }
+
+    ctx->base.op = &vulkan_base_encode_ops;
+    ctx->codec = codec;
+
+    s->frames_ref = av_buffer_ref(avctx->hw_frames_ctx);
+    s->frames = (AVHWFramesContext *)s->frames_ref->data;
+    s->hwfc = s->frames->hwctx;
+
+    s->device = (AVHWDeviceContext *)s->frames->device_ref->data;
+    s->hwctx = s->device->hwctx;
+
+    desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt);
+    if (!desc)
+        return AVERROR(EINVAL);
+
+    s->extensions = ff_vk_extensions_to_mask(s->hwctx->enabled_dev_extensions,
+                                             s->hwctx->nb_enabled_dev_extensions);
+
+    if (!(s->extensions & FF_VK_EXT_VIDEO_ENCODE_QUEUE)) {
+        av_log(avctx, AV_LOG_ERROR, "Device does not support the %s extension!\n",
+               VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME);
+        return AVERROR(ENOSYS);
+    } else if (!(s->extensions & FF_VK_EXT_VIDEO_MAINTENANCE_1)) {
+        av_log(avctx, AV_LOG_ERROR, "Device does not support the %s extension!\n",
+               VK_KHR_VIDEO_MAINTENANCE_1_EXTENSION_NAME);
+        return AVERROR(ENOSYS);
+    } else if (!(s->extensions & vk_desc->encode_extension)) {
+        av_log(avctx, AV_LOG_ERROR, "Device does not support encoding %s!\n",
+               avcodec_get_name(avctx->codec_id));
+        return AVERROR(ENOSYS);
+    }
+
+    /* Load functions */
+    err = ff_vk_load_functions(s->device, vk, s->extensions, 1, 1);
+    if (err < 0)
+        return err;
+
+    /* Create queue context */
+    ctx->qf_enc = ff_vk_qf_find(s, VK_QUEUE_VIDEO_ENCODE_BIT_KHR, vk_desc->encode_op);
+    if (!ctx->qf_enc) {
+        av_log(avctx, AV_LOG_ERROR, "Encoding of %s is not supported by this device\n",
+               avcodec_get_name(avctx->codec_id));
+        return err;
+    }
+
+    /* Load all properties */
+    err = ff_vk_load_props(s);
+    if (err < 0)
+        return err;
+
+    /* Set tuning */
+    ctx->usage_info = (VkVideoEncodeUsageInfoKHR) {
+        .sType             = VK_STRUCTURE_TYPE_VIDEO_ENCODE_USAGE_INFO_KHR,
+        .videoUsageHints   = ctx->opts.usage,
+        .videoContentHints = ctx->opts.content,
+        .tuningMode        = ctx->opts.tune,
+    };
+
+    /* Load up the profile now, needed for caps and to create a query pool */
+    ctx->profile.sType               = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR;
+    ctx->profile.pNext               = &ctx->usage_info;
+    ctx->profile.videoCodecOperation = vk_desc->encode_op;
+    ctx->profile.chromaSubsampling   = ff_vk_subsampling_from_av_desc(desc);
+    ctx->profile.lumaBitDepth        = ff_vk_depth_from_av_depth(desc->comp[0].depth);
+    ctx->profile.chromaBitDepth      = ctx->profile.lumaBitDepth;
+
+    /* Setup a profile */
+    err = codec->init_profile(avctx, &ctx->profile, &ctx->usage_info);
+    if (err < 0)
+        return err;
+
+    ctx->profile_list.sType        = VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR;
+    ctx->profile_list.profileCount = 1;
+    ctx->profile_list.pProfiles    = &ctx->profile;
+
+    /* Get the capabilities of the encoder for the given profile */
+    ctx->enc_caps.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR;
+    ctx->enc_caps.pNext = codec_caps;
+    ctx->caps.sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR;
+    ctx->caps.pNext = &ctx->enc_caps;
+
+    ret = vk->GetPhysicalDeviceVideoCapabilitiesKHR(s->hwctx->phys_dev,
+                                                    &ctx->profile,
+                                                    &ctx->caps);
+    if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to initialize encoding: "
+               "%s profile \"%s\" not supported!\n",
+               avcodec_get_name(avctx->codec_id),
+               avcodec_profile_name(avctx->codec_id, avctx->profile));
+        return AVERROR(EINVAL);
+    } else if (ret == VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to initialize encoding: "
+               "format (%s) not supported!\n",
+               av_get_pix_fmt_name(avctx->sw_pix_fmt));
+        return AVERROR(EINVAL);
+    } else if (ret == VK_ERROR_FEATURE_NOT_PRESENT ||
+               ret == VK_ERROR_FORMAT_NOT_SUPPORTED) {
+        return AVERROR(EINVAL);
+    } else if (ret != VK_SUCCESS) {
+        return AVERROR_EXTERNAL;
+    }
+
+    err = init_rc(avctx, ctx);
+    if (err < 0)
+        return err;
+
+    /* Create command and query pool */
+    query_create = (VkQueryPoolVideoEncodeFeedbackCreateInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR,
+        .pNext = &ctx->profile,
+        .encodeFeedbackFlags = ctx->enc_caps.supportedEncodeFeedbackFlags &
+                               (~VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_HAS_OVERRIDES_BIT_KHR),
+    };
+    err = ff_vk_exec_pool_init(s, ctx->qf_enc, &ctx->enc_pool, base_ctx->async_depth,
+                               1, VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR, 0,
+                               &query_create);
+    if (err < 0)
+        return err;
+
+    if (ctx->opts.quality > ctx->enc_caps.maxQualityLevels) {
+        av_log(avctx, AV_LOG_ERROR, "Invalid quality level %i: allowed range is "
+                                    "0 to %i\n",
+               ctx->opts.quality, ctx->enc_caps.maxQualityLevels);
+        return AVERROR(EINVAL);
+    }
+
+    /* Get quality properties for the profile and quality level */
+    quality_info = (VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR,
+        .pVideoProfile = &ctx->profile,
+        .qualityLevel = ctx->opts.quality,
+    };
+    ctx->quality_props = (VkVideoEncodeQualityLevelPropertiesKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_PROPERTIES_KHR,
+        .pNext = quality_pnext,
+    };
+    ret = vk->GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR(s->hwctx->phys_dev,
+                                                                    &quality_info,
+                                                                    &ctx->quality_props);
+    if (ret != VK_SUCCESS)
+        return AVERROR_EXTERNAL;
+
+    /* Printout informative properties */
+    av_log(avctx, AV_LOG_VERBOSE, "Encoder capabilities for %s profile \"%s\":\n",
+           avcodec_get_name(avctx->codec_id),
+           avcodec_profile_name(avctx->codec_id, avctx->profile));
+    av_log(avctx, AV_LOG_VERBOSE, "    Width: from %i to %i\n",
+           ctx->caps.minCodedExtent.width, ctx->caps.maxCodedExtent.width);
+    av_log(avctx, AV_LOG_VERBOSE, "    Height: from %i to %i\n",
+           ctx->caps.minCodedExtent.height, ctx->caps.maxCodedExtent.height);
+    av_log(avctx, AV_LOG_VERBOSE, "    Width alignment: %i\n",
+           ctx->caps.pictureAccessGranularity.width);
+    av_log(avctx, AV_LOG_VERBOSE, "    Height alignment: %i\n",
+           ctx->caps.pictureAccessGranularity.height);
+    av_log(avctx, AV_LOG_VERBOSE, "    Bitstream offset alignment: %"PRIu64"\n",
+           ctx->caps.minBitstreamBufferOffsetAlignment);
+    av_log(avctx, AV_LOG_VERBOSE, "    Bitstream size alignment: %"PRIu64"\n",
+           ctx->caps.minBitstreamBufferSizeAlignment);
+    av_log(avctx, AV_LOG_VERBOSE, "    Maximum references: %u\n",
+           ctx->caps.maxDpbSlots);
+    av_log(avctx, AV_LOG_VERBOSE, "    Maximum active references: %u\n",
+           ctx->caps.maxActiveReferencePictures);
+    av_log(avctx, AV_LOG_VERBOSE, "    Codec header version: %i.%i.%i (driver), %i.%i.%i (compiled)\n",
+           CODEC_VER(ctx->caps.stdHeaderVersion.specVersion),
+           CODEC_VER(vk_desc->ext_props.specVersion));
+    av_log(avctx, AV_LOG_VERBOSE, "    Encoder max quality: %i\n",
+           ctx->enc_caps.maxQualityLevels);
+    av_log(avctx, AV_LOG_VERBOSE, "    Encoder image width alignment: %i\n",
+           ctx->enc_caps.encodeInputPictureGranularity.width);
+    av_log(avctx, AV_LOG_VERBOSE, "    Encoder image height alignment: %i\n",
+           ctx->enc_caps.encodeInputPictureGranularity.height);
+    av_log(avctx, AV_LOG_VERBOSE, "    Capability flags:%s%s%s\n",
+           ctx->caps.flags ? "" :
+               " none",
+           ctx->caps.flags & VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR ?
+               " protected" : "",
+           ctx->caps.flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR ?
+               " separate_references" : "");
+
+    /* Setup width/height alignment */
+    base_ctx->surface_width = avctx->coded_width =
+        FFALIGN(avctx->width, ctx->enc_caps.encodeInputPictureGranularity.width);
+    base_ctx->surface_height = avctx->coded_height =
+        FFALIGN(avctx->height, ctx->enc_caps.encodeInputPictureGranularity.height);
+
+    /* Setup slice width/height */
+    base_ctx->slice_block_width = ctx->enc_caps.encodeInputPictureGranularity.width;
+    base_ctx->slice_block_height = ctx->enc_caps.encodeInputPictureGranularity.height;
+
+    /* Check if encoding is possible with the given parameters */
+    if (avctx->coded_width  < ctx->caps.minCodedExtent.width   ||
+        avctx->coded_height < ctx->caps.minCodedExtent.height  ||
+        avctx->coded_width  > ctx->caps.maxCodedExtent.width   ||
+        avctx->coded_height > ctx->caps.maxCodedExtent.height) {
+        av_log(avctx, AV_LOG_ERROR, "Input of %ix%i too large for encoder limits: %ix%i max\n",
+               avctx->coded_width, avctx->coded_height,
+               ctx->caps.minCodedExtent.width, ctx->caps.minCodedExtent.height);
+        return AVERROR(EINVAL);
+    }
+
+    fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR;
+
+    ctx->common.layered_dpb = !(ctx->caps.flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR);
+
+    /* Get the supported image formats */
+    ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(s->hwctx->phys_dev,
+                                                        &fmt_info,
+                                                        &nb_out_fmts, NULL);
+    if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
+        (!nb_out_fmts && ret == VK_SUCCESS)) {
+        return AVERROR(EINVAL);
+    } else if (ret != VK_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+
+    ret_info = av_mallocz(sizeof(*ret_info)*nb_out_fmts);
+    if (!ret_info)
+        return AVERROR(ENOMEM);
+
+    for (int i = 0; i < nb_out_fmts; i++)
+        ret_info[i].sType = VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR;
+
+    ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(s->hwctx->phys_dev,
+                                                        &fmt_info,
+                                                        &nb_out_fmts, ret_info);
+    if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
+        (!nb_out_fmts && ret == VK_SUCCESS)) {
+        av_free(ret_info);
+        return AVERROR(EINVAL);
+    } else if (ret != VK_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
+               ff_vk_ret2str(ret));
+        av_free(ret_info);
+        return AVERROR_EXTERNAL;
+    }
+
+    av_log(avctx, AV_LOG_VERBOSE, "Supported input formats:\n");
+    for (i = 0; i < nb_out_fmts; i++)
+        av_log(avctx, AV_LOG_VERBOSE, "    %i: %i\n", i, ret_info[i].format);
+
+    for (i = 0; i < nb_out_fmts; i++) {
+        if (ff_vk_pix_fmt_from_vkfmt(ret_info[i].format) == s->frames->sw_format) {
+            ctx->pic_format = ret_info[i].format;
+            break;
+        }
+    }
+
+    av_free(ret_info);
+
+    if (i == nb_out_fmts) {
+        av_log(avctx, AV_LOG_ERROR, "Pixel format %s of input frames not supported!\n",
+               av_get_pix_fmt_name(s->frames->sw_format));
+        return AVERROR(EINVAL);
+    }
+
+    /* Create session */
+    session_create.pVideoProfile = &ctx->profile;
+    session_create.flags = 0x0;
+    session_create.queueFamilyIndex = ctx->qf_enc->idx;
+    session_create.maxCodedExtent = ctx->caps.maxCodedExtent;
+    session_create.maxDpbSlots = ctx->caps.maxDpbSlots;
+    session_create.maxActiveReferencePictures = ctx->caps.maxActiveReferencePictures;
+    session_create.pictureFormat = ctx->pic_format;
+    session_create.referencePictureFormat = session_create.pictureFormat;
+    session_create.pStdHeaderVersion = &vk_desc->ext_props;
+
+    err = ff_vk_video_common_init(avctx, s, &ctx->common, &session_create);
+    if (err < 0)
+        return err;
+
+    err = ff_hw_base_encode_init(avctx, &ctx->base);
+    if (err < 0)
+        return err;
+
+    err = vulkan_encode_create_dpb(avctx, ctx);
+    if (err < 0)
+        return err;
+
+    base_ctx->async_encode = 1;
+    base_ctx->encode_fifo = av_fifo_alloc2(base_ctx->async_depth,
+                                           sizeof(FFVulkanEncodePicture *), 0);
+    if (!base_ctx->encode_fifo)
+        return AVERROR(ENOMEM);
+
+    return 0;
+}
+
+int ff_vulkan_encode_create_session_params(AVCodecContext *avctx, FFVulkanEncodeContext *ctx,
+                                           void *codec_params_pnext)
+{
+    VkResult ret;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+    FFVulkanContext *s = &ctx->s;
+
+    VkVideoEncodeQualityLevelInfoKHR q_info;
+    VkVideoSessionParametersCreateInfoKHR session_params_create;
+
+    q_info = (VkVideoEncodeQualityLevelInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR,
+        .pNext = codec_params_pnext,
+        .qualityLevel = ctx->opts.quality,
+    };
+    session_params_create = (VkVideoSessionParametersCreateInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
+        .pNext = &q_info,
+        .videoSession = ctx->common.session,
+        .videoSessionParametersTemplate = VK_NULL_HANDLE,
+    };
+
+    /* Create session parameters */
+    ret = vk->CreateVideoSessionParametersKHR(s->hwctx->act_dev, &session_params_create,
+                                              s->hwctx->alloc, &ctx->session_params);
+    if (ret != VK_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to create Vulkan video session parameters: %s!\n",
+               ff_vk_ret2str(ret));
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
-- 
2.49.1


From dbd82f7228f4d9a375892458ae093d5dc74e1c90 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:31:46 +0000
Subject: [PATCH 071/118] Changing vulkan file directory

---
 libavcodec/vulkan_encode.h | 259 -------------------------------------
 1 file changed, 259 deletions(-)
 delete mode 100644 libavcodec/vulkan_encode.h

diff --git a/libavcodec/vulkan_encode.h b/libavcodec/vulkan_encode.h
deleted file mode 100644
index 3df06e11d0..0000000000
--- a/libavcodec/vulkan_encode.h
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVCODEC_VULKAN_ENCODE_H
-#define AVCODEC_VULKAN_ENCODE_H
-
-#include "codec_id.h"
-#include "internal.h"
-
-#include "encode.h"
-#include "hwconfig.h"
-
-#include "vulkan_video.h"
-#include "hw_base_encode.h"
-
-typedef struct FFVulkanEncodeDescriptor {
-    enum AVCodecID                   codec_id;
-    FFVulkanExtensions               encode_extension;
-    VkVideoCodecOperationFlagBitsKHR encode_op;
-
-    VkExtensionProperties ext_props;
-} FFVulkanEncodeDescriptor;
-
-typedef struct FFVulkanEncodePicture {
-    FFHWBaseEncodePicture  base;
-    VkVideoPictureResourceInfoKHR dpb_res;
-    VkVideoReferenceSlotInfoKHR dpb_slot;
-
-    struct {
-        VkImageView        view;
-        VkImageAspectFlags aspect;
-    } in;
-
-    struct {
-        VkImageView        view;
-        VkImageAspectFlags aspect;
-    } dpb;
-
-    void                  *codec_layer;
-    void                  *codec_rc_layer;
-
-    FFVkExecContext       *exec;
-    AVBufferRef           *pkt_buf;
-    int                    slices_offset;
-} FFVulkanEncodePicture;
-
-/**
- * Callback for writing stream-level headers.
- */
-typedef int (*vkenc_cb_write_stream_headers)(AVCodecContext *avctx,
-                                             uint8_t *data, size_t *data_len);
-
-/**
- * Callback for initializing codec-specific picture headers.
- */
-typedef int (*vkenc_cb_init_pic_headers)(AVCodecContext *avctx,
-                                         FFVulkanEncodePicture *pic);
-
-/**
- * Callback for writing alignment data.
- * Align is the value to align offset to.
- */
-typedef int (*vkenc_cb_write_filler)(AVCodecContext *avctx, uint32_t filler,
-                                     uint8_t *data, size_t *data_len);
-
-/**
- * Callback for writing any extra units requested. data_len must be set
- * to the available size, and its value will be overwritten by the #bytes written
- * to the output buffer.
- */
-typedef int (*vkenc_cb_write_extra_headers)(AVCodecContext *avctx,
-                                            FFVulkanEncodePicture *pic,
-                                            uint8_t *data, size_t *data_len);
-
-typedef struct FFVulkanCodec {
-    /**
-     * Codec feature flags.
-     */
-    int flags;
-/* Codec output packet without timestamp delay, which means the
- * output packet has same PTS and DTS. For AV1. */
-#define VK_ENC_FLAG_NO_DELAY 1 << 6
-
-    /**
-     * Size of the codec-specific picture struct.
-     */
-    size_t picture_priv_data_size;
-
-    /**
-     * Size of the filler header.
-     */
-    size_t filler_header_size;
-
-    /**
-     * Initialize codec-specific structs in a Vulkan profile.
-     */
-    int (*init_profile)(AVCodecContext *avctx, VkVideoProfileInfoKHR *profile,
-                        void *pnext);
-
-    /**
-     * Initialize codec-specific rate control structures for a picture.
-     */
-    int (*init_pic_rc)(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
-                       VkVideoEncodeRateControlInfoKHR *rc_info,
-                       VkVideoEncodeRateControlLayerInfoKHR *rc_layer);
-
-    /**
-     * Initialize codec-specific picture parameters.
-     */
-    int (*init_pic_params)(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
-                           VkVideoEncodeInfoKHR *encode_info);
-
-    /**
-     * Callback for writing stream headers.
-     */
-    int (*write_sequence_headers)(AVCodecContext *avctx,
-                                  FFHWBaseEncodePicture *base_pic,
-                                  uint8_t *data, size_t *data_len);
-
-    /**
-     * Callback for writing alignment data.
-     */
-    int (*write_filler)(AVCodecContext *avctx, uint32_t filler,
-                        uint8_t *data, size_t *data_len);
-
-    /**
-     * Callback for writing any extra units requested. data_len must be set
-     * to the available size, and its value will be overwritten by the #bytes written
-     * to the output buffer.
-     */
-    int (*write_extra_headers)(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
-                               uint8_t *data, size_t *data_len);
-} FFVulkanCodec;
-
-typedef struct FFVkEncodeCommonOptions {
-    int qp;
-    int quality;
-    int profile;
-    int level;
-    int tier;
-    int async_depth;
-    VkVideoEncodeUsageFlagBitsKHR usage;
-    VkVideoEncodeContentFlagBitsKHR content;
-    VkVideoEncodeTuningModeKHR tune;
-
-    VkVideoEncodeRateControlModeFlagBitsKHR rc_mode;
-#define FF_VK_RC_MODE_AUTO 0xFFFFFFFF
-} FFVkEncodeCommonOptions;
-
-typedef struct FFVulkanEncodeContext {
-    FFVulkanContext s;
-    FFVkVideoCommon common;
-    FFHWBaseEncodeContext base;
-    const FFVulkanCodec *codec;
-
-    int explicit_qp;
-    int session_reset;
-
-    /* Session parameters object, initialized by each codec independently
-     * and set here. */
-    VkVideoSessionParametersKHR session_params;
-
-    AVBufferPool *buf_pool;
-
-    VkFormat pic_format;
-
-    FFVkEncodeCommonOptions opts;
-
-    VkVideoProfileInfoKHR profile;
-    VkVideoProfileListInfoKHR profile_list;
-    VkVideoCapabilitiesKHR caps;
-    VkVideoEncodeQualityLevelPropertiesKHR quality_props;
-    VkVideoEncodeCapabilitiesKHR enc_caps;
-    VkVideoEncodeUsageInfoKHR usage_info;
-
-    AVVulkanDeviceQueueFamily *qf_enc;
-    FFVkExecPool enc_pool;
-
-    FFHWBaseEncodePicture *slots[32];
-} FFVulkanEncodeContext;
-
-#define VULKAN_ENCODE_COMMON_OPTIONS \
-    { "qp", "Use an explicit constant quantizer for the whole stream", OFFSET(common.opts.qp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, FLAGS }, \
-    { "quality", "Set encode quality (trades off against speed, higher is faster)", OFFSET(common.opts.quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, \
-    { "rc_mode", "Select rate control type", OFFSET(common.opts.rc_mode), AV_OPT_TYPE_INT, { .i64 = FF_VK_RC_MODE_AUTO }, 0, FF_VK_RC_MODE_AUTO, FLAGS, "rc_mode" }, \
-        { "auto",    "Choose mode automatically based on parameters", 0, AV_OPT_TYPE_CONST, { .i64 = FF_VK_RC_MODE_AUTO }, INT_MIN, INT_MAX, FLAGS, "rc_mode" }, \
-        { "driver",  "Driver-specific rate control", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR      }, INT_MIN, INT_MAX, FLAGS, "rc_mode" }, \
-        { "cqp",     "Constant quantizer mode", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR }, INT_MIN, INT_MAX, FLAGS, "rc_mode" }, \
-        { "cbr",     "Constant bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR      }, INT_MIN, INT_MAX, FLAGS, "rc_mode" }, \
-        { "vbr",     "Variable bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR      }, INT_MIN, INT_MAX, FLAGS, "rc_mode" }, \
-    { "tune", "Select tuning type", OFFSET(common.opts.tune), AV_OPT_TYPE_INT, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_DEFAULT_KHR }, 0, INT_MAX, FLAGS, "tune" }, \
-        { "default",  "Default tuning", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_DEFAULT_KHR           }, INT_MIN, INT_MAX, FLAGS, "tune" }, \
-        { "hq",       "High quality tuning", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_HIGH_QUALITY_KHR      }, INT_MIN, INT_MAX, FLAGS, "tune" }, \
-        { "ll",       "Low-latency tuning", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_LOW_LATENCY_KHR       }, INT_MIN, INT_MAX, FLAGS, "tune" }, \
-        { "ull",      "Ultra low-latency tuning", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_ULTRA_LOW_LATENCY_KHR }, INT_MIN, INT_MAX, FLAGS, "tune" }, \
-        { "lossless", "Lossless mode tuning", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_LOSSLESS_KHR          }, INT_MIN, INT_MAX, FLAGS, "tune" }, \
-    { "usage", "Select usage type", OFFSET(common.opts.usage), AV_OPT_TYPE_FLAGS, { .i64 = VK_VIDEO_ENCODE_USAGE_DEFAULT_KHR }, 0, INT_MAX, FLAGS, "usage" }, \
-        { "default",    "Default optimizations", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_USAGE_DEFAULT_KHR          }, INT_MIN, INT_MAX, FLAGS, "usage" }, \
-        { "transcode",  "Optimize for transcoding", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_USAGE_TRANSCODING_BIT_KHR  }, INT_MIN, INT_MAX, FLAGS, "usage" }, \
-        { "stream",     "Optimize for streaming", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_USAGE_STREAMING_BIT_KHR    }, INT_MIN, INT_MAX, FLAGS, "usage" }, \
-        { "record",     "Optimize for offline recording", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_USAGE_RECORDING_BIT_KHR    }, INT_MIN, INT_MAX, FLAGS, "usage" }, \
-        { "conference", "Optimize for teleconferencing", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_USAGE_CONFERENCING_BIT_KHR }, INT_MIN, INT_MAX, FLAGS, "usage" }, \
-    { "content", "Select content type", OFFSET(common.opts.content), AV_OPT_TYPE_FLAGS, { .i64 = VK_VIDEO_ENCODE_CONTENT_DEFAULT_KHR }, 0, INT_MAX, FLAGS, "content" }, \
-        { "default",  "Default content", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_CONTENT_DEFAULT_KHR      }, INT_MIN, INT_MAX, FLAGS, "content" }, \
-        { "camera",   "Camera footage", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_CONTENT_CAMERA_BIT_KHR   }, INT_MIN, INT_MAX, FLAGS, "content" }, \
-        { "desktop",  "Screen recording", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_CONTENT_DESKTOP_BIT_KHR  }, INT_MIN, INT_MAX, FLAGS, "content" }, \
-        { "rendered", "Game or 3D content", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_CONTENT_RENDERED_BIT_KHR }, INT_MIN, INT_MAX, FLAGS, "content" }
-
-/**
- * Initialize encoder.
- */
-av_cold int ff_vulkan_encode_init(AVCodecContext *avctx, FFVulkanEncodeContext *ctx,
-                                  const FFVulkanEncodeDescriptor *vk_desc,
-                                  const FFVulkanCodec *codec,
-                                  void *codec_caps, void *quality_pnext);
-
-/**
- * Write out the extradata in case its needed.
- */
-av_cold int ff_vulkan_write_global_header(AVCodecContext *avctx,
-                                          FFVulkanEncodeContext *ctx);
-
-/**
- * Encode.
- */
-int ff_vulkan_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt);
-
-/**
- * Uninitialize encoder.
- */
-void ff_vulkan_encode_uninit(FFVulkanEncodeContext *ctx);
-
-/**
- * Create session parameters.
- */
-int ff_vulkan_encode_create_session_params(AVCodecContext *avctx, FFVulkanEncodeContext *ctx,
-                                           void *codec_params_pnext);
-
-/**
- * Paperwork.
- */
-extern const AVCodecHWConfigInternal *const ff_vulkan_encode_hw_configs[];
-
-#endif /* AVCODEC_VULKAN_ENCODE_H */
-- 
2.49.1


From f93392ea6e08431625475e3744e0b391ebc51516 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:32:14 +0000
Subject: [PATCH 072/118] Changing vulkan file directory

---
 libavcodec/vulkan/vulkan_encode.h | 259 ++++++++++++++++++++++++++++++
 1 file changed, 259 insertions(+)
 create mode 100644 libavcodec/vulkan/vulkan_encode.h

diff --git a/libavcodec/vulkan/vulkan_encode.h b/libavcodec/vulkan/vulkan_encode.h
new file mode 100644
index 0000000000..583199a7d7
--- /dev/null
+++ b/libavcodec/vulkan/vulkan_encode.h
@@ -0,0 +1,259 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_VULKAN_ENCODE_H
+#define AVCODEC_VULKAN_ENCODE_H
+
+#include "libavcodec/codec_id.h"
+#include "libavcodec/internal.h"
+
+#include "libavcodec/encode.h"
+#include "libavcodec/hwconfig.h"
+
+#include "vulkan_video.h"
+#include "libavcodec/hw_base_encode.h"
+
+typedef struct FFVulkanEncodeDescriptor {
+    enum AVCodecID                   codec_id;
+    FFVulkanExtensions               encode_extension;
+    VkVideoCodecOperationFlagBitsKHR encode_op;
+
+    VkExtensionProperties ext_props;
+} FFVulkanEncodeDescriptor;
+
+typedef struct FFVulkanEncodePicture {
+    FFHWBaseEncodePicture  base;
+    VkVideoPictureResourceInfoKHR dpb_res;
+    VkVideoReferenceSlotInfoKHR dpb_slot;
+
+    struct {
+        VkImageView        view;
+        VkImageAspectFlags aspect;
+    } in;
+
+    struct {
+        VkImageView        view;
+        VkImageAspectFlags aspect;
+    } dpb;
+
+    void                  *codec_layer;
+    void                  *codec_rc_layer;
+
+    FFVkExecContext       *exec;
+    AVBufferRef           *pkt_buf;
+    int                    slices_offset;
+} FFVulkanEncodePicture;
+
+/**
+ * Callback for writing stream-level headers.
+ */
+typedef int (*vkenc_cb_write_stream_headers)(AVCodecContext *avctx,
+                                             uint8_t *data, size_t *data_len);
+
+/**
+ * Callback for initializing codec-specific picture headers.
+ */
+typedef int (*vkenc_cb_init_pic_headers)(AVCodecContext *avctx,
+                                         FFVulkanEncodePicture *pic);
+
+/**
+ * Callback for writing alignment data.
+ * Align is the value to align offset to.
+ */
+typedef int (*vkenc_cb_write_filler)(AVCodecContext *avctx, uint32_t filler,
+                                     uint8_t *data, size_t *data_len);
+
+/**
+ * Callback for writing any extra units requested. data_len must be set
+ * to the available size, and its value will be overwritten by the #bytes written
+ * to the output buffer.
+ */
+typedef int (*vkenc_cb_write_extra_headers)(AVCodecContext *avctx,
+                                            FFVulkanEncodePicture *pic,
+                                            uint8_t *data, size_t *data_len);
+
+typedef struct FFVulkanCodec {
+    /**
+     * Codec feature flags.
+     */
+    int flags;
+/* Codec output packet without timestamp delay, which means the
+ * output packet has same PTS and DTS. For AV1. */
+#define VK_ENC_FLAG_NO_DELAY 1 << 6
+
+    /**
+     * Size of the codec-specific picture struct.
+     */
+    size_t picture_priv_data_size;
+
+    /**
+     * Size of the filler header.
+     */
+    size_t filler_header_size;
+
+    /**
+     * Initialize codec-specific structs in a Vulkan profile.
+     */
+    int (*init_profile)(AVCodecContext *avctx, VkVideoProfileInfoKHR *profile,
+                        void *pnext);
+
+    /**
+     * Initialize codec-specific rate control structures for a picture.
+     */
+    int (*init_pic_rc)(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
+                       VkVideoEncodeRateControlInfoKHR *rc_info,
+                       VkVideoEncodeRateControlLayerInfoKHR *rc_layer);
+
+    /**
+     * Initialize codec-specific picture parameters.
+     */
+    int (*init_pic_params)(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
+                           VkVideoEncodeInfoKHR *encode_info);
+
+    /**
+     * Callback for writing stream headers.
+     */
+    int (*write_sequence_headers)(AVCodecContext *avctx,
+                                  FFHWBaseEncodePicture *base_pic,
+                                  uint8_t *data, size_t *data_len);
+
+    /**
+     * Callback for writing alignment data.
+     */
+    int (*write_filler)(AVCodecContext *avctx, uint32_t filler,
+                        uint8_t *data, size_t *data_len);
+
+    /**
+     * Callback for writing any extra units requested. data_len must be set
+     * to the available size, and its value will be overwritten by the #bytes written
+     * to the output buffer.
+     */
+    int (*write_extra_headers)(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
+                               uint8_t *data, size_t *data_len);
+} FFVulkanCodec;
+
+typedef struct FFVkEncodeCommonOptions {
+    int qp;
+    int quality;
+    int profile;
+    int level;
+    int tier;
+    int async_depth;
+    VkVideoEncodeUsageFlagBitsKHR usage;
+    VkVideoEncodeContentFlagBitsKHR content;
+    VkVideoEncodeTuningModeKHR tune;
+
+    VkVideoEncodeRateControlModeFlagBitsKHR rc_mode;
+#define FF_VK_RC_MODE_AUTO 0xFFFFFFFF
+} FFVkEncodeCommonOptions;
+
+typedef struct FFVulkanEncodeContext {
+    FFVulkanContext s;
+    FFVkVideoCommon common;
+    FFHWBaseEncodeContext base;
+    const FFVulkanCodec *codec;
+
+    int explicit_qp;
+    int session_reset;
+
+    /* Session parameters object, initialized by each codec independently
+     * and set here. */
+    VkVideoSessionParametersKHR session_params;
+
+    AVBufferPool *buf_pool;
+
+    VkFormat pic_format;
+
+    FFVkEncodeCommonOptions opts;
+
+    VkVideoProfileInfoKHR profile;
+    VkVideoProfileListInfoKHR profile_list;
+    VkVideoCapabilitiesKHR caps;
+    VkVideoEncodeQualityLevelPropertiesKHR quality_props;
+    VkVideoEncodeCapabilitiesKHR enc_caps;
+    VkVideoEncodeUsageInfoKHR usage_info;
+
+    AVVulkanDeviceQueueFamily *qf_enc;
+    FFVkExecPool enc_pool;
+
+    FFHWBaseEncodePicture *slots[32];
+} FFVulkanEncodeContext;
+
+#define VULKAN_ENCODE_COMMON_OPTIONS \
+    { "qp", "Use an explicit constant quantizer for the whole stream", OFFSET(common.opts.qp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, FLAGS }, \
+    { "quality", "Set encode quality (trades off against speed, higher is faster)", OFFSET(common.opts.quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, \
+    { "rc_mode", "Select rate control type", OFFSET(common.opts.rc_mode), AV_OPT_TYPE_INT, { .i64 = FF_VK_RC_MODE_AUTO }, 0, FF_VK_RC_MODE_AUTO, FLAGS, "rc_mode" }, \
+        { "auto",    "Choose mode automatically based on parameters", 0, AV_OPT_TYPE_CONST, { .i64 = FF_VK_RC_MODE_AUTO }, INT_MIN, INT_MAX, FLAGS, "rc_mode" }, \
+        { "driver",  "Driver-specific rate control", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR      }, INT_MIN, INT_MAX, FLAGS, "rc_mode" }, \
+        { "cqp",     "Constant quantizer mode", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR }, INT_MIN, INT_MAX, FLAGS, "rc_mode" }, \
+        { "cbr",     "Constant bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR      }, INT_MIN, INT_MAX, FLAGS, "rc_mode" }, \
+        { "vbr",     "Variable bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR      }, INT_MIN, INT_MAX, FLAGS, "rc_mode" }, \
+    { "tune", "Select tuning type", OFFSET(common.opts.tune), AV_OPT_TYPE_INT, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_DEFAULT_KHR }, 0, INT_MAX, FLAGS, "tune" }, \
+        { "default",  "Default tuning", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_DEFAULT_KHR           }, INT_MIN, INT_MAX, FLAGS, "tune" }, \
+        { "hq",       "High quality tuning", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_HIGH_QUALITY_KHR      }, INT_MIN, INT_MAX, FLAGS, "tune" }, \
+        { "ll",       "Low-latency tuning", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_LOW_LATENCY_KHR       }, INT_MIN, INT_MAX, FLAGS, "tune" }, \
+        { "ull",      "Ultra low-latency tuning", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_ULTRA_LOW_LATENCY_KHR }, INT_MIN, INT_MAX, FLAGS, "tune" }, \
+        { "lossless", "Lossless mode tuning", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_LOSSLESS_KHR          }, INT_MIN, INT_MAX, FLAGS, "tune" }, \
+    { "usage", "Select usage type", OFFSET(common.opts.usage), AV_OPT_TYPE_FLAGS, { .i64 = VK_VIDEO_ENCODE_USAGE_DEFAULT_KHR }, 0, INT_MAX, FLAGS, "usage" }, \
+        { "default",    "Default optimizations", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_USAGE_DEFAULT_KHR          }, INT_MIN, INT_MAX, FLAGS, "usage" }, \
+        { "transcode",  "Optimize for transcoding", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_USAGE_TRANSCODING_BIT_KHR  }, INT_MIN, INT_MAX, FLAGS, "usage" }, \
+        { "stream",     "Optimize for streaming", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_USAGE_STREAMING_BIT_KHR    }, INT_MIN, INT_MAX, FLAGS, "usage" }, \
+        { "record",     "Optimize for offline recording", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_USAGE_RECORDING_BIT_KHR    }, INT_MIN, INT_MAX, FLAGS, "usage" }, \
+        { "conference", "Optimize for teleconferencing", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_USAGE_CONFERENCING_BIT_KHR }, INT_MIN, INT_MAX, FLAGS, "usage" }, \
+    { "content", "Select content type", OFFSET(common.opts.content), AV_OPT_TYPE_FLAGS, { .i64 = VK_VIDEO_ENCODE_CONTENT_DEFAULT_KHR }, 0, INT_MAX, FLAGS, "content" }, \
+        { "default",  "Default content", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_CONTENT_DEFAULT_KHR      }, INT_MIN, INT_MAX, FLAGS, "content" }, \
+        { "camera",   "Camera footage", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_CONTENT_CAMERA_BIT_KHR   }, INT_MIN, INT_MAX, FLAGS, "content" }, \
+        { "desktop",  "Screen recording", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_CONTENT_DESKTOP_BIT_KHR  }, INT_MIN, INT_MAX, FLAGS, "content" }, \
+        { "rendered", "Game or 3D content", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_CONTENT_RENDERED_BIT_KHR }, INT_MIN, INT_MAX, FLAGS, "content" }
+
+/**
+ * Initialize encoder.
+ */
+av_cold int ff_vulkan_encode_init(AVCodecContext *avctx, FFVulkanEncodeContext *ctx,
+                                  const FFVulkanEncodeDescriptor *vk_desc,
+                                  const FFVulkanCodec *codec,
+                                  void *codec_caps, void *quality_pnext);
+
+/**
+ * Write out the extradata in case its needed.
+ */
+av_cold int ff_vulkan_write_global_header(AVCodecContext *avctx,
+                                          FFVulkanEncodeContext *ctx);
+
+/**
+ * Encode.
+ */
+int ff_vulkan_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt);
+
+/**
+ * Uninitialize encoder.
+ */
+void ff_vulkan_encode_uninit(FFVulkanEncodeContext *ctx);
+
+/**
+ * Create session parameters.
+ */
+int ff_vulkan_encode_create_session_params(AVCodecContext *avctx, FFVulkanEncodeContext *ctx,
+                                           void *codec_params_pnext);
+
+/**
+ * Paperwork.
+ */
+extern const AVCodecHWConfigInternal *const ff_vulkan_encode_hw_configs[];
+
+#endif /* AVCODEC_VULKAN_ENCODE_H */
-- 
2.49.1


From b127a0655932ae25775dbf741c74fbc5fe05151b Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:32:35 +0000
Subject: [PATCH 073/118] Changing vulkan file directory

---
 libavcodec/vulkan_encode_av1.c | 1401 --------------------------------
 1 file changed, 1401 deletions(-)
 delete mode 100644 libavcodec/vulkan_encode_av1.c

diff --git a/libavcodec/vulkan_encode_av1.c b/libavcodec/vulkan_encode_av1.c
deleted file mode 100644
index 08ffbfa393..0000000000
--- a/libavcodec/vulkan_encode_av1.c
+++ /dev/null
@@ -1,1401 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/opt.h"
-#include "libavutil/mem.h"
-
-#include "cbs.h"
-#include "cbs_av1.h"
-#include "av1_levels.h"
-#include "libavutil/mastering_display_metadata.h"
-
-#include "codec_internal.h"
-#include "vulkan_encode.h"
-
-#include "libavutil/avassert.h"
-
-const FFVulkanEncodeDescriptor ff_vk_enc_av1_desc = {
-    .codec_id         = AV_CODEC_ID_AV1,
-    .encode_extension = FF_VK_EXT_VIDEO_ENCODE_AV1,
-    .encode_op        = VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR,
-    .ext_props = {
-        .extensionName = VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_EXTENSION_NAME,
-        .specVersion   = VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_SPEC_VERSION,
-    },
-};
-
-enum UnitElems {
-    UNIT_MASTERING_DISPLAY   = 1 << 0,
-    UNIT_CONTENT_LIGHT_LEVEL = 1 << 1,
-};
-
-typedef struct VulkanEncodeAV1Picture {
-    int slot;
-    int64_t last_idr_frame;
-
-    enum UnitElems units_needed;
-
-    StdVideoAV1TileInfo tile_info;
-    StdVideoAV1Quantization quantization;
-    StdVideoAV1Segmentation segmentation;
-    StdVideoAV1LoopFilter loop_filter;
-    StdVideoAV1CDEF cdef;
-    StdVideoAV1LoopRestoration loop_restoration;
-    StdVideoAV1GlobalMotion global_motion;
-
-    StdVideoEncodeAV1PictureInfo av1pic_info;
-    VkVideoEncodeAV1PictureInfoKHR vkav1pic_info;
-
-    StdVideoEncodeAV1ExtensionHeader ext_header;
-    StdVideoEncodeAV1ReferenceInfo av1dpb_info;
-    VkVideoEncodeAV1DpbSlotInfoKHR vkav1dpb_info;
-
-    VkVideoEncodeAV1RateControlInfoKHR vkrc_info;
-    VkVideoEncodeAV1RateControlLayerInfoKHR vkrc_layer_info;
-    VkVideoEncodeAV1GopRemainingFrameInfoKHR vkrc_remaining;
-} VulkanEncodeAV1Picture;
-
-typedef struct VulkanEncodeAV1Context {
-    FFVulkanEncodeContext common;
-
-    CodedBitstreamContext *cbs;
-    CodedBitstreamFragment current_access_unit;
-
-    enum UnitElems unit_elems;
-    AV1RawOBU seq_hdr_obu;
-    AV1RawOBU meta_cll_obu;
-    AV1RawOBU meta_mastering_obu;
-
-    VkVideoEncodeAV1ProfileInfoKHR profile;
-
-    VkVideoEncodeAV1CapabilitiesKHR caps;
-    VkVideoEncodeAV1QualityLevelPropertiesKHR quality_props;
-
-    uint64_t hrd_buffer_size;
-    uint64_t initial_buffer_fullness;
-
-    int uniform_tile;
-    int tile_cols;
-    int tile_rows;
-
-    int seq_tier;
-    int seq_level_idx;
-
-    int q_idx_idr;
-    int q_idx_p;
-    int q_idx_b;
-
-    uint8_t *padding_payload;
-} VulkanEncodeAV1Context;
-
-static int init_pic_rc(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
-                       VkVideoEncodeRateControlInfoKHR *rc_info,
-                       VkVideoEncodeRateControlLayerInfoKHR *rc_layer)
-{
-    VulkanEncodeAV1Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext  *ctx = &enc->common;
-    VulkanEncodeAV1Picture  *ap = pic->codec_priv;
-
-    /* This can be easy to calculate */
-    ap->vkrc_remaining = (VkVideoEncodeAV1GopRemainingFrameInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_GOP_REMAINING_FRAME_INFO_KHR,
-        .useGopRemainingFrames = 0,
-        .gopRemainingIntra = 0,
-        .gopRemainingPredictive = 0,
-        .gopRemainingBipredictive = 0,
-    };
-
-    ap->vkrc_info = (VkVideoEncodeAV1RateControlInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_RATE_CONTROL_INFO_KHR,
-        .flags = VK_VIDEO_ENCODE_AV1_RATE_CONTROL_REFERENCE_PATTERN_FLAT_BIT_KHR |
-                 VK_VIDEO_ENCODE_AV1_RATE_CONTROL_REGULAR_GOP_BIT_KHR,
-        .gopFrameCount = ctx->base.gop_size,
-        .keyFramePeriod = ctx->base.gop_size,
-        .consecutiveBipredictiveFrameCount = FFMAX(ctx->base.b_per_p - 1, 0),
-        .temporalLayerCount = 0,
-    };
-    rc_info->pNext = &ap->vkrc_info;
-
-    if (rc_info->rateControlMode > VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
-        rc_info->virtualBufferSizeInMs = (enc->hrd_buffer_size * 1000LL) / avctx->bit_rate;
-        rc_info->initialVirtualBufferSizeInMs = (enc->initial_buffer_fullness * 1000LL) / avctx->bit_rate;
-
-        ap->vkrc_layer_info = (VkVideoEncodeAV1RateControlLayerInfoKHR) {
-            .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_RATE_CONTROL_LAYER_INFO_KHR,
-
-            .useMinQIndex  = avctx->qmin > 0,
-            .minQIndex.intraQIndex = avctx->qmin > 0 ? avctx->qmin : 0,
-            .minQIndex.predictiveQIndex = avctx->qmin > 0 ? avctx->qmin : 0,
-            .minQIndex.bipredictiveQIndex = avctx->qmin > 0 ? avctx->qmin : 0,
-
-            .useMaxQIndex  = avctx->qmax > 0,
-            .maxQIndex.intraQIndex = avctx->qmax > 0 ? avctx->qmax : 0,
-            .maxQIndex.predictiveQIndex = avctx->qmax > 0 ? avctx->qmax : 0,
-            .maxQIndex.bipredictiveQIndex = avctx->qmax > 0 ? avctx->qmax : 0,
-
-            .useMaxFrameSize = 0,
-        };
-        rc_layer->pNext = &ap->vkrc_layer_info;
-        ap->vkrc_info.temporalLayerCount = 1;
-    }
-
-    return 0;
-}
-
-static void set_name_slot(int slot, int *slot_indices, uint32_t allowed_idx, int group)
-{
-    int from = group ? AV1_REF_FRAME_GOLDEN : 0;
-    int to = group ? AV1_REFS_PER_FRAME : AV1_REF_FRAME_GOLDEN;
-
-    for (int i = from; i < to; i++) {
-        if ((slot_indices[i] == -1) && (allowed_idx & (1 << i))) {
-            slot_indices[i] = slot;
-            return;
-        }
-    }
-
-    av_assert0(0);
-}
-
-
-static int init_pic_params(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
-                           VkVideoEncodeInfoKHR *encode_info)
-{
-    VulkanEncodeAV1Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext *ctx = &enc->common;
-    FFHWBaseEncodeContext *base_ctx = &ctx->base;
-
-    VulkanEncodeAV1Picture *ap = pic->codec_priv;
-    FFHWBaseEncodePicture *ref;
-    VulkanEncodeAV1Picture *ap_ref;
-    VkVideoReferenceSlotInfoKHR *ref_slot;
-
-    uint32_t ref_name_mask = 0x0;
-    int name_slots[STD_VIDEO_AV1_REFS_PER_FRAME];
-
-    StdVideoAV1Segmentation *segmentation = &ap->segmentation;
-    StdVideoAV1LoopFilter  *loop_filter = &ap->loop_filter;
-    StdVideoAV1Quantization *quantization = &ap->quantization;
-    StdVideoAV1CDEF *cdef = &ap->cdef;
-    StdVideoAV1LoopRestoration *loop_restoration = &ap->loop_restoration;
-    StdVideoAV1GlobalMotion *global_motion = &ap->global_motion;
-    StdVideoAV1TileInfo *tile_info = &ap->tile_info;
-    static const int8_t default_loop_filter_ref_deltas[STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME] =
-        { 1, 0, 0, 0, -1, 0, -1, -1 };
-
-    VkVideoEncodeAV1PredictionModeKHR pred_mode;
-    VkVideoEncodeAV1RateControlGroupKHR rc_group;
-    int lr_unit_shift = 0;
-    int lr_uv_shift = 0;
-
-    ap->ext_header = (StdVideoEncodeAV1ExtensionHeader) {
-        .temporal_id = 0,
-        .spatial_id = 0,
-    };
-
-    *tile_info = (StdVideoAV1TileInfo) {
-        .flags = (StdVideoAV1TileInfoFlags) {
-            .uniform_tile_spacing_flag = enc->uniform_tile,
-        },
-        .TileCols = enc->tile_cols,
-        .TileRows = enc->tile_rows,
-        .context_update_tile_id = 0,
-        .tile_size_bytes_minus_1 = 0,
-    };
-
-    for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++) {
-        global_motion->GmType[i] = 0;
-        for (int j = 0; j < STD_VIDEO_AV1_GLOBAL_MOTION_PARAMS; j++) {
-            global_motion->gm_params[i][j] = 0;
-        }
-    }
-
-    for (int i = 0; i < STD_VIDEO_AV1_REFS_PER_FRAME; i++)
-        name_slots[i] = -1;
-
-    *loop_restoration = (StdVideoAV1LoopRestoration) {
-        .FrameRestorationType[0] = STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_NONE,
-        .FrameRestorationType[1] = STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_NONE,
-        .FrameRestorationType[2] = STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_NONE,
-        .LoopRestorationSize[0] = 1 + lr_unit_shift,
-        .LoopRestorationSize[1] = 1 + lr_unit_shift - lr_uv_shift,
-        .LoopRestorationSize[2] = 1 + lr_unit_shift - lr_uv_shift,
-    };
-
-    *cdef = (StdVideoAV1CDEF) {
-        .cdef_damping_minus_3 = 0,
-        .cdef_bits = 0,
-    };
-
-    for (int i = 0; i < STD_VIDEO_AV1_MAX_SEGMENTS; i++) {
-        segmentation->FeatureEnabled[i] = 0x0;
-        for (int j = 0; j < STD_VIDEO_AV1_SEG_LVL_MAX; j++) {
-            segmentation->FeatureEnabled[i] |= 0x0;
-            segmentation->FeatureData[i][j] = 0;
-        }
-    }
-
-    *loop_filter = (StdVideoAV1LoopFilter) {
-        .flags = (StdVideoAV1LoopFilterFlags) {
-            .loop_filter_delta_enabled = 0,
-            .loop_filter_delta_update = 0,
-        },
-        .loop_filter_level = { 0 },
-        .loop_filter_sharpness = 0,
-        .update_ref_delta = 0,
-        .loop_filter_ref_deltas = { 0 },
-        .update_mode_delta = 0,
-        .loop_filter_mode_deltas = { 0 },
-    };
-    loop_filter->update_mode_delta = 1;
-    memcpy(loop_filter->loop_filter_ref_deltas, default_loop_filter_ref_deltas,
-           STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME * sizeof(int8_t));
-
-    *quantization = (StdVideoAV1Quantization) {
-        .flags = (StdVideoAV1QuantizationFlags) {
-            .using_qmatrix = 0,
-            .diff_uv_delta = 0,
-            /* Reserved */
-        },
-        .base_q_idx = 0, /* Set later */
-        .DeltaQYDc = 0,
-        .DeltaQUDc = 0,
-        .DeltaQUAc = 0,
-        .DeltaQVDc = 0,
-        .DeltaQVAc = 0,
-        .qm_y = 0,
-        .qm_u = 0,
-        .qm_v = 0,
-    };
-
-    ref_slot = (VkVideoReferenceSlotInfoKHR *)encode_info->pSetupReferenceSlot;
-    ap->av1pic_info = (StdVideoEncodeAV1PictureInfo) {
-        .flags = (StdVideoEncodeAV1PictureInfoFlags) {
-            .error_resilient_mode = (pic->type == FF_HW_PICTURE_TYPE_I ||
-                                     pic->type == FF_HW_PICTURE_TYPE_IDR) &&
-                                    (pic->display_order <= pic->encode_order),
-            .disable_cdf_update = 0,
-            .use_superres = 0,
-            .render_and_frame_size_different = 0,
-            .allow_screen_content_tools = 0,
-            .is_filter_switchable = 0,
-            .force_integer_mv = 0,
-            .frame_size_override_flag = 0,
-            .buffer_removal_time_present_flag = 0,
-            .allow_intrabc = 0,
-            .frame_refs_short_signaling = 0,
-            .allow_high_precision_mv = 0,
-            .is_motion_mode_switchable = 0,
-            .use_ref_frame_mvs = 0,
-            .disable_frame_end_update_cdf = 0,
-            .allow_warped_motion = 0,
-            .reduced_tx_set = 0,
-            .skip_mode_present = 0,
-            .delta_q_present = 0,
-            .delta_lf_present = 0,
-            .delta_lf_multi = 0,
-            .segmentation_enabled = 0,
-            .segmentation_update_map = 0,
-            .segmentation_temporal_update = 0,
-            .segmentation_update_data = 0,
-            .UsesLr = 0,
-            .usesChromaLr = 0,
-            .show_frame = pic->display_order <= pic->encode_order,
-            .showable_frame = 0,
-            /* Reserved */
-        },
-        .frame_type = 0, // set later
-        .frame_presentation_time = 0,
-        .current_frame_id = ref_slot->slotIndex,
-        .order_hint = 0, // set later
-        .primary_ref_frame = 0, // set later
-        .refresh_frame_flags = 0x0, // set later
-        .coded_denom = 0,
-        .render_width_minus_1 = base_ctx->surface_width - 1,
-        .render_height_minus_1 = base_ctx->surface_height - 1,
-        .interpolation_filter = 0,
-        .TxMode = STD_VIDEO_AV1_TX_MODE_SELECT,
-        .delta_q_res = 0,
-        .delta_lf_res = 0,
-        .ref_order_hint = { 0 }, // set later
-        .ref_frame_idx = { 0 }, // set later
-        /* Reserved */
-        .delta_frame_id_minus_1 = { 0 },
-
-//        .pTileInfo = tile_info, TODO FIX
-        .pQuantization = quantization,
-        .pSegmentation = segmentation,
-        .pLoopFilter = loop_filter,
-        .pCDEF = cdef,
-        .pLoopRestoration = loop_restoration,
-        .pGlobalMotion = global_motion,
-        .pExtensionHeader = &ap->ext_header,
-        .pBufferRemovalTimes = NULL,
-    };
-
-    switch (pic->type) {
-    case FF_HW_PICTURE_TYPE_I:
-    case FF_HW_PICTURE_TYPE_IDR:
-        av_assert0(pic->nb_refs[0] == 0 || pic->nb_refs[1]);
-        ap->av1pic_info.frame_type = STD_VIDEO_AV1_FRAME_TYPE_KEY;
-        ap->av1pic_info.refresh_frame_flags = 0xFF;
-        quantization->base_q_idx = enc->q_idx_idr;
-        ap->slot = 0;
-        ap->last_idr_frame = pic->display_order;
-        pred_mode = VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_INTRA_ONLY_KHR;
-        rc_group = VK_VIDEO_ENCODE_AV1_RATE_CONTROL_GROUP_INTRA_KHR;
-        break;
-    case FF_HW_PICTURE_TYPE_P:
-        ref = pic->refs[0][pic->nb_refs[0] - 1];
-        ap_ref = ref->codec_priv;
-
-        ap->av1pic_info.frame_type = STD_VIDEO_AV1_FRAME_TYPE_INTER;
-        quantization->base_q_idx = enc->q_idx_p;
-
-        ap->last_idr_frame = ap_ref->last_idr_frame;
-        ap->slot = !ap_ref->slot;
-
-        ap->av1pic_info.refresh_frame_flags = 1 << ap->slot;
-
-        /** set the nearest frame in L0 as all reference frame. */
-        for (int i = 0; i < AV1_REFS_PER_FRAME; i++)
-            ap->av1pic_info.ref_frame_idx[i] = ap_ref->slot;
-
-        ap->av1pic_info.primary_ref_frame = ap_ref->slot;
-        ap->av1pic_info.ref_order_hint[ap_ref->slot] = ref->display_order - ap_ref->last_idr_frame;
-        rc_group = VK_VIDEO_ENCODE_AV1_RATE_CONTROL_GROUP_PREDICTIVE_KHR;
-        pred_mode = VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_SINGLE_REFERENCE_KHR;
-        ref_name_mask = enc->caps.singleReferenceNameMask;
-        set_name_slot(ap_ref->av1pic_info.current_frame_id, name_slots, ref_name_mask, 0);
-
-//        vpic->ref_frame_ctrl_l0.fields.search_idx0 = AV1_REF_FRAME_LAST;
-
-        /** set the 2nd nearest frame in L0 as Golden frame. */
-        if ((pic->nb_refs[0] > 1) &&
-            ((enc->caps.maxSingleReferenceCount > 1) ||
-             (enc->caps.maxUnidirectionalCompoundReferenceCount > 0))) {
-            if (enc->caps.maxUnidirectionalCompoundReferenceCount) {
-                pred_mode = VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_UNIDIRECTIONAL_COMPOUND_KHR;
-                ref_name_mask = enc->caps.unidirectionalCompoundReferenceNameMask;
-            }
-            ref = pic->refs[0][pic->nb_refs[0] - 2];
-            ap_ref = ref->codec_priv;
-            ap->av1pic_info.ref_frame_idx[3] = ap_ref->slot;
-            ap->av1pic_info.ref_order_hint[ap_ref->slot] = ref->display_order - ap_ref->last_idr_frame;
-//            vpic->ref_frame_ctrl_l0.fields.search_idx1 = AV1_REF_FRAME_GOLDEN;
-            set_name_slot(ap_ref->av1pic_info.current_frame_id, name_slots, ref_name_mask, 0);
-        }
-        break;
-    case FF_HW_PICTURE_TYPE_B:
-        ap->av1pic_info.frame_type = STD_VIDEO_AV1_FRAME_TYPE_INTER;
-        quantization->base_q_idx = enc->q_idx_b;
-        ap->av1pic_info.refresh_frame_flags = 0x0;
-
-        rc_group = VK_VIDEO_ENCODE_AV1_RATE_CONTROL_GROUP_BIPREDICTIVE_KHR;
-        pred_mode = VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_BIDIRECTIONAL_COMPOUND_KHR;
-        ref_name_mask = enc->caps.bidirectionalCompoundReferenceNameMask;
-
-//        fh->reference_select = 1;
-        /** B frame will not be referenced, disable its recon frame. */
-//        vpic->picture_flags.bits.disable_frame_recon = 1;
-
-        /** Use LAST_FRAME and BWDREF_FRAME for reference. */
-//        vpic->ref_frame_ctrl_l0.fields.search_idx0 = AV1_REF_FRAME_LAST;
-//        vpic->ref_frame_ctrl_l1.fields.search_idx0 = AV1_REF_FRAME_BWDREF;
-
-        ref = pic->refs[0][pic->nb_refs[0] - 1];
-        ap_ref = ref->codec_priv;
-        ap->last_idr_frame = ap_ref->last_idr_frame;
-        ap->av1pic_info.primary_ref_frame = ap_ref->slot;
-        ap->av1pic_info.ref_order_hint[ap_ref->slot] = ref->display_order - ap_ref->last_idr_frame;
-        for (int i = 0; i < AV1_REF_FRAME_GOLDEN; i++)
-            ap->av1pic_info.ref_frame_idx[i] = ap_ref->slot;
-        set_name_slot(ap_ref->av1pic_info.current_frame_id, name_slots, ref_name_mask, 0);
-
-        ref = pic->refs[1][pic->nb_refs[1] - 1];
-        ap_ref = ref->codec_priv;
-        ap->av1pic_info.ref_order_hint[ap_ref->slot] = ref->display_order - ap_ref->last_idr_frame;
-        for (int i = AV1_REF_FRAME_GOLDEN; i < AV1_REFS_PER_FRAME; i++)
-            ap->av1pic_info.ref_frame_idx[i] = ap_ref->slot;
-        set_name_slot(ap_ref->av1pic_info.current_frame_id, name_slots, ref_name_mask, 1);
-        break;
-    }
-
-    ap->av1pic_info.flags.showable_frame = ap->av1pic_info.frame_type != STD_VIDEO_AV1_FRAME_TYPE_KEY;
-    ap->av1pic_info.order_hint = pic->display_order - ap->last_idr_frame;
-
-    ap->vkav1pic_info = (VkVideoEncodeAV1PictureInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_PICTURE_INFO_KHR,
-        .pNext = NULL,
-        .predictionMode = pred_mode,
-        .rateControlGroup = rc_group,
-        .constantQIndex = quantization->base_q_idx,
-        .pStdPictureInfo = &ap->av1pic_info,
-        // .referenceNameSlotIndices is set below
-        .primaryReferenceCdfOnly = 0,
-        .generateObuExtensionHeader = 0,
-    };
-    encode_info->pNext = &ap->vkav1pic_info;
-
-    for (int i = 0; i < FF_ARRAY_ELEMS(ap->vkav1pic_info.referenceNameSlotIndices); i++)
-        ap->vkav1pic_info.referenceNameSlotIndices[i] = name_slots[i];
-
-    ref_slot = (VkVideoReferenceSlotInfoKHR *)encode_info->pSetupReferenceSlot;
-    ref_slot->pNext = &ap->vkav1dpb_info;
-
-    ap->av1dpb_info = (StdVideoEncodeAV1ReferenceInfo) {
-        .flags = (StdVideoEncodeAV1ReferenceInfoFlags) {
-            .disable_frame_end_update_cdf = 0,
-            .segmentation_enabled = 0,
-            /* Reserved */
-        },
-        .RefFrameId = ref_slot->slotIndex,
-        .frame_type = ap->av1pic_info.frame_type,
-        .OrderHint = pic->display_order - ap->last_idr_frame,
-        /* Reserved */
-        .pExtensionHeader = &ap->ext_header,
-    };
-
-    ap->vkav1dpb_info = (VkVideoEncodeAV1DpbSlotInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_DPB_SLOT_INFO_KHR,
-        .pStdReferenceInfo = &ap->av1dpb_info,
-    };
-
-    ap->units_needed = 0;
-    if (pic->type == FF_HW_PICTURE_TYPE_IDR) {
-        AVFrameSideData *sd = NULL;
-        if (enc->unit_elems & UNIT_MASTERING_DISPLAY)
-            sd = av_frame_get_side_data(pic->input_image,
-                                        AV_FRAME_DATA_MASTERING_DISPLAY_METADATA);
-        if (sd) {
-            AVMasteringDisplayMetadata *mdm =
-                (AVMasteringDisplayMetadata *)sd->data;
-            if (mdm->has_primaries && mdm->has_luminance) {
-                AV1RawOBU              *obu = &enc->meta_mastering_obu;
-                AV1RawMetadata          *md = &obu->obu.metadata;
-                AV1RawMetadataHDRMDCV *mdcv = &md->metadata.hdr_mdcv;
-                const int        chroma_den = 1 << 16;
-                const int      max_luma_den = 1 << 8;
-                const int      min_luma_den = 1 << 14;
-
-                memset(obu, 0, sizeof(*obu));
-                obu->header.obu_type = AV1_OBU_METADATA;
-                md->metadata_type = AV1_METADATA_TYPE_HDR_MDCV;
-
-                for (int i = 0; i < 3; i++) {
-                    mdcv->primary_chromaticity_x[i] =
-                        av_rescale(mdm->display_primaries[i][0].num, chroma_den,
-                                   mdm->display_primaries[i][0].den);
-                    mdcv->primary_chromaticity_y[i] =
-                        av_rescale(mdm->display_primaries[i][1].num, chroma_den,
-                                   mdm->display_primaries[i][1].den);
-                }
-
-                mdcv->white_point_chromaticity_x =
-                    av_rescale(mdm->white_point[0].num, chroma_den,
-                               mdm->white_point[0].den);
-                mdcv->white_point_chromaticity_y =
-                    av_rescale(mdm->white_point[1].num, chroma_den,
-                               mdm->white_point[1].den);
-
-                mdcv->luminance_max =
-                    av_rescale(mdm->max_luminance.num, max_luma_den,
-                               mdm->max_luminance.den);
-                mdcv->luminance_min =
-                    av_rescale(mdm->min_luminance.num, min_luma_den,
-                               mdm->min_luminance.den);
-                ap->units_needed |= UNIT_MASTERING_DISPLAY;
-            }
-        }
-
-        if (enc->unit_elems & UNIT_CONTENT_LIGHT_LEVEL)
-            sd = av_frame_get_side_data(pic->input_image,
-                                        AV_FRAME_DATA_CONTENT_LIGHT_LEVEL);
-        if (sd) {
-            AVContentLightMetadata *cllm = (AVContentLightMetadata *)sd->data;
-            AV1RawOBU               *obu = &enc->meta_cll_obu;
-            AV1RawMetadata           *md = &obu->obu.metadata;
-            AV1RawMetadataHDRCLL    *cll = &md->metadata.hdr_cll;
-
-            memset(obu, 0, sizeof(*obu));
-            obu->header.obu_type = AV1_OBU_METADATA;
-            md->metadata_type    = AV1_METADATA_TYPE_HDR_CLL;
-            cll->max_cll         = cllm->MaxCLL;
-            cll->max_fall        = cllm->MaxFALL;
-
-            ap->units_needed |= UNIT_CONTENT_LIGHT_LEVEL;
-        }
-    }
-
-    return 0;
-}
-
-static int init_profile(AVCodecContext *avctx,
-                        VkVideoProfileInfoKHR *profile, void *pnext)
-{
-    VkResult ret;
-    VulkanEncodeAV1Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext *ctx = &enc->common;
-    FFVulkanContext *s = &ctx->s;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-    FFHWBaseEncodeContext *base_ctx = &ctx->base;
-
-    VkVideoEncodeAV1CapabilitiesKHR av1_caps = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_CAPABILITIES_KHR,
-    };
-    VkVideoEncodeCapabilitiesKHR enc_caps = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR,
-        .pNext = &av1_caps,
-    };
-    VkVideoCapabilitiesKHR caps = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR,
-        .pNext = &enc_caps,
-    };
-
-    /* In order of preference */
-    int last_supported = AV_PROFILE_UNKNOWN;
-    static const int known_profiles[] = {
-        AV_PROFILE_AV1_MAIN,
-        AV_PROFILE_AV1_HIGH,
-        AV_PROFILE_AV1_PROFESSIONAL,
-    };
-    int nb_profiles = FF_ARRAY_ELEMS(known_profiles);
-
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->frames->sw_format);
-    if (!desc)
-        return AVERROR(EINVAL);
-
-    if (s->frames->sw_format == AV_PIX_FMT_NV12 ||
-        s->frames->sw_format == AV_PIX_FMT_P010)
-        nb_profiles = 1;
-
-    enc->profile = (VkVideoEncodeAV1ProfileInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_PROFILE_INFO_KHR,
-        .pNext = pnext,
-        .stdProfile = ff_vk_av1_profile_to_vk(avctx->profile),
-    };
-    profile->pNext = &enc->profile;
-
-    /* Set level */
-    if (avctx->level == AV_LEVEL_UNKNOWN) {
-        const AV1LevelDescriptor *level;
-        float framerate = 0.0;
-
-        if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
-            framerate = av_q2d(avctx->framerate);
-
-        level = ff_av1_guess_level(avctx->bit_rate, enc->seq_tier,
-                                   base_ctx->surface_width, base_ctx->surface_height,
-                                   enc->tile_rows * enc->tile_cols,
-                                   enc->tile_cols, framerate);
-        if (level) {
-            av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name);
-            enc->seq_level_idx = ff_vk_av1_level_to_vk(level->level_idx);
-        } else {
-            av_log(avctx, AV_LOG_VERBOSE, "Stream will not conform to "
-                   "any normal level, using level 7.3 by default.\n");
-            enc->seq_level_idx = STD_VIDEO_AV1_LEVEL_7_3;
-            enc->seq_tier = 1;
-        }
-    } else {
-        enc->seq_level_idx = ff_vk_av1_level_to_vk(avctx->level);
-    }
-
-    /* User has explicitly specified a profile. */
-    if (avctx->profile != AV_PROFILE_UNKNOWN)
-        return 0;
-
-    av_log(avctx, AV_LOG_DEBUG, "Supported profiles:\n");
-    for (int i = 0; i < nb_profiles; i++) {
-        enc->profile.stdProfile = ff_vk_av1_profile_to_vk(known_profiles[i]);
-        ret = vk->GetPhysicalDeviceVideoCapabilitiesKHR(s->hwctx->phys_dev,
-                                                        profile,
-                                                        &caps);
-        if (ret == VK_SUCCESS) {
-            av_log(avctx, AV_LOG_DEBUG, "    %s\n",
-                   avcodec_profile_name(avctx->codec_id, known_profiles[i]));
-            last_supported = known_profiles[i];
-        }
-    }
-
-    if (last_supported == AV_PROFILE_UNKNOWN) {
-        av_log(avctx, AV_LOG_ERROR, "No supported profiles for given format\n");
-        return AVERROR(ENOTSUP);
-    }
-
-    enc->profile.stdProfile = ff_vk_av1_profile_to_vk(last_supported);
-    av_log(avctx, AV_LOG_VERBOSE, "Using profile %s\n",
-           avcodec_profile_name(avctx->codec_id, last_supported));
-    avctx->profile = last_supported;
-
-    return 0;
-}
-
-static int init_enc_options(AVCodecContext *avctx)
-{
-    VulkanEncodeAV1Context *enc = avctx->priv_data;
-
-    if (avctx->rc_buffer_size)
-        enc->hrd_buffer_size = avctx->rc_buffer_size;
-    else if (avctx->rc_max_rate > 0)
-        enc->hrd_buffer_size = avctx->rc_max_rate;
-    else
-        enc->hrd_buffer_size = avctx->bit_rate;
-
-    if (avctx->rc_initial_buffer_occupancy) {
-        if (avctx->rc_initial_buffer_occupancy > enc->hrd_buffer_size) {
-            av_log(avctx, AV_LOG_ERROR, "Invalid RC buffer settings: "
-                                        "must have initial buffer size (%d) <= "
-                                        "buffer size (%"PRId64").\n",
-                   avctx->rc_initial_buffer_occupancy, enc->hrd_buffer_size);
-            return AVERROR(EINVAL);
-        }
-        enc->initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
-    } else {
-        enc->initial_buffer_fullness = enc->hrd_buffer_size * 3 / 4;
-    }
-
-    if (enc->common.opts.rc_mode == VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
-        enc->q_idx_p = av_clip(enc->common.opts.qp,
-                               enc->caps.minQIndex, enc->caps.maxQIndex);
-        if (fabs(avctx->i_quant_factor) > 0.0)
-            enc->q_idx_idr =
-                av_clip((fabs(avctx->i_quant_factor) * enc->q_idx_p  +
-                         avctx->i_quant_offset) + 0.5,
-                        0, 255);
-        else
-            enc->q_idx_idr = enc->q_idx_p;
-
-        if (fabs(avctx->b_quant_factor) > 0.0)
-            enc->q_idx_b =
-                av_clip((fabs(avctx->b_quant_factor) * enc->q_idx_p  +
-                         avctx->b_quant_offset) + 0.5,
-                        0, 255);
-        else
-            enc->q_idx_b = enc->q_idx_p;
-    } else {
-        /** Arbitrary value */
-        enc->q_idx_idr = enc->q_idx_p = enc->q_idx_b = 128;
-    }
-
-    return 0;
-}
-
-static av_cold int init_sequence_headers(AVCodecContext *avctx)
-{
-    VulkanEncodeAV1Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext *ctx = &enc->common;
-    FFVulkanContext *s = &ctx->s;
-    FFHWBaseEncodeContext *base_ctx = &ctx->base;
-
-    AV1RawOBU *seq_obu = &enc->seq_hdr_obu;
-    AV1RawSequenceHeader *seq = &seq_obu->obu.sequence_header;
-
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->frames->sw_format);
-    if (!desc)
-        return AVERROR(EINVAL);
-
-    seq_obu->header.obu_type = AV1_OBU_SEQUENCE_HEADER;
-    *seq = (AV1RawSequenceHeader) {
-        .seq_profile = avctx->profile,
-        .seq_force_integer_mv = seq->seq_force_screen_content_tools ?
-                                AV1_SELECT_SCREEN_CONTENT_TOOLS :
-                                AV1_SELECT_INTEGER_MV,
-        .frame_width_bits_minus_1 = av_log2(base_ctx->surface_width),
-        .frame_height_bits_minus_1 = av_log2(base_ctx->surface_height),
-        .max_frame_width_minus_1 = base_ctx->surface_width - 1,
-        .max_frame_height_minus_1 = base_ctx->surface_height - 1,
-        .enable_order_hint = 1,
-        .order_hint_bits_minus_1 = av_clip_intp2(av_log2(ctx->base.gop_size), 3),
-        .use_128x128_superblock = !!(enc->caps.superblockSizes & VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_128_BIT_KHR),
-        .color_config = (AV1RawColorConfig) {
-            .high_bitdepth = desc->comp[0].depth > 8,
-            .color_primaries                = avctx->color_primaries,
-            .transfer_characteristics       = avctx->color_trc,
-            .matrix_coefficients            = avctx->colorspace,
-            .color_description_present_flag = (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED ||
-                                               avctx->color_trc       != AVCOL_TRC_UNSPECIFIED ||
-                                               avctx->colorspace      != AVCOL_SPC_UNSPECIFIED),
-            .subsampling_x                  = desc->log2_chroma_w,
-            .subsampling_y                  = desc->log2_chroma_h,
-            .chroma_sample_position         = avctx->chroma_sample_location == AVCHROMA_LOC_LEFT ?
-                                              AV1_CSP_VERTICAL :
-                                              avctx->chroma_sample_location == AVCHROMA_LOC_TOPLEFT ?
-                                              AV1_CSP_COLOCATED :
-                                              AV1_CSP_UNKNOWN,
-        },
-
-        /* Operating point */
-        .seq_tier = { enc->seq_tier },
-        .seq_level_idx = { enc->seq_level_idx },
-        .decoder_buffer_delay = { base_ctx->decode_delay },
-        .encoder_buffer_delay = { base_ctx->output_delay },
-        .operating_points_cnt_minus_1 = 1 - 1,
-    };
-
-    return 0;
-}
-
-typedef struct VulkanAV1Units {
-    StdVideoAV1SequenceHeader seq_hdr;
-    StdVideoAV1TimingInfo timing_info;
-    StdVideoAV1ColorConfig color_config;
-
-    StdVideoEncodeAV1DecoderModelInfo decoder_model;
-    StdVideoEncodeAV1OperatingPointInfo operating_points[AV1_MAX_OPERATING_POINTS];
-    int nb_operating_points;
-} VulkanAV1Units;
-
-static av_cold int base_unit_to_vk(AVCodecContext *avctx, VulkanAV1Units *vk_units)
-{
-    VulkanEncodeAV1Context *enc = avctx->priv_data;
-
-    AV1RawOBU *seq_obu = &enc->seq_hdr_obu;
-    AV1RawSequenceHeader *seq = &seq_obu->obu.sequence_header;
-
-    StdVideoAV1SequenceHeader *seq_hdr = &vk_units->seq_hdr;
-    StdVideoAV1TimingInfo *timing_info = &vk_units->timing_info;
-    StdVideoAV1ColorConfig *color_config = &vk_units->color_config;
-
-    StdVideoEncodeAV1OperatingPointInfo *operating_points = vk_units->operating_points;
-
-    *timing_info = (StdVideoAV1TimingInfo) {
-        .flags = (StdVideoAV1TimingInfoFlags) {
-            .equal_picture_interval = seq->timing_info.equal_picture_interval,
-        },
-        .num_units_in_display_tick = seq->timing_info.num_units_in_display_tick,
-        .time_scale = seq->timing_info.time_scale,
-        .num_ticks_per_picture_minus_1 = seq->timing_info.num_ticks_per_picture_minus_1,
-    };
-
-    *color_config = (StdVideoAV1ColorConfig) {
-        .flags = (StdVideoAV1ColorConfigFlags) {
-            .mono_chrome = seq->color_config.mono_chrome,
-            .color_range = seq->color_config.color_range,
-            .separate_uv_delta_q = seq->color_config.separate_uv_delta_q,
-        },
-        .BitDepth = seq->color_config.twelve_bit    ? 12 :
-                    seq->color_config.high_bitdepth ? 10 : 8,
-        .subsampling_x = seq->color_config.subsampling_x,
-        .subsampling_y = seq->color_config.subsampling_y,
-        .color_primaries = seq->color_config.color_primaries,
-        .transfer_characteristics = seq->color_config.transfer_characteristics,
-        .matrix_coefficients = seq->color_config.matrix_coefficients,
-    };
-
-    *seq_hdr = (StdVideoAV1SequenceHeader) {
-        .flags = (StdVideoAV1SequenceHeaderFlags) {
-            .still_picture = seq->still_picture,
-            .reduced_still_picture_header = seq->reduced_still_picture_header,
-            .use_128x128_superblock = seq->use_128x128_superblock,
-            .enable_filter_intra = seq->enable_filter_intra,
-            .enable_intra_edge_filter = seq->enable_intra_edge_filter,
-            .enable_interintra_compound = seq->enable_interintra_compound,
-            .enable_masked_compound = seq->enable_masked_compound,
-            .enable_warped_motion = seq->enable_warped_motion,
-            .enable_dual_filter = seq->enable_dual_filter,
-            .enable_order_hint = seq->enable_order_hint,
-            .enable_jnt_comp = seq->enable_jnt_comp,
-            .enable_ref_frame_mvs = seq->enable_ref_frame_mvs,
-            .frame_id_numbers_present_flag = seq->frame_id_numbers_present_flag,
-            .enable_superres = seq->enable_superres,
-            .enable_cdef = seq->enable_cdef,
-            .enable_restoration = seq->enable_restoration,
-            .film_grain_params_present = seq->film_grain_params_present,
-            .timing_info_present_flag = seq->timing_info_present_flag,
-            .initial_display_delay_present_flag = seq->initial_display_delay_present_flag,
-        },
-        .seq_profile = seq->seq_profile,
-        .frame_width_bits_minus_1 = seq->frame_width_bits_minus_1,
-        .frame_height_bits_minus_1 = seq->frame_height_bits_minus_1,
-        .max_frame_width_minus_1 = seq->max_frame_width_minus_1,
-        .max_frame_height_minus_1 = seq->max_frame_height_minus_1,
-        .delta_frame_id_length_minus_2 = seq->delta_frame_id_length_minus_2,
-        .additional_frame_id_length_minus_1 = seq->additional_frame_id_length_minus_1,
-        .order_hint_bits_minus_1 = seq->order_hint_bits_minus_1,
-        .seq_force_integer_mv = seq->seq_force_integer_mv,
-        .seq_force_screen_content_tools = seq->seq_force_screen_content_tools,
-        .pTimingInfo = timing_info,
-        .pColorConfig = color_config,
-    };
-
-    for (int i = 0; i <= seq->operating_points_cnt_minus_1; i++) {
-        operating_points[i] = (StdVideoEncodeAV1OperatingPointInfo) {
-            .flags = (StdVideoEncodeAV1OperatingPointInfoFlags) {
-                .decoder_model_present_for_this_op = seq->decoder_model_present_for_this_op[i],
-                .low_delay_mode_flag = seq->low_delay_mode_flag[i],
-                .initial_display_delay_present_for_this_op = seq->initial_display_delay_present_for_this_op[i],
-                /* Reserved */
-            },
-            .operating_point_idc = seq->operating_point_idc[i],
-            .seq_level_idx = seq->seq_level_idx[i],
-            .seq_tier = seq->seq_tier[i],
-            .decoder_buffer_delay = seq->decoder_buffer_delay[i],
-            .encoder_buffer_delay = seq->encoder_buffer_delay[i],
-            .initial_display_delay_minus_1 = seq->initial_display_delay_minus_1[i],
-        };
-    }
-    vk_units->nb_operating_points = seq->operating_points_cnt_minus_1 + 1;
-
-    return 0;
-}
-
-static int create_session_params(AVCodecContext *avctx)
-{
-    int err;
-    VulkanEncodeAV1Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext *ctx = &enc->common;
-    FFVulkanContext *s = &ctx->s;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-
-    VulkanAV1Units vk_units = { 0 };
-
-    VkVideoEncodeAV1SessionParametersCreateInfoKHR av1_params;
-
-    /* Convert it to Vulkan */
-    err = base_unit_to_vk(avctx, &vk_units);
-    if (err < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to convert sequence header to Vulkan: %s\n",
-               av_err2str(err));
-        return err;
-    }
-
-    /* Destroy the session params */
-    if (ctx->session_params)
-        vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
-                                             ctx->session_params,
-                                             s->hwctx->alloc);
-
-    av1_params = (VkVideoEncodeAV1SessionParametersCreateInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR,
-        .pStdSequenceHeader = &vk_units.seq_hdr,
-        .pStdDecoderModelInfo = &vk_units.decoder_model,
-        .pStdOperatingPoints = vk_units.operating_points,
-        .stdOperatingPointCount = vk_units.nb_operating_points,
-    };
-
-    return ff_vulkan_encode_create_session_params(avctx, ctx, &av1_params);
-}
-
-static int parse_feedback_units(AVCodecContext *avctx,
-                                const uint8_t *data, size_t size)
-{
-    int err;
-    VulkanEncodeAV1Context *enc = avctx->priv_data;
-    AV1RawOBU *seq_obu = &enc->seq_hdr_obu;
-    AV1RawSequenceHeader *seq = &seq_obu->obu.sequence_header;
-
-    CodedBitstreamContext *cbs;
-    CodedBitstreamFragment obu = { 0 };
-
-    err = ff_cbs_init(&cbs, AV_CODEC_ID_AV1, avctx);
-    if (err < 0)
-        return err;
-
-    err = ff_cbs_read(cbs, &obu, NULL, data, size);
-    if (err < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to parse feedback units, bad drivers: %s\n",
-               av_err2str(err));
-        return err;
-    }
-
-    /* If PPS has an override, just copy it entirely. */
-    for (int i = 0; i < obu.nb_units; i++) {
-        if (obu.units[i].type == AV1_OBU_SEQUENCE_HEADER) {
-            AV1RawOBU *f_seq_obu = obu.units[i].content;
-            AV1RawSequenceHeader *f_seq = &f_seq_obu->obu.sequence_header;
-            seq->frame_width_bits_minus_1 = f_seq->frame_width_bits_minus_1;
-            seq->frame_height_bits_minus_1 = f_seq->frame_height_bits_minus_1;
-            seq->max_frame_width_minus_1 = f_seq->max_frame_width_minus_1;
-            seq->max_frame_height_minus_1 = f_seq->max_frame_height_minus_1;
-            seq->seq_choose_screen_content_tools = f_seq->seq_choose_screen_content_tools;
-            seq->seq_force_screen_content_tools = f_seq->seq_force_screen_content_tools;
-            seq->seq_choose_integer_mv = f_seq->seq_choose_integer_mv;
-            seq->seq_force_integer_mv = f_seq->seq_force_integer_mv;
-        }
-    }
-
-    ff_cbs_fragment_free(&obu);
-    ff_cbs_close(&cbs);
-
-    return 0;
-}
-
-static int init_base_units(AVCodecContext *avctx)
-{
-    int err;
-    VkResult ret;
-    VulkanEncodeAV1Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext *ctx = &enc->common;
-    FFVulkanContext *s = &ctx->s;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-
-    VkVideoEncodeSessionParametersGetInfoKHR params_info;
-    VkVideoEncodeSessionParametersFeedbackInfoKHR params_feedback;
-
-    void *data = NULL;
-    size_t data_size = 0;
-
-    /* Generate SPS/PPS unit info */
-    err = init_sequence_headers(avctx);
-    if (err < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to initialize sequence header: %s\n",
-               av_err2str(err));
-        return err;
-    }
-
-    /* Create session parameters from them */
-    err = create_session_params(avctx);
-    if (err < 0)
-        return err;
-
-    params_info = (VkVideoEncodeSessionParametersGetInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_GET_INFO_KHR,
-        .videoSessionParameters = ctx->session_params,
-    };
-    params_feedback = (VkVideoEncodeSessionParametersFeedbackInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_FEEDBACK_INFO_KHR,
-    };
-
-    ret = vk->GetEncodedVideoSessionParametersKHR(s->hwctx->act_dev, &params_info,
-                                                  &params_feedback,
-                                                  &data_size, data);
-    if (ret == VK_INCOMPLETE ||
-        (ret == VK_SUCCESS) && (data_size > 0)) {
-        data = av_mallocz(data_size);
-        if (!data)
-            return AVERROR(ENOMEM);
-    } else {
-        av_log(avctx, AV_LOG_ERROR, "Unable to get feedback for AV1 sequence header = %"SIZE_SPECIFIER"\n",
-               data_size);
-        return err;
-    }
-
-    ret = vk->GetEncodedVideoSessionParametersKHR(s->hwctx->act_dev, &params_info,
-                                                  &params_feedback,
-                                                  &data_size, data);
-    if (ret != VK_SUCCESS) {
-        av_log(avctx, AV_LOG_ERROR, "Error writing feedback units\n");
-        return err;
-    }
-
-    av_log(avctx, AV_LOG_VERBOSE, "Feedback units written, overrides: %i\n",
-           params_feedback.hasOverrides);
-
-    params_feedback.hasOverrides = 1;
-
-    /* No need to sync any overrides */
-    if (!params_feedback.hasOverrides)
-        return 0;
-
-    /* Parse back tne units and override */
-    err = parse_feedback_units(avctx, data, data_size);
-    if (err < 0)
-        return err;
-
-    /* Create final session parameters */
-    err = create_session_params(avctx);
-    if (err < 0)
-        return err;
-
-    return 0;
-}
-
-static int vulkan_encode_av1_add_obu(AVCodecContext *avctx,
-                                     CodedBitstreamFragment *au,
-                                     uint8_t type, void *obu_unit)
-{
-    int err;
-
-    err = ff_cbs_insert_unit_content(au, -1,
-                                     type, obu_unit, NULL);
-    if (err < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Failed to add OBU unit: "
-               "type = %d.\n", type);
-        return err;
-    }
-
-    return err;
-}
-
-static int vulkan_encode_av1_write_obu(AVCodecContext *avctx,
-                                       uint8_t *data, size_t *data_len,
-                                       CodedBitstreamFragment *obu)
-{
-    VulkanEncodeAV1Context *enc = avctx->priv_data;
-    int ret;
-
-    ret = ff_cbs_write_fragment_data(enc->cbs, obu);
-    if (ret < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n");
-        return ret;
-    }
-
-    memcpy(data, obu->data, obu->data_size);
-    *data_len = obu->data_size;
-
-    return 0;
-}
-
-static int write_sequence_header(AVCodecContext *avctx,
-                                 FFHWBaseEncodePicture *base_pic,
-                                 uint8_t *data, size_t *data_len)
-{
-    int err;
-    VulkanEncodeAV1Context *enc = avctx->priv_data;
-    CodedBitstreamFragment *obu = &enc->current_access_unit;
-
-    err = vulkan_encode_av1_add_obu(avctx, obu,
-                                    AV1_OBU_SEQUENCE_HEADER, &enc->seq_hdr_obu);
-    if (err < 0)
-        goto fail;
-
-    err = vulkan_encode_av1_write_obu(avctx, data, data_len, obu);
-
-fail:
-    ff_cbs_fragment_reset(obu);
-    return err;
-}
-
-static int write_extra_headers(AVCodecContext *avctx,
-                               FFHWBaseEncodePicture *base_pic,
-                               uint8_t *data, size_t *data_len)
-{
-    int err;
-    VulkanEncodeAV1Context *enc = avctx->priv_data;
-    VulkanEncodeAV1Picture  *ap = base_pic->codec_priv;
-    CodedBitstreamFragment *obu = &enc->current_access_unit;
-
-    if (ap->units_needed & AV_FRAME_DATA_MASTERING_DISPLAY_METADATA) {
-        err = vulkan_encode_av1_add_obu(avctx, obu,
-                                        AV1_OBU_METADATA,
-                                        &enc->meta_mastering_obu);
-        if (err < 0)
-            goto fail;
-    }
-
-    if (ap->units_needed & UNIT_CONTENT_LIGHT_LEVEL) {
-        err = vulkan_encode_av1_add_obu(avctx, obu,
-                                        AV1_OBU_METADATA,
-                                        &enc->meta_cll_obu);
-        if (err < 0)
-            goto fail;
-    }
-
-    if (ap->units_needed) {
-        err = vulkan_encode_av1_write_obu(avctx, data, data_len, obu);
-        if (err < 0)
-            goto fail;
-    } else {
-        err = 0;
-        *data_len = 0;
-    }
-
-fail:
-    ff_cbs_fragment_reset(obu);
-    return err;
-}
-
-static int write_padding(AVCodecContext *avctx, uint32_t padding,
-                         uint8_t *data, size_t *data_len)
-{
-    int err;
-    VulkanEncodeAV1Context *enc = avctx->priv_data;
-    CodedBitstreamFragment *obu = &enc->current_access_unit;
-
-    AV1RawOBU padding_obu = { 0 };
-    AV1RawPadding *raw_padding = &padding_obu.obu.padding;
-
-    if (!padding)
-        padding = 16;
-
-    /* 2 byte header + 1 byte trailing bits */
-    padding_obu.header.obu_type = AV1_OBU_PADDING;
-    *raw_padding = (AV1RawPadding) {
-        .payload = enc->padding_payload,
-        .payload_size = padding,
-    };
-
-    err = vulkan_encode_av1_add_obu(avctx, obu, AV1_OBU_PADDING, &padding_obu);
-    if (err < 0)
-        goto fail;
-
-    err = vulkan_encode_av1_write_obu(avctx, data, data_len, obu);
-fail:
-    ff_cbs_fragment_reset(obu);
-    return err;
-}
-
-static const FFVulkanCodec enc_cb = {
-    .flags = FF_HW_FLAG_B_PICTURES |
-             FF_HW_FLAG_B_PICTURE_REFERENCES |
-             VK_ENC_FLAG_NO_DELAY |
-             FF_HW_FLAG_SLICE_CONTROL,
-    .picture_priv_data_size = sizeof(VulkanEncodeAV1Picture),
-    .filler_header_size = 4,
-    .init_profile = init_profile,
-    .init_pic_rc = init_pic_rc,
-    .init_pic_params = init_pic_params,
-    .write_sequence_headers = write_sequence_header,
-    .write_extra_headers = write_extra_headers,
-    .write_filler = write_padding,
-};
-
-static av_cold int vulkan_encode_av1_init(AVCodecContext *avctx)
-{
-    int err;
-    VulkanEncodeAV1Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext *ctx = &enc->common;
-    FFHWBaseEncodeContext *base_ctx = &ctx->base;
-    int flags;
-
-    if (avctx->profile == AV_PROFILE_UNKNOWN)
-        avctx->profile = enc->common.opts.profile;
-
-    enc->caps = (VkVideoEncodeAV1CapabilitiesKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_CAPABILITIES_KHR,
-    };
-
-    enc->quality_props = (VkVideoEncodeAV1QualityLevelPropertiesKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_QUALITY_LEVEL_PROPERTIES_KHR,
-    };
-
-    err = ff_vulkan_encode_init(avctx, &enc->common,
-                                &ff_vk_enc_av1_desc, &enc_cb,
-                                &enc->caps, &enc->quality_props);
-    if (err < 0)
-        return err;
-
-    av_log(avctx, AV_LOG_VERBOSE, "AV1 encoder capabilities:\n");
-    av_log(avctx, AV_LOG_VERBOSE, "    Standard capability flags:\n");
-    av_log(avctx, AV_LOG_VERBOSE, "        per_rate_control_group_min_max_q_index: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_AV1_CAPABILITY_PER_RATE_CONTROL_GROUP_MIN_MAX_Q_INDEX_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        generate_obu_extension_header: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_AV1_CAPABILITY_GENERATE_OBU_EXTENSION_HEADER_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        primary_reference_cdf_only: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_AV1_CAPABILITY_PRIMARY_REFERENCE_CDF_ONLY_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        frame_size_override: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_AV1_CAPABILITY_FRAME_SIZE_OVERRIDE_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        motion_vector_scaling: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_AV1_CAPABILITY_MOTION_VECTOR_SCALING_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "    Capabilities:\n");
-    av_log(avctx, AV_LOG_VERBOSE, "        64x64 superblocks: %i\n",
-           !!(enc->caps.superblockSizes & VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_64_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        128x128 superblocks: %i\n",
-           !!(enc->caps.superblockSizes & VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_128_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        maxSingleReferenceCount: %i\n",
-           enc->caps.maxSingleReferenceCount);
-    av_log(avctx, AV_LOG_VERBOSE, "        singleReferenceNameMask: 0x%x\n",
-           enc->caps.singleReferenceNameMask);
-    av_log(avctx, AV_LOG_VERBOSE, "        maxUnidirectionalCompoundReferenceCount: %i\n",
-           enc->caps.maxUnidirectionalCompoundReferenceCount);
-    av_log(avctx, AV_LOG_VERBOSE, "        maxUnidirectionalCompoundGroup1ReferenceCount: %i\n",
-           enc->caps.maxUnidirectionalCompoundGroup1ReferenceCount);
-    av_log(avctx, AV_LOG_VERBOSE, "        unidirectionalCompoundReferenceNameMask: 0x%x\n",
-           enc->caps.unidirectionalCompoundReferenceNameMask);
-    av_log(avctx, AV_LOG_VERBOSE, "        maxBidirectionalCompoundReferenceCount: %i\n",
-           enc->caps.maxBidirectionalCompoundReferenceCount);
-    av_log(avctx, AV_LOG_VERBOSE, "        maxBidirectionalCompoundGroup1ReferenceCount: %i\n",
-           enc->caps.maxBidirectionalCompoundGroup1ReferenceCount);
-    av_log(avctx, AV_LOG_VERBOSE, "        maxBidirectionalCompoundGroup2ReferenceCount: %i\n",
-           enc->caps.maxBidirectionalCompoundGroup2ReferenceCount);
-    av_log(avctx, AV_LOG_VERBOSE, "        bidirectionalCompoundReferenceNameMask: 0x%x\n",
-           enc->caps.bidirectionalCompoundReferenceNameMask);
-    av_log(avctx, AV_LOG_VERBOSE, "        maxTemporalLayerCount: %i\n",
-           enc->caps.maxTemporalLayerCount);
-    av_log(avctx, AV_LOG_VERBOSE, "        maxSpatialLayerCount: %i\n",
-           enc->caps.maxSpatialLayerCount);
-    av_log(avctx, AV_LOG_VERBOSE, "        maxOperatingPoints: %i\n",
-           enc->caps.maxOperatingPoints);
-    av_log(avctx, AV_LOG_VERBOSE, "        min/max Qindex: [%i, %i]\n",
-           enc->caps.minQIndex, enc->caps.maxQIndex);
-    av_log(avctx, AV_LOG_VERBOSE, "        prefersGopRemainingFrames: %i\n",
-           enc->caps.prefersGopRemainingFrames);
-    av_log(avctx, AV_LOG_VERBOSE, "        requiresGopRemainingFrames: %i\n",
-           enc->caps.requiresGopRemainingFrames);
-    av_log(avctx, AV_LOG_VERBOSE, "        maxLevel: %i\n",
-           enc->caps.maxLevel);
-    av_log(avctx, AV_LOG_VERBOSE, "        codedPictureAlignment: %ix%i\n",
-           enc->caps.codedPictureAlignment.width, enc->caps.codedPictureAlignment.height);
-    av_log(avctx, AV_LOG_VERBOSE, "        maxTiles: %ix%i\n",
-           enc->caps.maxTiles.width, enc->caps.maxTiles.height);
-    av_log(avctx, AV_LOG_VERBOSE, "        Tile size: %ix%i to %ix%i\n",
-           enc->caps.minTileSize.width, enc->caps.minTileSize.height,
-           enc->caps.maxTileSize.width, enc->caps.maxTileSize.height);
-
-    err = init_enc_options(avctx);
-    if (err < 0)
-        return err;
-
-    flags = ctx->codec->flags;
-    err = ff_hw_base_init_gop_structure(base_ctx, avctx,
-                                        ctx->caps.maxDpbSlots,
-                                        enc->caps.maxBidirectionalCompoundReferenceCount,
-                                        flags, 0);
-    if (err < 0)
-        return err;
-
-    base_ctx->output_delay = base_ctx->b_per_p;
-    base_ctx->decode_delay = base_ctx->max_b_depth;
-
-    /* Create units and session parameters */
-    err = init_base_units(avctx);
-    if (err < 0)
-        return err;
-
-    /* Init CBS */
-    err = ff_cbs_init(&enc->cbs, AV_CODEC_ID_AV1, avctx);
-    if (err < 0)
-        return err;
-
-    if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
-        uint8_t data[4096];
-        size_t data_len = sizeof(data);
-
-        err = write_sequence_header(avctx, NULL, data, &data_len);
-        if (err < 0) {
-            av_log(avctx, AV_LOG_ERROR, "Failed to write sequence header "
-                   "for extradata: %d.\n", err);
-            return err;
-        } else {
-            avctx->extradata_size = data_len;
-            avctx->extradata = av_mallocz(avctx->extradata_size +
-                                          AV_INPUT_BUFFER_PADDING_SIZE);
-            if (!avctx->extradata) {
-                err = AVERROR(ENOMEM);
-                return err;
-            }
-            memcpy(avctx->extradata, data, avctx->extradata_size);
-        }
-    }
-
-    enc->padding_payload = av_mallocz(2*ctx->caps.minBitstreamBufferOffsetAlignment);
-    if (!enc->padding_payload)
-        return AVERROR(ENOMEM);
-
-    memset(enc->padding_payload, 0xaa, 2*ctx->caps.minBitstreamBufferOffsetAlignment);
-
-    return 0;
-}
-
-static av_cold int vulkan_encode_av1_close(AVCodecContext *avctx)
-{
-    VulkanEncodeAV1Context *enc = avctx->priv_data;
-    av_free(enc->padding_payload);
-    ff_vulkan_encode_uninit(&enc->common);
-    return 0;
-}
-
-#define OFFSET(x) offsetof(VulkanEncodeAV1Context, x)
-#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
-static const AVOption vulkan_encode_av1_options[] = {
-    HW_BASE_ENCODE_COMMON_OPTIONS,
-    VULKAN_ENCODE_COMMON_OPTIONS,
-
-    { "profile", "Set profile",
-      OFFSET(common.opts.profile), AV_OPT_TYPE_INT,
-      { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, 0xffff, FLAGS, .unit = "profile" },
-
-#define PROFILE(name, value)  name, NULL, 0, AV_OPT_TYPE_CONST, \
-      { .i64 = value }, 0, 0, FLAGS, .unit = "profile"
-    { PROFILE("main",                 AV_PROFILE_AV1_MAIN) },
-    { PROFILE("high",                 AV_PROFILE_AV1_HIGH) },
-    { PROFILE("professional",         AV_PROFILE_AV1_PROFESSIONAL) },
-#undef PROFILE
-
-    { "tier", "Set tier (seq_tier)",
-      OFFSET(common.opts.tier), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, .unit = "tier" },
-        { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, .unit = "tier" },
-        { "high", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, .unit = "tier" },
-
-    { "level", "Set level (level_idc)",
-      OFFSET(common.opts.level), AV_OPT_TYPE_INT,
-      { .i64 = AV_LEVEL_UNKNOWN }, AV_LEVEL_UNKNOWN, 0xff, FLAGS, .unit = "level" },
-
-#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
-      { .i64 = value }, 0, 0, FLAGS, .unit = "level"
-    { LEVEL("20", 0) },
-    { LEVEL("21", 1) },
-    { LEVEL("22", 2) },
-    { LEVEL("23", 3) },
-    { LEVEL("30", 4) },
-    { LEVEL("31", 5) },
-    { LEVEL("32", 6) },
-    { LEVEL("33", 7) },
-    { LEVEL("40", 8) },
-    { LEVEL("41", 9) },
-    { LEVEL("42", 10) },
-    { LEVEL("43", 11) },
-    { LEVEL("50", 12) },
-    { LEVEL("51", 13) },
-    { LEVEL("52", 14) },
-    { LEVEL("53", 15) },
-    { LEVEL("60", 16) },
-    { LEVEL("61", 17) },
-    { LEVEL("62", 18) },
-    { LEVEL("63", 19) },
-    { LEVEL("70", 20) },
-    { LEVEL("71", 21) },
-    { LEVEL("72", 22) },
-    { LEVEL("73", 23) },
-#undef LEVEL
-
-    { "units", "Set units to include", OFFSET(unit_elems), AV_OPT_TYPE_FLAGS, { .i64 = UNIT_MASTERING_DISPLAY | UNIT_CONTENT_LIGHT_LEVEL }, 0, INT_MAX, FLAGS, "units" },
-        { "hdr",        "Include HDR metadata for mastering display colour volume and content light level information", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_MASTERING_DISPLAY | UNIT_CONTENT_LIGHT_LEVEL }, INT_MIN, INT_MAX, FLAGS, "units" },
-
-    { NULL },
-};
-
-static const FFCodecDefault vulkan_encode_av1_defaults[] = {
-    { "b",              "0"   },
-    { "bf",             "2"   },
-    { "g",              "300" },
-    { "qmin",           "1"   },
-    { "qmax",           "255" },
-    { "refs",           "0"   },
-    { NULL },
-};
-
-static const AVClass vulkan_encode_av1_class = {
-    .class_name = "av1_vulkan",
-    .item_name  = av_default_item_name,
-    .option     = vulkan_encode_av1_options,
-    .version    = LIBAVUTIL_VERSION_INT,
-};
-
-const FFCodec ff_av1_vulkan_encoder = {
-    .p.name         = "av1_vulkan",
-    CODEC_LONG_NAME("AV1 (Vulkan)"),
-    .p.type         = AVMEDIA_TYPE_VIDEO,
-    .p.id           = AV_CODEC_ID_AV1,
-    .priv_data_size = sizeof(VulkanEncodeAV1Context),
-    .init           = &vulkan_encode_av1_init,
-    FF_CODEC_RECEIVE_PACKET_CB(&ff_vulkan_encode_receive_packet),
-    .close          = &vulkan_encode_av1_close,
-    .p.priv_class   = &vulkan_encode_av1_class,
-    .p.capabilities = AV_CODEC_CAP_DELAY |
-                      AV_CODEC_CAP_HARDWARE |
-                      AV_CODEC_CAP_DR1 |
-                      AV_CODEC_CAP_ENCODER_FLUSH |
-                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
-    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
-    .defaults       = vulkan_encode_av1_defaults,
-    CODEC_PIXFMTS(AV_PIX_FMT_VULKAN),
-    .hw_configs     = ff_vulkan_encode_hw_configs,
-    .p.wrapper_name = "vulkan",
-};
-- 
2.49.1


From 9711a91b3b9f7b3693a0faa62e22d98ba3d2a717 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:33:07 +0000
Subject: [PATCH 074/118] Changing vulkan file directory

---
 libavcodec/vulkan/vulkan_encode_av1.c | 1401 +++++++++++++++++++++++++
 1 file changed, 1401 insertions(+)
 create mode 100644 libavcodec/vulkan/vulkan_encode_av1.c

diff --git a/libavcodec/vulkan/vulkan_encode_av1.c b/libavcodec/vulkan/vulkan_encode_av1.c
new file mode 100644
index 0000000000..a2e4b575bb
--- /dev/null
+++ b/libavcodec/vulkan/vulkan_encode_av1.c
@@ -0,0 +1,1401 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/opt.h"
+#include "libavutil/mem.h"
+
+#include "libavcodec/cbs.h"
+#include "libavcodec/cbs_av1.h"
+#include "libavcodec/av1_levels.h"
+#include "libavutil/mastering_display_metadata.h"
+
+#include "libavcodec/codec_internal.h"
+#include "vulkan_encode.h"
+
+#include "libavutil/avassert.h"
+
+const FFVulkanEncodeDescriptor ff_vk_enc_av1_desc = {
+    .codec_id         = AV_CODEC_ID_AV1,
+    .encode_extension = FF_VK_EXT_VIDEO_ENCODE_AV1,
+    .encode_op        = VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR,
+    .ext_props = {
+        .extensionName = VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_EXTENSION_NAME,
+        .specVersion   = VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_SPEC_VERSION,
+    },
+};
+
+enum UnitElems {
+    UNIT_MASTERING_DISPLAY   = 1 << 0,
+    UNIT_CONTENT_LIGHT_LEVEL = 1 << 1,
+};
+
+typedef struct VulkanEncodeAV1Picture {
+    int slot;
+    int64_t last_idr_frame;
+
+    enum UnitElems units_needed;
+
+    StdVideoAV1TileInfo tile_info;
+    StdVideoAV1Quantization quantization;
+    StdVideoAV1Segmentation segmentation;
+    StdVideoAV1LoopFilter loop_filter;
+    StdVideoAV1CDEF cdef;
+    StdVideoAV1LoopRestoration loop_restoration;
+    StdVideoAV1GlobalMotion global_motion;
+
+    StdVideoEncodeAV1PictureInfo av1pic_info;
+    VkVideoEncodeAV1PictureInfoKHR vkav1pic_info;
+
+    StdVideoEncodeAV1ExtensionHeader ext_header;
+    StdVideoEncodeAV1ReferenceInfo av1dpb_info;
+    VkVideoEncodeAV1DpbSlotInfoKHR vkav1dpb_info;
+
+    VkVideoEncodeAV1RateControlInfoKHR vkrc_info;
+    VkVideoEncodeAV1RateControlLayerInfoKHR vkrc_layer_info;
+    VkVideoEncodeAV1GopRemainingFrameInfoKHR vkrc_remaining;
+} VulkanEncodeAV1Picture;
+
+typedef struct VulkanEncodeAV1Context {
+    FFVulkanEncodeContext common;
+
+    CodedBitstreamContext *cbs;
+    CodedBitstreamFragment current_access_unit;
+
+    enum UnitElems unit_elems;
+    AV1RawOBU seq_hdr_obu;
+    AV1RawOBU meta_cll_obu;
+    AV1RawOBU meta_mastering_obu;
+
+    VkVideoEncodeAV1ProfileInfoKHR profile;
+
+    VkVideoEncodeAV1CapabilitiesKHR caps;
+    VkVideoEncodeAV1QualityLevelPropertiesKHR quality_props;
+
+    uint64_t hrd_buffer_size;
+    uint64_t initial_buffer_fullness;
+
+    int uniform_tile;
+    int tile_cols;
+    int tile_rows;
+
+    int seq_tier;
+    int seq_level_idx;
+
+    int q_idx_idr;
+    int q_idx_p;
+    int q_idx_b;
+
+    uint8_t *padding_payload;
+} VulkanEncodeAV1Context;
+
+static int init_pic_rc(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
+                       VkVideoEncodeRateControlInfoKHR *rc_info,
+                       VkVideoEncodeRateControlLayerInfoKHR *rc_layer)
+{
+    VulkanEncodeAV1Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext  *ctx = &enc->common;
+    VulkanEncodeAV1Picture  *ap = pic->codec_priv;
+
+    /* This can be easy to calculate */
+    ap->vkrc_remaining = (VkVideoEncodeAV1GopRemainingFrameInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_GOP_REMAINING_FRAME_INFO_KHR,
+        .useGopRemainingFrames = 0,
+        .gopRemainingIntra = 0,
+        .gopRemainingPredictive = 0,
+        .gopRemainingBipredictive = 0,
+    };
+
+    ap->vkrc_info = (VkVideoEncodeAV1RateControlInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_RATE_CONTROL_INFO_KHR,
+        .flags = VK_VIDEO_ENCODE_AV1_RATE_CONTROL_REFERENCE_PATTERN_FLAT_BIT_KHR |
+                 VK_VIDEO_ENCODE_AV1_RATE_CONTROL_REGULAR_GOP_BIT_KHR,
+        .gopFrameCount = ctx->base.gop_size,
+        .keyFramePeriod = ctx->base.gop_size,
+        .consecutiveBipredictiveFrameCount = FFMAX(ctx->base.b_per_p - 1, 0),
+        .temporalLayerCount = 0,
+    };
+    rc_info->pNext = &ap->vkrc_info;
+
+    if (rc_info->rateControlMode > VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
+        rc_info->virtualBufferSizeInMs = (enc->hrd_buffer_size * 1000LL) / avctx->bit_rate;
+        rc_info->initialVirtualBufferSizeInMs = (enc->initial_buffer_fullness * 1000LL) / avctx->bit_rate;
+
+        ap->vkrc_layer_info = (VkVideoEncodeAV1RateControlLayerInfoKHR) {
+            .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_RATE_CONTROL_LAYER_INFO_KHR,
+
+            .useMinQIndex  = avctx->qmin > 0,
+            .minQIndex.intraQIndex = avctx->qmin > 0 ? avctx->qmin : 0,
+            .minQIndex.predictiveQIndex = avctx->qmin > 0 ? avctx->qmin : 0,
+            .minQIndex.bipredictiveQIndex = avctx->qmin > 0 ? avctx->qmin : 0,
+
+            .useMaxQIndex  = avctx->qmax > 0,
+            .maxQIndex.intraQIndex = avctx->qmax > 0 ? avctx->qmax : 0,
+            .maxQIndex.predictiveQIndex = avctx->qmax > 0 ? avctx->qmax : 0,
+            .maxQIndex.bipredictiveQIndex = avctx->qmax > 0 ? avctx->qmax : 0,
+
+            .useMaxFrameSize = 0,
+        };
+        rc_layer->pNext = &ap->vkrc_layer_info;
+        ap->vkrc_info.temporalLayerCount = 1;
+    }
+
+    return 0;
+}
+
+static void set_name_slot(int slot, int *slot_indices, uint32_t allowed_idx, int group)
+{
+    int from = group ? AV1_REF_FRAME_GOLDEN : 0;
+    int to = group ? AV1_REFS_PER_FRAME : AV1_REF_FRAME_GOLDEN;
+
+    for (int i = from; i < to; i++) {
+        if ((slot_indices[i] == -1) && (allowed_idx & (1 << i))) {
+            slot_indices[i] = slot;
+            return;
+        }
+    }
+
+    av_assert0(0);
+}
+
+
+static int init_pic_params(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
+                           VkVideoEncodeInfoKHR *encode_info)
+{
+    VulkanEncodeAV1Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext *ctx = &enc->common;
+    FFHWBaseEncodeContext *base_ctx = &ctx->base;
+
+    VulkanEncodeAV1Picture *ap = pic->codec_priv;
+    FFHWBaseEncodePicture *ref;
+    VulkanEncodeAV1Picture *ap_ref;
+    VkVideoReferenceSlotInfoKHR *ref_slot;
+
+    uint32_t ref_name_mask = 0x0;
+    int name_slots[STD_VIDEO_AV1_REFS_PER_FRAME];
+
+    StdVideoAV1Segmentation *segmentation = &ap->segmentation;
+    StdVideoAV1LoopFilter  *loop_filter = &ap->loop_filter;
+    StdVideoAV1Quantization *quantization = &ap->quantization;
+    StdVideoAV1CDEF *cdef = &ap->cdef;
+    StdVideoAV1LoopRestoration *loop_restoration = &ap->loop_restoration;
+    StdVideoAV1GlobalMotion *global_motion = &ap->global_motion;
+    StdVideoAV1TileInfo *tile_info = &ap->tile_info;
+    static const int8_t default_loop_filter_ref_deltas[STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME] =
+        { 1, 0, 0, 0, -1, 0, -1, -1 };
+
+    VkVideoEncodeAV1PredictionModeKHR pred_mode;
+    VkVideoEncodeAV1RateControlGroupKHR rc_group;
+    int lr_unit_shift = 0;
+    int lr_uv_shift = 0;
+
+    ap->ext_header = (StdVideoEncodeAV1ExtensionHeader) {
+        .temporal_id = 0,
+        .spatial_id = 0,
+    };
+
+    *tile_info = (StdVideoAV1TileInfo) {
+        .flags = (StdVideoAV1TileInfoFlags) {
+            .uniform_tile_spacing_flag = enc->uniform_tile,
+        },
+        .TileCols = enc->tile_cols,
+        .TileRows = enc->tile_rows,
+        .context_update_tile_id = 0,
+        .tile_size_bytes_minus_1 = 0,
+    };
+
+    for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++) {
+        global_motion->GmType[i] = 0;
+        for (int j = 0; j < STD_VIDEO_AV1_GLOBAL_MOTION_PARAMS; j++) {
+            global_motion->gm_params[i][j] = 0;
+        }
+    }
+
+    for (int i = 0; i < STD_VIDEO_AV1_REFS_PER_FRAME; i++)
+        name_slots[i] = -1;
+
+    *loop_restoration = (StdVideoAV1LoopRestoration) {
+        .FrameRestorationType[0] = STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_NONE,
+        .FrameRestorationType[1] = STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_NONE,
+        .FrameRestorationType[2] = STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_NONE,
+        .LoopRestorationSize[0] = 1 + lr_unit_shift,
+        .LoopRestorationSize[1] = 1 + lr_unit_shift - lr_uv_shift,
+        .LoopRestorationSize[2] = 1 + lr_unit_shift - lr_uv_shift,
+    };
+
+    *cdef = (StdVideoAV1CDEF) {
+        .cdef_damping_minus_3 = 0,
+        .cdef_bits = 0,
+    };
+
+    for (int i = 0; i < STD_VIDEO_AV1_MAX_SEGMENTS; i++) {
+        segmentation->FeatureEnabled[i] = 0x0;
+        for (int j = 0; j < STD_VIDEO_AV1_SEG_LVL_MAX; j++) {
+            segmentation->FeatureEnabled[i] |= 0x0;
+            segmentation->FeatureData[i][j] = 0;
+        }
+    }
+
+    *loop_filter = (StdVideoAV1LoopFilter) {
+        .flags = (StdVideoAV1LoopFilterFlags) {
+            .loop_filter_delta_enabled = 0,
+            .loop_filter_delta_update = 0,
+        },
+        .loop_filter_level = { 0 },
+        .loop_filter_sharpness = 0,
+        .update_ref_delta = 0,
+        .loop_filter_ref_deltas = { 0 },
+        .update_mode_delta = 0,
+        .loop_filter_mode_deltas = { 0 },
+    };
+    loop_filter->update_mode_delta = 1;
+    memcpy(loop_filter->loop_filter_ref_deltas, default_loop_filter_ref_deltas,
+           STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME * sizeof(int8_t));
+
+    *quantization = (StdVideoAV1Quantization) {
+        .flags = (StdVideoAV1QuantizationFlags) {
+            .using_qmatrix = 0,
+            .diff_uv_delta = 0,
+            /* Reserved */
+        },
+        .base_q_idx = 0, /* Set later */
+        .DeltaQYDc = 0,
+        .DeltaQUDc = 0,
+        .DeltaQUAc = 0,
+        .DeltaQVDc = 0,
+        .DeltaQVAc = 0,
+        .qm_y = 0,
+        .qm_u = 0,
+        .qm_v = 0,
+    };
+
+    ref_slot = (VkVideoReferenceSlotInfoKHR *)encode_info->pSetupReferenceSlot;
+    ap->av1pic_info = (StdVideoEncodeAV1PictureInfo) {
+        .flags = (StdVideoEncodeAV1PictureInfoFlags) {
+            .error_resilient_mode = (pic->type == FF_HW_PICTURE_TYPE_I ||
+                                     pic->type == FF_HW_PICTURE_TYPE_IDR) &&
+                                    (pic->display_order <= pic->encode_order),
+            .disable_cdf_update = 0,
+            .use_superres = 0,
+            .render_and_frame_size_different = 0,
+            .allow_screen_content_tools = 0,
+            .is_filter_switchable = 0,
+            .force_integer_mv = 0,
+            .frame_size_override_flag = 0,
+            .buffer_removal_time_present_flag = 0,
+            .allow_intrabc = 0,
+            .frame_refs_short_signaling = 0,
+            .allow_high_precision_mv = 0,
+            .is_motion_mode_switchable = 0,
+            .use_ref_frame_mvs = 0,
+            .disable_frame_end_update_cdf = 0,
+            .allow_warped_motion = 0,
+            .reduced_tx_set = 0,
+            .skip_mode_present = 0,
+            .delta_q_present = 0,
+            .delta_lf_present = 0,
+            .delta_lf_multi = 0,
+            .segmentation_enabled = 0,
+            .segmentation_update_map = 0,
+            .segmentation_temporal_update = 0,
+            .segmentation_update_data = 0,
+            .UsesLr = 0,
+            .usesChromaLr = 0,
+            .show_frame = pic->display_order <= pic->encode_order,
+            .showable_frame = 0,
+            /* Reserved */
+        },
+        .frame_type = 0, // set later
+        .frame_presentation_time = 0,
+        .current_frame_id = ref_slot->slotIndex,
+        .order_hint = 0, // set later
+        .primary_ref_frame = 0, // set later
+        .refresh_frame_flags = 0x0, // set later
+        .coded_denom = 0,
+        .render_width_minus_1 = base_ctx->surface_width - 1,
+        .render_height_minus_1 = base_ctx->surface_height - 1,
+        .interpolation_filter = 0,
+        .TxMode = STD_VIDEO_AV1_TX_MODE_SELECT,
+        .delta_q_res = 0,
+        .delta_lf_res = 0,
+        .ref_order_hint = { 0 }, // set later
+        .ref_frame_idx = { 0 }, // set later
+        /* Reserved */
+        .delta_frame_id_minus_1 = { 0 },
+
+//        .pTileInfo = tile_info, TODO FIX
+        .pQuantization = quantization,
+        .pSegmentation = segmentation,
+        .pLoopFilter = loop_filter,
+        .pCDEF = cdef,
+        .pLoopRestoration = loop_restoration,
+        .pGlobalMotion = global_motion,
+        .pExtensionHeader = &ap->ext_header,
+        .pBufferRemovalTimes = NULL,
+    };
+
+    switch (pic->type) {
+    case FF_HW_PICTURE_TYPE_I:
+    case FF_HW_PICTURE_TYPE_IDR:
+        av_assert0(pic->nb_refs[0] == 0 || pic->nb_refs[1]);
+        ap->av1pic_info.frame_type = STD_VIDEO_AV1_FRAME_TYPE_KEY;
+        ap->av1pic_info.refresh_frame_flags = 0xFF;
+        quantization->base_q_idx = enc->q_idx_idr;
+        ap->slot = 0;
+        ap->last_idr_frame = pic->display_order;
+        pred_mode = VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_INTRA_ONLY_KHR;
+        rc_group = VK_VIDEO_ENCODE_AV1_RATE_CONTROL_GROUP_INTRA_KHR;
+        break;
+    case FF_HW_PICTURE_TYPE_P:
+        ref = pic->refs[0][pic->nb_refs[0] - 1];
+        ap_ref = ref->codec_priv;
+
+        ap->av1pic_info.frame_type = STD_VIDEO_AV1_FRAME_TYPE_INTER;
+        quantization->base_q_idx = enc->q_idx_p;
+
+        ap->last_idr_frame = ap_ref->last_idr_frame;
+        ap->slot = !ap_ref->slot;
+
+        ap->av1pic_info.refresh_frame_flags = 1 << ap->slot;
+
+        /** set the nearest frame in L0 as all reference frame. */
+        for (int i = 0; i < AV1_REFS_PER_FRAME; i++)
+            ap->av1pic_info.ref_frame_idx[i] = ap_ref->slot;
+
+        ap->av1pic_info.primary_ref_frame = ap_ref->slot;
+        ap->av1pic_info.ref_order_hint[ap_ref->slot] = ref->display_order - ap_ref->last_idr_frame;
+        rc_group = VK_VIDEO_ENCODE_AV1_RATE_CONTROL_GROUP_PREDICTIVE_KHR;
+        pred_mode = VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_SINGLE_REFERENCE_KHR;
+        ref_name_mask = enc->caps.singleReferenceNameMask;
+        set_name_slot(ap_ref->av1pic_info.current_frame_id, name_slots, ref_name_mask, 0);
+
+//        vpic->ref_frame_ctrl_l0.fields.search_idx0 = AV1_REF_FRAME_LAST;
+
+        /** set the 2nd nearest frame in L0 as Golden frame. */
+        if ((pic->nb_refs[0] > 1) &&
+            ((enc->caps.maxSingleReferenceCount > 1) ||
+             (enc->caps.maxUnidirectionalCompoundReferenceCount > 0))) {
+            if (enc->caps.maxUnidirectionalCompoundReferenceCount) {
+                pred_mode = VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_UNIDIRECTIONAL_COMPOUND_KHR;
+                ref_name_mask = enc->caps.unidirectionalCompoundReferenceNameMask;
+            }
+            ref = pic->refs[0][pic->nb_refs[0] - 2];
+            ap_ref = ref->codec_priv;
+            ap->av1pic_info.ref_frame_idx[3] = ap_ref->slot;
+            ap->av1pic_info.ref_order_hint[ap_ref->slot] = ref->display_order - ap_ref->last_idr_frame;
+//            vpic->ref_frame_ctrl_l0.fields.search_idx1 = AV1_REF_FRAME_GOLDEN;
+            set_name_slot(ap_ref->av1pic_info.current_frame_id, name_slots, ref_name_mask, 0);
+        }
+        break;
+    case FF_HW_PICTURE_TYPE_B:
+        ap->av1pic_info.frame_type = STD_VIDEO_AV1_FRAME_TYPE_INTER;
+        quantization->base_q_idx = enc->q_idx_b;
+        ap->av1pic_info.refresh_frame_flags = 0x0;
+
+        rc_group = VK_VIDEO_ENCODE_AV1_RATE_CONTROL_GROUP_BIPREDICTIVE_KHR;
+        pred_mode = VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_BIDIRECTIONAL_COMPOUND_KHR;
+        ref_name_mask = enc->caps.bidirectionalCompoundReferenceNameMask;
+
+//        fh->reference_select = 1;
+        /** B frame will not be referenced, disable its recon frame. */
+//        vpic->picture_flags.bits.disable_frame_recon = 1;
+
+        /** Use LAST_FRAME and BWDREF_FRAME for reference. */
+//        vpic->ref_frame_ctrl_l0.fields.search_idx0 = AV1_REF_FRAME_LAST;
+//        vpic->ref_frame_ctrl_l1.fields.search_idx0 = AV1_REF_FRAME_BWDREF;
+
+        ref = pic->refs[0][pic->nb_refs[0] - 1];
+        ap_ref = ref->codec_priv;
+        ap->last_idr_frame = ap_ref->last_idr_frame;
+        ap->av1pic_info.primary_ref_frame = ap_ref->slot;
+        ap->av1pic_info.ref_order_hint[ap_ref->slot] = ref->display_order - ap_ref->last_idr_frame;
+        for (int i = 0; i < AV1_REF_FRAME_GOLDEN; i++)
+            ap->av1pic_info.ref_frame_idx[i] = ap_ref->slot;
+        set_name_slot(ap_ref->av1pic_info.current_frame_id, name_slots, ref_name_mask, 0);
+
+        ref = pic->refs[1][pic->nb_refs[1] - 1];
+        ap_ref = ref->codec_priv;
+        ap->av1pic_info.ref_order_hint[ap_ref->slot] = ref->display_order - ap_ref->last_idr_frame;
+        for (int i = AV1_REF_FRAME_GOLDEN; i < AV1_REFS_PER_FRAME; i++)
+            ap->av1pic_info.ref_frame_idx[i] = ap_ref->slot;
+        set_name_slot(ap_ref->av1pic_info.current_frame_id, name_slots, ref_name_mask, 1);
+        break;
+    }
+
+    ap->av1pic_info.flags.showable_frame = ap->av1pic_info.frame_type != STD_VIDEO_AV1_FRAME_TYPE_KEY;
+    ap->av1pic_info.order_hint = pic->display_order - ap->last_idr_frame;
+
+    ap->vkav1pic_info = (VkVideoEncodeAV1PictureInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_PICTURE_INFO_KHR,
+        .pNext = NULL,
+        .predictionMode = pred_mode,
+        .rateControlGroup = rc_group,
+        .constantQIndex = quantization->base_q_idx,
+        .pStdPictureInfo = &ap->av1pic_info,
+        // .referenceNameSlotIndices is set below
+        .primaryReferenceCdfOnly = 0,
+        .generateObuExtensionHeader = 0,
+    };
+    encode_info->pNext = &ap->vkav1pic_info;
+
+    for (int i = 0; i < FF_ARRAY_ELEMS(ap->vkav1pic_info.referenceNameSlotIndices); i++)
+        ap->vkav1pic_info.referenceNameSlotIndices[i] = name_slots[i];
+
+    ref_slot = (VkVideoReferenceSlotInfoKHR *)encode_info->pSetupReferenceSlot;
+    ref_slot->pNext = &ap->vkav1dpb_info;
+
+    ap->av1dpb_info = (StdVideoEncodeAV1ReferenceInfo) {
+        .flags = (StdVideoEncodeAV1ReferenceInfoFlags) {
+            .disable_frame_end_update_cdf = 0,
+            .segmentation_enabled = 0,
+            /* Reserved */
+        },
+        .RefFrameId = ref_slot->slotIndex,
+        .frame_type = ap->av1pic_info.frame_type,
+        .OrderHint = pic->display_order - ap->last_idr_frame,
+        /* Reserved */
+        .pExtensionHeader = &ap->ext_header,
+    };
+
+    ap->vkav1dpb_info = (VkVideoEncodeAV1DpbSlotInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_DPB_SLOT_INFO_KHR,
+        .pStdReferenceInfo = &ap->av1dpb_info,
+    };
+
+    ap->units_needed = 0;
+    if (pic->type == FF_HW_PICTURE_TYPE_IDR) {
+        AVFrameSideData *sd = NULL;
+        if (enc->unit_elems & UNIT_MASTERING_DISPLAY)
+            sd = av_frame_get_side_data(pic->input_image,
+                                        AV_FRAME_DATA_MASTERING_DISPLAY_METADATA);
+        if (sd) {
+            AVMasteringDisplayMetadata *mdm =
+                (AVMasteringDisplayMetadata *)sd->data;
+            if (mdm->has_primaries && mdm->has_luminance) {
+                AV1RawOBU              *obu = &enc->meta_mastering_obu;
+                AV1RawMetadata          *md = &obu->obu.metadata;
+                AV1RawMetadataHDRMDCV *mdcv = &md->metadata.hdr_mdcv;
+                const int        chroma_den = 1 << 16;
+                const int      max_luma_den = 1 << 8;
+                const int      min_luma_den = 1 << 14;
+
+                memset(obu, 0, sizeof(*obu));
+                obu->header.obu_type = AV1_OBU_METADATA;
+                md->metadata_type = AV1_METADATA_TYPE_HDR_MDCV;
+
+                for (int i = 0; i < 3; i++) {
+                    mdcv->primary_chromaticity_x[i] =
+                        av_rescale(mdm->display_primaries[i][0].num, chroma_den,
+                                   mdm->display_primaries[i][0].den);
+                    mdcv->primary_chromaticity_y[i] =
+                        av_rescale(mdm->display_primaries[i][1].num, chroma_den,
+                                   mdm->display_primaries[i][1].den);
+                }
+
+                mdcv->white_point_chromaticity_x =
+                    av_rescale(mdm->white_point[0].num, chroma_den,
+                               mdm->white_point[0].den);
+                mdcv->white_point_chromaticity_y =
+                    av_rescale(mdm->white_point[1].num, chroma_den,
+                               mdm->white_point[1].den);
+
+                mdcv->luminance_max =
+                    av_rescale(mdm->max_luminance.num, max_luma_den,
+                               mdm->max_luminance.den);
+                mdcv->luminance_min =
+                    av_rescale(mdm->min_luminance.num, min_luma_den,
+                               mdm->min_luminance.den);
+                ap->units_needed |= UNIT_MASTERING_DISPLAY;
+            }
+        }
+
+        if (enc->unit_elems & UNIT_CONTENT_LIGHT_LEVEL)
+            sd = av_frame_get_side_data(pic->input_image,
+                                        AV_FRAME_DATA_CONTENT_LIGHT_LEVEL);
+        if (sd) {
+            AVContentLightMetadata *cllm = (AVContentLightMetadata *)sd->data;
+            AV1RawOBU               *obu = &enc->meta_cll_obu;
+            AV1RawMetadata           *md = &obu->obu.metadata;
+            AV1RawMetadataHDRCLL    *cll = &md->metadata.hdr_cll;
+
+            memset(obu, 0, sizeof(*obu));
+            obu->header.obu_type = AV1_OBU_METADATA;
+            md->metadata_type    = AV1_METADATA_TYPE_HDR_CLL;
+            cll->max_cll         = cllm->MaxCLL;
+            cll->max_fall        = cllm->MaxFALL;
+
+            ap->units_needed |= UNIT_CONTENT_LIGHT_LEVEL;
+        }
+    }
+
+    return 0;
+}
+
+static int init_profile(AVCodecContext *avctx,
+                        VkVideoProfileInfoKHR *profile, void *pnext)
+{
+    VkResult ret;
+    VulkanEncodeAV1Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext *ctx = &enc->common;
+    FFVulkanContext *s = &ctx->s;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+    FFHWBaseEncodeContext *base_ctx = &ctx->base;
+
+    VkVideoEncodeAV1CapabilitiesKHR av1_caps = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_CAPABILITIES_KHR,
+    };
+    VkVideoEncodeCapabilitiesKHR enc_caps = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR,
+        .pNext = &av1_caps,
+    };
+    VkVideoCapabilitiesKHR caps = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR,
+        .pNext = &enc_caps,
+    };
+
+    /* In order of preference */
+    int last_supported = AV_PROFILE_UNKNOWN;
+    static const int known_profiles[] = {
+        AV_PROFILE_AV1_MAIN,
+        AV_PROFILE_AV1_HIGH,
+        AV_PROFILE_AV1_PROFESSIONAL,
+    };
+    int nb_profiles = FF_ARRAY_ELEMS(known_profiles);
+
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->frames->sw_format);
+    if (!desc)
+        return AVERROR(EINVAL);
+
+    if (s->frames->sw_format == AV_PIX_FMT_NV12 ||
+        s->frames->sw_format == AV_PIX_FMT_P010)
+        nb_profiles = 1;
+
+    enc->profile = (VkVideoEncodeAV1ProfileInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_PROFILE_INFO_KHR,
+        .pNext = pnext,
+        .stdProfile = ff_vk_av1_profile_to_vk(avctx->profile),
+    };
+    profile->pNext = &enc->profile;
+
+    /* Set level */
+    if (avctx->level == AV_LEVEL_UNKNOWN) {
+        const AV1LevelDescriptor *level;
+        float framerate = 0.0;
+
+        if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
+            framerate = av_q2d(avctx->framerate);
+
+        level = ff_av1_guess_level(avctx->bit_rate, enc->seq_tier,
+                                   base_ctx->surface_width, base_ctx->surface_height,
+                                   enc->tile_rows * enc->tile_cols,
+                                   enc->tile_cols, framerate);
+        if (level) {
+            av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name);
+            enc->seq_level_idx = ff_vk_av1_level_to_vk(level->level_idx);
+        } else {
+            av_log(avctx, AV_LOG_VERBOSE, "Stream will not conform to "
+                   "any normal level, using level 7.3 by default.\n");
+            enc->seq_level_idx = STD_VIDEO_AV1_LEVEL_7_3;
+            enc->seq_tier = 1;
+        }
+    } else {
+        enc->seq_level_idx = ff_vk_av1_level_to_vk(avctx->level);
+    }
+
+    /* User has explicitly specified a profile. */
+    if (avctx->profile != AV_PROFILE_UNKNOWN)
+        return 0;
+
+    av_log(avctx, AV_LOG_DEBUG, "Supported profiles:\n");
+    for (int i = 0; i < nb_profiles; i++) {
+        enc->profile.stdProfile = ff_vk_av1_profile_to_vk(known_profiles[i]);
+        ret = vk->GetPhysicalDeviceVideoCapabilitiesKHR(s->hwctx->phys_dev,
+                                                        profile,
+                                                        &caps);
+        if (ret == VK_SUCCESS) {
+            av_log(avctx, AV_LOG_DEBUG, "    %s\n",
+                   avcodec_profile_name(avctx->codec_id, known_profiles[i]));
+            last_supported = known_profiles[i];
+        }
+    }
+
+    if (last_supported == AV_PROFILE_UNKNOWN) {
+        av_log(avctx, AV_LOG_ERROR, "No supported profiles for given format\n");
+        return AVERROR(ENOTSUP);
+    }
+
+    enc->profile.stdProfile = ff_vk_av1_profile_to_vk(last_supported);
+    av_log(avctx, AV_LOG_VERBOSE, "Using profile %s\n",
+           avcodec_profile_name(avctx->codec_id, last_supported));
+    avctx->profile = last_supported;
+
+    return 0;
+}
+
+static int init_enc_options(AVCodecContext *avctx)
+{
+    VulkanEncodeAV1Context *enc = avctx->priv_data;
+
+    if (avctx->rc_buffer_size)
+        enc->hrd_buffer_size = avctx->rc_buffer_size;
+    else if (avctx->rc_max_rate > 0)
+        enc->hrd_buffer_size = avctx->rc_max_rate;
+    else
+        enc->hrd_buffer_size = avctx->bit_rate;
+
+    if (avctx->rc_initial_buffer_occupancy) {
+        if (avctx->rc_initial_buffer_occupancy > enc->hrd_buffer_size) {
+            av_log(avctx, AV_LOG_ERROR, "Invalid RC buffer settings: "
+                                        "must have initial buffer size (%d) <= "
+                                        "buffer size (%"PRId64").\n",
+                   avctx->rc_initial_buffer_occupancy, enc->hrd_buffer_size);
+            return AVERROR(EINVAL);
+        }
+        enc->initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
+    } else {
+        enc->initial_buffer_fullness = enc->hrd_buffer_size * 3 / 4;
+    }
+
+    if (enc->common.opts.rc_mode == VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
+        enc->q_idx_p = av_clip(enc->common.opts.qp,
+                               enc->caps.minQIndex, enc->caps.maxQIndex);
+        if (fabs(avctx->i_quant_factor) > 0.0)
+            enc->q_idx_idr =
+                av_clip((fabs(avctx->i_quant_factor) * enc->q_idx_p  +
+                         avctx->i_quant_offset) + 0.5,
+                        0, 255);
+        else
+            enc->q_idx_idr = enc->q_idx_p;
+
+        if (fabs(avctx->b_quant_factor) > 0.0)
+            enc->q_idx_b =
+                av_clip((fabs(avctx->b_quant_factor) * enc->q_idx_p  +
+                         avctx->b_quant_offset) + 0.5,
+                        0, 255);
+        else
+            enc->q_idx_b = enc->q_idx_p;
+    } else {
+        /** Arbitrary value */
+        enc->q_idx_idr = enc->q_idx_p = enc->q_idx_b = 128;
+    }
+
+    return 0;
+}
+
+static av_cold int init_sequence_headers(AVCodecContext *avctx)
+{
+    VulkanEncodeAV1Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext *ctx = &enc->common;
+    FFVulkanContext *s = &ctx->s;
+    FFHWBaseEncodeContext *base_ctx = &ctx->base;
+
+    AV1RawOBU *seq_obu = &enc->seq_hdr_obu;
+    AV1RawSequenceHeader *seq = &seq_obu->obu.sequence_header;
+
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->frames->sw_format);
+    if (!desc)
+        return AVERROR(EINVAL);
+
+    seq_obu->header.obu_type = AV1_OBU_SEQUENCE_HEADER;
+    *seq = (AV1RawSequenceHeader) {
+        .seq_profile = avctx->profile,
+        .seq_force_integer_mv = seq->seq_force_screen_content_tools ?
+                                AV1_SELECT_SCREEN_CONTENT_TOOLS :
+                                AV1_SELECT_INTEGER_MV,
+        .frame_width_bits_minus_1 = av_log2(base_ctx->surface_width),
+        .frame_height_bits_minus_1 = av_log2(base_ctx->surface_height),
+        .max_frame_width_minus_1 = base_ctx->surface_width - 1,
+        .max_frame_height_minus_1 = base_ctx->surface_height - 1,
+        .enable_order_hint = 1,
+        .order_hint_bits_minus_1 = av_clip_intp2(av_log2(ctx->base.gop_size), 3),
+        .use_128x128_superblock = !!(enc->caps.superblockSizes & VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_128_BIT_KHR),
+        .color_config = (AV1RawColorConfig) {
+            .high_bitdepth = desc->comp[0].depth > 8,
+            .color_primaries                = avctx->color_primaries,
+            .transfer_characteristics       = avctx->color_trc,
+            .matrix_coefficients            = avctx->colorspace,
+            .color_description_present_flag = (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED ||
+                                               avctx->color_trc       != AVCOL_TRC_UNSPECIFIED ||
+                                               avctx->colorspace      != AVCOL_SPC_UNSPECIFIED),
+            .subsampling_x                  = desc->log2_chroma_w,
+            .subsampling_y                  = desc->log2_chroma_h,
+            .chroma_sample_position         = avctx->chroma_sample_location == AVCHROMA_LOC_LEFT ?
+                                              AV1_CSP_VERTICAL :
+                                              avctx->chroma_sample_location == AVCHROMA_LOC_TOPLEFT ?
+                                              AV1_CSP_COLOCATED :
+                                              AV1_CSP_UNKNOWN,
+        },
+
+        /* Operating point */
+        .seq_tier = { enc->seq_tier },
+        .seq_level_idx = { enc->seq_level_idx },
+        .decoder_buffer_delay = { base_ctx->decode_delay },
+        .encoder_buffer_delay = { base_ctx->output_delay },
+        .operating_points_cnt_minus_1 = 1 - 1,
+    };
+
+    return 0;
+}
+
+typedef struct VulkanAV1Units {
+    StdVideoAV1SequenceHeader seq_hdr;
+    StdVideoAV1TimingInfo timing_info;
+    StdVideoAV1ColorConfig color_config;
+
+    StdVideoEncodeAV1DecoderModelInfo decoder_model;
+    StdVideoEncodeAV1OperatingPointInfo operating_points[AV1_MAX_OPERATING_POINTS];
+    int nb_operating_points;
+} VulkanAV1Units;
+
+static av_cold int base_unit_to_vk(AVCodecContext *avctx, VulkanAV1Units *vk_units)
+{
+    VulkanEncodeAV1Context *enc = avctx->priv_data;
+
+    AV1RawOBU *seq_obu = &enc->seq_hdr_obu;
+    AV1RawSequenceHeader *seq = &seq_obu->obu.sequence_header;
+
+    StdVideoAV1SequenceHeader *seq_hdr = &vk_units->seq_hdr;
+    StdVideoAV1TimingInfo *timing_info = &vk_units->timing_info;
+    StdVideoAV1ColorConfig *color_config = &vk_units->color_config;
+
+    StdVideoEncodeAV1OperatingPointInfo *operating_points = vk_units->operating_points;
+
+    *timing_info = (StdVideoAV1TimingInfo) {
+        .flags = (StdVideoAV1TimingInfoFlags) {
+            .equal_picture_interval = seq->timing_info.equal_picture_interval,
+        },
+        .num_units_in_display_tick = seq->timing_info.num_units_in_display_tick,
+        .time_scale = seq->timing_info.time_scale,
+        .num_ticks_per_picture_minus_1 = seq->timing_info.num_ticks_per_picture_minus_1,
+    };
+
+    *color_config = (StdVideoAV1ColorConfig) {
+        .flags = (StdVideoAV1ColorConfigFlags) {
+            .mono_chrome = seq->color_config.mono_chrome,
+            .color_range = seq->color_config.color_range,
+            .separate_uv_delta_q = seq->color_config.separate_uv_delta_q,
+        },
+        .BitDepth = seq->color_config.twelve_bit    ? 12 :
+                    seq->color_config.high_bitdepth ? 10 : 8,
+        .subsampling_x = seq->color_config.subsampling_x,
+        .subsampling_y = seq->color_config.subsampling_y,
+        .color_primaries = seq->color_config.color_primaries,
+        .transfer_characteristics = seq->color_config.transfer_characteristics,
+        .matrix_coefficients = seq->color_config.matrix_coefficients,
+    };
+
+    *seq_hdr = (StdVideoAV1SequenceHeader) {
+        .flags = (StdVideoAV1SequenceHeaderFlags) {
+            .still_picture = seq->still_picture,
+            .reduced_still_picture_header = seq->reduced_still_picture_header,
+            .use_128x128_superblock = seq->use_128x128_superblock,
+            .enable_filter_intra = seq->enable_filter_intra,
+            .enable_intra_edge_filter = seq->enable_intra_edge_filter,
+            .enable_interintra_compound = seq->enable_interintra_compound,
+            .enable_masked_compound = seq->enable_masked_compound,
+            .enable_warped_motion = seq->enable_warped_motion,
+            .enable_dual_filter = seq->enable_dual_filter,
+            .enable_order_hint = seq->enable_order_hint,
+            .enable_jnt_comp = seq->enable_jnt_comp,
+            .enable_ref_frame_mvs = seq->enable_ref_frame_mvs,
+            .frame_id_numbers_present_flag = seq->frame_id_numbers_present_flag,
+            .enable_superres = seq->enable_superres,
+            .enable_cdef = seq->enable_cdef,
+            .enable_restoration = seq->enable_restoration,
+            .film_grain_params_present = seq->film_grain_params_present,
+            .timing_info_present_flag = seq->timing_info_present_flag,
+            .initial_display_delay_present_flag = seq->initial_display_delay_present_flag,
+        },
+        .seq_profile = seq->seq_profile,
+        .frame_width_bits_minus_1 = seq->frame_width_bits_minus_1,
+        .frame_height_bits_minus_1 = seq->frame_height_bits_minus_1,
+        .max_frame_width_minus_1 = seq->max_frame_width_minus_1,
+        .max_frame_height_minus_1 = seq->max_frame_height_minus_1,
+        .delta_frame_id_length_minus_2 = seq->delta_frame_id_length_minus_2,
+        .additional_frame_id_length_minus_1 = seq->additional_frame_id_length_minus_1,
+        .order_hint_bits_minus_1 = seq->order_hint_bits_minus_1,
+        .seq_force_integer_mv = seq->seq_force_integer_mv,
+        .seq_force_screen_content_tools = seq->seq_force_screen_content_tools,
+        .pTimingInfo = timing_info,
+        .pColorConfig = color_config,
+    };
+
+    for (int i = 0; i <= seq->operating_points_cnt_minus_1; i++) {
+        operating_points[i] = (StdVideoEncodeAV1OperatingPointInfo) {
+            .flags = (StdVideoEncodeAV1OperatingPointInfoFlags) {
+                .decoder_model_present_for_this_op = seq->decoder_model_present_for_this_op[i],
+                .low_delay_mode_flag = seq->low_delay_mode_flag[i],
+                .initial_display_delay_present_for_this_op = seq->initial_display_delay_present_for_this_op[i],
+                /* Reserved */
+            },
+            .operating_point_idc = seq->operating_point_idc[i],
+            .seq_level_idx = seq->seq_level_idx[i],
+            .seq_tier = seq->seq_tier[i],
+            .decoder_buffer_delay = seq->decoder_buffer_delay[i],
+            .encoder_buffer_delay = seq->encoder_buffer_delay[i],
+            .initial_display_delay_minus_1 = seq->initial_display_delay_minus_1[i],
+        };
+    }
+    vk_units->nb_operating_points = seq->operating_points_cnt_minus_1 + 1;
+
+    return 0;
+}
+
+static int create_session_params(AVCodecContext *avctx)
+{
+    int err;
+    VulkanEncodeAV1Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext *ctx = &enc->common;
+    FFVulkanContext *s = &ctx->s;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+
+    VulkanAV1Units vk_units = { 0 };
+
+    VkVideoEncodeAV1SessionParametersCreateInfoKHR av1_params;
+
+    /* Convert it to Vulkan */
+    err = base_unit_to_vk(avctx, &vk_units);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to convert sequence header to Vulkan: %s\n",
+               av_err2str(err));
+        return err;
+    }
+
+    /* Destroy the session params */
+    if (ctx->session_params)
+        vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
+                                             ctx->session_params,
+                                             s->hwctx->alloc);
+
+    av1_params = (VkVideoEncodeAV1SessionParametersCreateInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR,
+        .pStdSequenceHeader = &vk_units.seq_hdr,
+        .pStdDecoderModelInfo = &vk_units.decoder_model,
+        .pStdOperatingPoints = vk_units.operating_points,
+        .stdOperatingPointCount = vk_units.nb_operating_points,
+    };
+
+    return ff_vulkan_encode_create_session_params(avctx, ctx, &av1_params);
+}
+
+static int parse_feedback_units(AVCodecContext *avctx,
+                                const uint8_t *data, size_t size)
+{
+    int err;
+    VulkanEncodeAV1Context *enc = avctx->priv_data;
+    AV1RawOBU *seq_obu = &enc->seq_hdr_obu;
+    AV1RawSequenceHeader *seq = &seq_obu->obu.sequence_header;
+
+    CodedBitstreamContext *cbs;
+    CodedBitstreamFragment obu = { 0 };
+
+    err = ff_cbs_init(&cbs, AV_CODEC_ID_AV1, avctx);
+    if (err < 0)
+        return err;
+
+    err = ff_cbs_read(cbs, &obu, NULL, data, size);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to parse feedback units, bad drivers: %s\n",
+               av_err2str(err));
+        return err;
+    }
+
+    /* If PPS has an override, just copy it entirely. */
+    for (int i = 0; i < obu.nb_units; i++) {
+        if (obu.units[i].type == AV1_OBU_SEQUENCE_HEADER) {
+            AV1RawOBU *f_seq_obu = obu.units[i].content;
+            AV1RawSequenceHeader *f_seq = &f_seq_obu->obu.sequence_header;
+            seq->frame_width_bits_minus_1 = f_seq->frame_width_bits_minus_1;
+            seq->frame_height_bits_minus_1 = f_seq->frame_height_bits_minus_1;
+            seq->max_frame_width_minus_1 = f_seq->max_frame_width_minus_1;
+            seq->max_frame_height_minus_1 = f_seq->max_frame_height_minus_1;
+            seq->seq_choose_screen_content_tools = f_seq->seq_choose_screen_content_tools;
+            seq->seq_force_screen_content_tools = f_seq->seq_force_screen_content_tools;
+            seq->seq_choose_integer_mv = f_seq->seq_choose_integer_mv;
+            seq->seq_force_integer_mv = f_seq->seq_force_integer_mv;
+        }
+    }
+
+    ff_cbs_fragment_free(&obu);
+    ff_cbs_close(&cbs);
+
+    return 0;
+}
+
+static int init_base_units(AVCodecContext *avctx)
+{
+    int err;
+    VkResult ret;
+    VulkanEncodeAV1Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext *ctx = &enc->common;
+    FFVulkanContext *s = &ctx->s;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+
+    VkVideoEncodeSessionParametersGetInfoKHR params_info;
+    VkVideoEncodeSessionParametersFeedbackInfoKHR params_feedback;
+
+    void *data = NULL;
+    size_t data_size = 0;
+
+    /* Generate SPS/PPS unit info */
+    err = init_sequence_headers(avctx);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to initialize sequence header: %s\n",
+               av_err2str(err));
+        return err;
+    }
+
+    /* Create session parameters from them */
+    err = create_session_params(avctx);
+    if (err < 0)
+        return err;
+
+    params_info = (VkVideoEncodeSessionParametersGetInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_GET_INFO_KHR,
+        .videoSessionParameters = ctx->session_params,
+    };
+    params_feedback = (VkVideoEncodeSessionParametersFeedbackInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_FEEDBACK_INFO_KHR,
+    };
+
+    ret = vk->GetEncodedVideoSessionParametersKHR(s->hwctx->act_dev, &params_info,
+                                                  &params_feedback,
+                                                  &data_size, data);
+    if (ret == VK_INCOMPLETE ||
+        (ret == VK_SUCCESS) && (data_size > 0)) {
+        data = av_mallocz(data_size);
+        if (!data)
+            return AVERROR(ENOMEM);
+    } else {
+        av_log(avctx, AV_LOG_ERROR, "Unable to get feedback for AV1 sequence header = %"SIZE_SPECIFIER"\n",
+               data_size);
+        return err;
+    }
+
+    ret = vk->GetEncodedVideoSessionParametersKHR(s->hwctx->act_dev, &params_info,
+                                                  &params_feedback,
+                                                  &data_size, data);
+    if (ret != VK_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Error writing feedback units\n");
+        return err;
+    }
+
+    av_log(avctx, AV_LOG_VERBOSE, "Feedback units written, overrides: %i\n",
+           params_feedback.hasOverrides);
+
+    params_feedback.hasOverrides = 1;
+
+    /* No need to sync any overrides */
+    if (!params_feedback.hasOverrides)
+        return 0;
+
+    /* Parse back tne units and override */
+    err = parse_feedback_units(avctx, data, data_size);
+    if (err < 0)
+        return err;
+
+    /* Create final session parameters */
+    err = create_session_params(avctx);
+    if (err < 0)
+        return err;
+
+    return 0;
+}
+
+static int vulkan_encode_av1_add_obu(AVCodecContext *avctx,
+                                     CodedBitstreamFragment *au,
+                                     uint8_t type, void *obu_unit)
+{
+    int err;
+
+    err = ff_cbs_insert_unit_content(au, -1,
+                                     type, obu_unit, NULL);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to add OBU unit: "
+               "type = %d.\n", type);
+        return err;
+    }
+
+    return err;
+}
+
+static int vulkan_encode_av1_write_obu(AVCodecContext *avctx,
+                                       uint8_t *data, size_t *data_len,
+                                       CodedBitstreamFragment *obu)
+{
+    VulkanEncodeAV1Context *enc = avctx->priv_data;
+    int ret;
+
+    ret = ff_cbs_write_fragment_data(enc->cbs, obu);
+    if (ret < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n");
+        return ret;
+    }
+
+    memcpy(data, obu->data, obu->data_size);
+    *data_len = obu->data_size;
+
+    return 0;
+}
+
+static int write_sequence_header(AVCodecContext *avctx,
+                                 FFHWBaseEncodePicture *base_pic,
+                                 uint8_t *data, size_t *data_len)
+{
+    int err;
+    VulkanEncodeAV1Context *enc = avctx->priv_data;
+    CodedBitstreamFragment *obu = &enc->current_access_unit;
+
+    err = vulkan_encode_av1_add_obu(avctx, obu,
+                                    AV1_OBU_SEQUENCE_HEADER, &enc->seq_hdr_obu);
+    if (err < 0)
+        goto fail;
+
+    err = vulkan_encode_av1_write_obu(avctx, data, data_len, obu);
+
+fail:
+    ff_cbs_fragment_reset(obu);
+    return err;
+}
+
+static int write_extra_headers(AVCodecContext *avctx,
+                               FFHWBaseEncodePicture *base_pic,
+                               uint8_t *data, size_t *data_len)
+{
+    int err;
+    VulkanEncodeAV1Context *enc = avctx->priv_data;
+    VulkanEncodeAV1Picture  *ap = base_pic->codec_priv;
+    CodedBitstreamFragment *obu = &enc->current_access_unit;
+
+    if (ap->units_needed & AV_FRAME_DATA_MASTERING_DISPLAY_METADATA) {
+        err = vulkan_encode_av1_add_obu(avctx, obu,
+                                        AV1_OBU_METADATA,
+                                        &enc->meta_mastering_obu);
+        if (err < 0)
+            goto fail;
+    }
+
+    if (ap->units_needed & UNIT_CONTENT_LIGHT_LEVEL) {
+        err = vulkan_encode_av1_add_obu(avctx, obu,
+                                        AV1_OBU_METADATA,
+                                        &enc->meta_cll_obu);
+        if (err < 0)
+            goto fail;
+    }
+
+    if (ap->units_needed) {
+        err = vulkan_encode_av1_write_obu(avctx, data, data_len, obu);
+        if (err < 0)
+            goto fail;
+    } else {
+        err = 0;
+        *data_len = 0;
+    }
+
+fail:
+    ff_cbs_fragment_reset(obu);
+    return err;
+}
+
+static int write_padding(AVCodecContext *avctx, uint32_t padding,
+                         uint8_t *data, size_t *data_len)
+{
+    int err;
+    VulkanEncodeAV1Context *enc = avctx->priv_data;
+    CodedBitstreamFragment *obu = &enc->current_access_unit;
+
+    AV1RawOBU padding_obu = { 0 };
+    AV1RawPadding *raw_padding = &padding_obu.obu.padding;
+
+    if (!padding)
+        padding = 16;
+
+    /* 2 byte header + 1 byte trailing bits */
+    padding_obu.header.obu_type = AV1_OBU_PADDING;
+    *raw_padding = (AV1RawPadding) {
+        .payload = enc->padding_payload,
+        .payload_size = padding,
+    };
+
+    err = vulkan_encode_av1_add_obu(avctx, obu, AV1_OBU_PADDING, &padding_obu);
+    if (err < 0)
+        goto fail;
+
+    err = vulkan_encode_av1_write_obu(avctx, data, data_len, obu);
+fail:
+    ff_cbs_fragment_reset(obu);
+    return err;
+}
+
+static const FFVulkanCodec enc_cb = {
+    .flags = FF_HW_FLAG_B_PICTURES |
+             FF_HW_FLAG_B_PICTURE_REFERENCES |
+             VK_ENC_FLAG_NO_DELAY |
+             FF_HW_FLAG_SLICE_CONTROL,
+    .picture_priv_data_size = sizeof(VulkanEncodeAV1Picture),
+    .filler_header_size = 4,
+    .init_profile = init_profile,
+    .init_pic_rc = init_pic_rc,
+    .init_pic_params = init_pic_params,
+    .write_sequence_headers = write_sequence_header,
+    .write_extra_headers = write_extra_headers,
+    .write_filler = write_padding,
+};
+
+static av_cold int vulkan_encode_av1_init(AVCodecContext *avctx)
+{
+    int err;
+    VulkanEncodeAV1Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext *ctx = &enc->common;
+    FFHWBaseEncodeContext *base_ctx = &ctx->base;
+    int flags;
+
+    if (avctx->profile == AV_PROFILE_UNKNOWN)
+        avctx->profile = enc->common.opts.profile;
+
+    enc->caps = (VkVideoEncodeAV1CapabilitiesKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_CAPABILITIES_KHR,
+    };
+
+    enc->quality_props = (VkVideoEncodeAV1QualityLevelPropertiesKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_QUALITY_LEVEL_PROPERTIES_KHR,
+    };
+
+    err = ff_vulkan_encode_init(avctx, &enc->common,
+                                &ff_vk_enc_av1_desc, &enc_cb,
+                                &enc->caps, &enc->quality_props);
+    if (err < 0)
+        return err;
+
+    av_log(avctx, AV_LOG_VERBOSE, "AV1 encoder capabilities:\n");
+    av_log(avctx, AV_LOG_VERBOSE, "    Standard capability flags:\n");
+    av_log(avctx, AV_LOG_VERBOSE, "        per_rate_control_group_min_max_q_index: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_AV1_CAPABILITY_PER_RATE_CONTROL_GROUP_MIN_MAX_Q_INDEX_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        generate_obu_extension_header: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_AV1_CAPABILITY_GENERATE_OBU_EXTENSION_HEADER_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        primary_reference_cdf_only: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_AV1_CAPABILITY_PRIMARY_REFERENCE_CDF_ONLY_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        frame_size_override: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_AV1_CAPABILITY_FRAME_SIZE_OVERRIDE_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        motion_vector_scaling: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_AV1_CAPABILITY_MOTION_VECTOR_SCALING_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "    Capabilities:\n");
+    av_log(avctx, AV_LOG_VERBOSE, "        64x64 superblocks: %i\n",
+           !!(enc->caps.superblockSizes & VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_64_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        128x128 superblocks: %i\n",
+           !!(enc->caps.superblockSizes & VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_128_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        maxSingleReferenceCount: %i\n",
+           enc->caps.maxSingleReferenceCount);
+    av_log(avctx, AV_LOG_VERBOSE, "        singleReferenceNameMask: 0x%x\n",
+           enc->caps.singleReferenceNameMask);
+    av_log(avctx, AV_LOG_VERBOSE, "        maxUnidirectionalCompoundReferenceCount: %i\n",
+           enc->caps.maxUnidirectionalCompoundReferenceCount);
+    av_log(avctx, AV_LOG_VERBOSE, "        maxUnidirectionalCompoundGroup1ReferenceCount: %i\n",
+           enc->caps.maxUnidirectionalCompoundGroup1ReferenceCount);
+    av_log(avctx, AV_LOG_VERBOSE, "        unidirectionalCompoundReferenceNameMask: 0x%x\n",
+           enc->caps.unidirectionalCompoundReferenceNameMask);
+    av_log(avctx, AV_LOG_VERBOSE, "        maxBidirectionalCompoundReferenceCount: %i\n",
+           enc->caps.maxBidirectionalCompoundReferenceCount);
+    av_log(avctx, AV_LOG_VERBOSE, "        maxBidirectionalCompoundGroup1ReferenceCount: %i\n",
+           enc->caps.maxBidirectionalCompoundGroup1ReferenceCount);
+    av_log(avctx, AV_LOG_VERBOSE, "        maxBidirectionalCompoundGroup2ReferenceCount: %i\n",
+           enc->caps.maxBidirectionalCompoundGroup2ReferenceCount);
+    av_log(avctx, AV_LOG_VERBOSE, "        bidirectionalCompoundReferenceNameMask: 0x%x\n",
+           enc->caps.bidirectionalCompoundReferenceNameMask);
+    av_log(avctx, AV_LOG_VERBOSE, "        maxTemporalLayerCount: %i\n",
+           enc->caps.maxTemporalLayerCount);
+    av_log(avctx, AV_LOG_VERBOSE, "        maxSpatialLayerCount: %i\n",
+           enc->caps.maxSpatialLayerCount);
+    av_log(avctx, AV_LOG_VERBOSE, "        maxOperatingPoints: %i\n",
+           enc->caps.maxOperatingPoints);
+    av_log(avctx, AV_LOG_VERBOSE, "        min/max Qindex: [%i, %i]\n",
+           enc->caps.minQIndex, enc->caps.maxQIndex);
+    av_log(avctx, AV_LOG_VERBOSE, "        prefersGopRemainingFrames: %i\n",
+           enc->caps.prefersGopRemainingFrames);
+    av_log(avctx, AV_LOG_VERBOSE, "        requiresGopRemainingFrames: %i\n",
+           enc->caps.requiresGopRemainingFrames);
+    av_log(avctx, AV_LOG_VERBOSE, "        maxLevel: %i\n",
+           enc->caps.maxLevel);
+    av_log(avctx, AV_LOG_VERBOSE, "        codedPictureAlignment: %ix%i\n",
+           enc->caps.codedPictureAlignment.width, enc->caps.codedPictureAlignment.height);
+    av_log(avctx, AV_LOG_VERBOSE, "        maxTiles: %ix%i\n",
+           enc->caps.maxTiles.width, enc->caps.maxTiles.height);
+    av_log(avctx, AV_LOG_VERBOSE, "        Tile size: %ix%i to %ix%i\n",
+           enc->caps.minTileSize.width, enc->caps.minTileSize.height,
+           enc->caps.maxTileSize.width, enc->caps.maxTileSize.height);
+
+    err = init_enc_options(avctx);
+    if (err < 0)
+        return err;
+
+    flags = ctx->codec->flags;
+    err = ff_hw_base_init_gop_structure(base_ctx, avctx,
+                                        ctx->caps.maxDpbSlots,
+                                        enc->caps.maxBidirectionalCompoundReferenceCount,
+                                        flags, 0);
+    if (err < 0)
+        return err;
+
+    base_ctx->output_delay = base_ctx->b_per_p;
+    base_ctx->decode_delay = base_ctx->max_b_depth;
+
+    /* Create units and session parameters */
+    err = init_base_units(avctx);
+    if (err < 0)
+        return err;
+
+    /* Init CBS */
+    err = ff_cbs_init(&enc->cbs, AV_CODEC_ID_AV1, avctx);
+    if (err < 0)
+        return err;
+
+    if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
+        uint8_t data[4096];
+        size_t data_len = sizeof(data);
+
+        err = write_sequence_header(avctx, NULL, data, &data_len);
+        if (err < 0) {
+            av_log(avctx, AV_LOG_ERROR, "Failed to write sequence header "
+                   "for extradata: %d.\n", err);
+            return err;
+        } else {
+            avctx->extradata_size = data_len;
+            avctx->extradata = av_mallocz(avctx->extradata_size +
+                                          AV_INPUT_BUFFER_PADDING_SIZE);
+            if (!avctx->extradata) {
+                err = AVERROR(ENOMEM);
+                return err;
+            }
+            memcpy(avctx->extradata, data, avctx->extradata_size);
+        }
+    }
+
+    enc->padding_payload = av_mallocz(2*ctx->caps.minBitstreamBufferOffsetAlignment);
+    if (!enc->padding_payload)
+        return AVERROR(ENOMEM);
+
+    memset(enc->padding_payload, 0xaa, 2*ctx->caps.minBitstreamBufferOffsetAlignment);
+
+    return 0;
+}
+
+static av_cold int vulkan_encode_av1_close(AVCodecContext *avctx)
+{
+    VulkanEncodeAV1Context *enc = avctx->priv_data;
+    av_free(enc->padding_payload);
+    ff_vulkan_encode_uninit(&enc->common);
+    return 0;
+}
+
+#define OFFSET(x) offsetof(VulkanEncodeAV1Context, x)
+#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
+static const AVOption vulkan_encode_av1_options[] = {
+    HW_BASE_ENCODE_COMMON_OPTIONS,
+    VULKAN_ENCODE_COMMON_OPTIONS,
+
+    { "profile", "Set profile",
+      OFFSET(common.opts.profile), AV_OPT_TYPE_INT,
+      { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, 0xffff, FLAGS, .unit = "profile" },
+
+#define PROFILE(name, value)  name, NULL, 0, AV_OPT_TYPE_CONST, \
+      { .i64 = value }, 0, 0, FLAGS, .unit = "profile"
+    { PROFILE("main",                 AV_PROFILE_AV1_MAIN) },
+    { PROFILE("high",                 AV_PROFILE_AV1_HIGH) },
+    { PROFILE("professional",         AV_PROFILE_AV1_PROFESSIONAL) },
+#undef PROFILE
+
+    { "tier", "Set tier (seq_tier)",
+      OFFSET(common.opts.tier), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, .unit = "tier" },
+        { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, .unit = "tier" },
+        { "high", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, .unit = "tier" },
+
+    { "level", "Set level (level_idc)",
+      OFFSET(common.opts.level), AV_OPT_TYPE_INT,
+      { .i64 = AV_LEVEL_UNKNOWN }, AV_LEVEL_UNKNOWN, 0xff, FLAGS, .unit = "level" },
+
+#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
+      { .i64 = value }, 0, 0, FLAGS, .unit = "level"
+    { LEVEL("20", 0) },
+    { LEVEL("21", 1) },
+    { LEVEL("22", 2) },
+    { LEVEL("23", 3) },
+    { LEVEL("30", 4) },
+    { LEVEL("31", 5) },
+    { LEVEL("32", 6) },
+    { LEVEL("33", 7) },
+    { LEVEL("40", 8) },
+    { LEVEL("41", 9) },
+    { LEVEL("42", 10) },
+    { LEVEL("43", 11) },
+    { LEVEL("50", 12) },
+    { LEVEL("51", 13) },
+    { LEVEL("52", 14) },
+    { LEVEL("53", 15) },
+    { LEVEL("60", 16) },
+    { LEVEL("61", 17) },
+    { LEVEL("62", 18) },
+    { LEVEL("63", 19) },
+    { LEVEL("70", 20) },
+    { LEVEL("71", 21) },
+    { LEVEL("72", 22) },
+    { LEVEL("73", 23) },
+#undef LEVEL
+
+    { "units", "Set units to include", OFFSET(unit_elems), AV_OPT_TYPE_FLAGS, { .i64 = UNIT_MASTERING_DISPLAY | UNIT_CONTENT_LIGHT_LEVEL }, 0, INT_MAX, FLAGS, "units" },
+        { "hdr",        "Include HDR metadata for mastering display colour volume and content light level information", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_MASTERING_DISPLAY | UNIT_CONTENT_LIGHT_LEVEL }, INT_MIN, INT_MAX, FLAGS, "units" },
+
+    { NULL },
+};
+
+static const FFCodecDefault vulkan_encode_av1_defaults[] = {
+    { "b",              "0"   },
+    { "bf",             "2"   },
+    { "g",              "300" },
+    { "qmin",           "1"   },
+    { "qmax",           "255" },
+    { "refs",           "0"   },
+    { NULL },
+};
+
+static const AVClass vulkan_encode_av1_class = {
+    .class_name = "av1_vulkan",
+    .item_name  = av_default_item_name,
+    .option     = vulkan_encode_av1_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+const FFCodec ff_av1_vulkan_encoder = {
+    .p.name         = "av1_vulkan",
+    CODEC_LONG_NAME("AV1 (Vulkan)"),
+    .p.type         = AVMEDIA_TYPE_VIDEO,
+    .p.id           = AV_CODEC_ID_AV1,
+    .priv_data_size = sizeof(VulkanEncodeAV1Context),
+    .init           = &vulkan_encode_av1_init,
+    FF_CODEC_RECEIVE_PACKET_CB(&ff_vulkan_encode_receive_packet),
+    .close          = &vulkan_encode_av1_close,
+    .p.priv_class   = &vulkan_encode_av1_class,
+    .p.capabilities = AV_CODEC_CAP_DELAY |
+                      AV_CODEC_CAP_HARDWARE |
+                      AV_CODEC_CAP_DR1 |
+                      AV_CODEC_CAP_ENCODER_FLUSH |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
+    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
+    .defaults       = vulkan_encode_av1_defaults,
+    CODEC_PIXFMTS(AV_PIX_FMT_VULKAN),
+    .hw_configs     = ff_vulkan_encode_hw_configs,
+    .p.wrapper_name = "vulkan",
+};
-- 
2.49.1


From ba55a3eea07d7300edb5d8de02ba0856a4a0b629 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:33:26 +0000
Subject: [PATCH 075/118] Changing vulkan file directory

---
 libavcodec/vulkan_encode_h264.c | 1668 -------------------------------
 1 file changed, 1668 deletions(-)
 delete mode 100644 libavcodec/vulkan_encode_h264.c

diff --git a/libavcodec/vulkan_encode_h264.c b/libavcodec/vulkan_encode_h264.c
deleted file mode 100644
index 942e911fb7..0000000000
--- a/libavcodec/vulkan_encode_h264.c
+++ /dev/null
@@ -1,1668 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/internal.h"
-#include "libavutil/opt.h"
-#include "libavutil/mem.h"
-
-#include "cbs.h"
-#include "cbs_h264.h"
-#include "atsc_a53.h"
-
-#include "h264_levels.h"
-#include "h2645data.h"
-#include "codec_internal.h"
-#include "version.h"
-#include "hw_base_encode_h264.h"
-
-#include "vulkan_encode.h"
-
-enum UnitElems {
-    UNIT_AUD            = 1 << 0,
-    UNIT_SEI_TIMING     = 1 << 1,
-    UNIT_SEI_IDENTIFIER = 1 << 2,
-    UNIT_SEI_RECOVERY   = 1 << 3,
-    UNIT_SEI_A53_CC     = 1 << 4,
-};
-
-const FFVulkanEncodeDescriptor ff_vk_enc_h264_desc = {
-    .codec_id         = AV_CODEC_ID_H264,
-    .encode_extension = FF_VK_EXT_VIDEO_ENCODE_H264,
-    .encode_op        = VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR,
-    .ext_props = {
-        .extensionName = VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_EXTENSION_NAME,
-        .specVersion   = VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION,
-    },
-};
-
-/* Random (version 4) ISO 11578 UUID. */
-static const uint8_t vulkan_encode_h264_sei_identifier_uuid[16] = {
-    0x03, 0xfd, 0xf2, 0x0a, 0x5d, 0x4c, 0x05, 0x48,
-    0x20, 0x98, 0xca, 0x6b, 0x0c, 0x95, 0x30, 0x1c,
-};
-
-typedef struct VulkanEncodeH264Picture {
-    int frame_num;
-    int64_t last_idr_frame;
-    uint16_t idr_pic_id;
-    int primary_pic_type;
-    int slice_type;
-    int pic_order_cnt;
-
-    enum UnitElems units_needed;
-
-    VkVideoEncodeH264RateControlInfoKHR vkrc_info;
-    VkVideoEncodeH264RateControlLayerInfoKHR vkrc_layer_info;
-    VkVideoEncodeH264GopRemainingFrameInfoKHR vkrc_remaining;
-
-    StdVideoEncodeH264WeightTable slice_wt;
-    StdVideoEncodeH264SliceHeader slice_hdr;
-    VkVideoEncodeH264NaluSliceInfoKHR vkslice;
-
-    StdVideoEncodeH264PictureInfo   h264pic_info;
-    VkVideoEncodeH264PictureInfoKHR vkh264pic_info;
-
-    StdVideoEncodeH264ReferenceInfo h264dpb_info;
-    VkVideoEncodeH264DpbSlotInfoKHR vkh264dpb_info;
-
-    StdVideoEncodeH264RefListModEntry mods[MAX_REFERENCE_LIST_NUM][H264_MAX_RPLM_COUNT];
-    StdVideoEncodeH264RefPicMarkingEntry mmco[H264_MAX_RPLM_COUNT];
-    StdVideoEncodeH264ReferenceListsInfo ref_list_info;
-} VulkanEncodeH264Picture;
-
-typedef struct VulkanEncodeH264Context {
-    FFVulkanEncodeContext common;
-
-    FFHWBaseEncodeH264 units;
-    FFHWBaseEncodeH264Opts unit_opts;
-
-    enum UnitElems unit_elems;
-
-    uint8_t fixed_qp_p;
-    uint8_t fixed_qp_b;
-
-    VkVideoEncodeH264ProfileInfoKHR profile;
-
-    VkVideoEncodeH264CapabilitiesKHR caps;
-    VkVideoEncodeH264QualityLevelPropertiesKHR quality_props;
-
-    CodedBitstreamContext *cbs;
-    CodedBitstreamFragment current_access_unit;
-
-    H264RawAUD                  raw_aud;
-
-    SEIRawUserDataUnregistered  sei_identifier;
-    H264RawSEIPicTiming         sei_pic_timing;
-    H264RawSEIRecoveryPoint     sei_recovery_point;
-    SEIRawUserDataRegistered    sei_a53cc;
-    void                       *sei_a53cc_data;
-    char                       *sei_identifier_string;
-} VulkanEncodeH264Context;
-
-static int init_pic_rc(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
-                       VkVideoEncodeRateControlInfoKHR *rc_info,
-                       VkVideoEncodeRateControlLayerInfoKHR *rc_layer)
-{
-    VulkanEncodeH264Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext   *ctx = &enc->common;
-    VulkanEncodeH264Picture  *hp = pic->codec_priv;
-
-    hp->vkrc_info = (VkVideoEncodeH264RateControlInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_KHR,
-        .flags = VK_VIDEO_ENCODE_H264_RATE_CONTROL_REFERENCE_PATTERN_FLAT_BIT_KHR |
-                 VK_VIDEO_ENCODE_H264_RATE_CONTROL_REGULAR_GOP_BIT_KHR,
-        .idrPeriod = ctx->base.gop_size,
-        .gopFrameCount = ctx->base.gop_size,
-        .consecutiveBFrameCount = FFMAX(ctx->base.b_per_p - 1, 0),
-        .temporalLayerCount = 0,
-    };
-    rc_info->pNext = &hp->vkrc_info;
-
-    if (rc_info->rateControlMode > VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
-        rc_info->virtualBufferSizeInMs = (enc->unit_opts.hrd_buffer_size * 1000LL) / avctx->bit_rate;
-        rc_info->initialVirtualBufferSizeInMs = (enc->unit_opts.initial_buffer_fullness * 1000LL) / avctx->bit_rate;
-
-        hp->vkrc_layer_info = (VkVideoEncodeH264RateControlLayerInfoKHR) {
-            .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_KHR,
-
-            .useMinQp  = avctx->qmin > 0,
-            .minQp.qpI = avctx->qmin > 0 ? avctx->qmin : 0,
-            .minQp.qpP = avctx->qmin > 0 ? avctx->qmin : 0,
-            .minQp.qpB = avctx->qmin > 0 ? avctx->qmin : 0,
-
-            .useMaxQp  = avctx->qmax > 0,
-            .maxQp.qpI = avctx->qmax > 0 ? avctx->qmax : 0,
-            .maxQp.qpP = avctx->qmax > 0 ? avctx->qmax : 0,
-            .maxQp.qpB = avctx->qmax > 0 ? avctx->qmax : 0,
-
-            .useMaxFrameSize = 0,
-        };
-        rc_layer->pNext = &hp->vkrc_layer_info;
-        hp->vkrc_info.temporalLayerCount = 1;
-    }
-
-    return 0;
-}
-
-static int vk_enc_h264_update_pic_info(AVCodecContext *avctx,
-                                       FFHWBaseEncodePicture *pic)
-{
-    VulkanEncodeH264Context   *enc = avctx->priv_data;
-    FFVulkanEncodeContext     *ctx = &enc->common;
-    VulkanEncodeH264Picture    *hp = pic->codec_priv;
-    FFHWBaseEncodePicture    *prev = pic->prev;
-    VulkanEncodeH264Picture *hprev = prev ? prev->codec_priv : NULL;
-
-    if (pic->type == FF_HW_PICTURE_TYPE_IDR) {
-        av_assert0(pic->display_order == pic->encode_order);
-
-        hp->frame_num      = 0;
-        hp->last_idr_frame = pic->display_order;
-        hp->idr_pic_id     = hprev ? hprev->idr_pic_id + 1 : 0;
-
-        hp->primary_pic_type = 0;
-        hp->slice_type       = STD_VIDEO_H264_SLICE_TYPE_I;
-    } else {
-        av_assert0(prev);
-
-        hp->frame_num = hprev->frame_num + prev->is_reference;
-
-        hp->last_idr_frame = hprev->last_idr_frame;
-        hp->idr_pic_id     = hprev->idr_pic_id;
-
-        if (pic->type == FF_HW_PICTURE_TYPE_I) {
-            hp->slice_type       = STD_VIDEO_H264_SLICE_TYPE_I;
-            hp->primary_pic_type = 0;
-        } else if (pic->type == FF_HW_PICTURE_TYPE_P) {
-            hp->slice_type       = STD_VIDEO_H264_SLICE_TYPE_P;
-            hp->primary_pic_type = 1;
-        } else {
-            hp->slice_type       = STD_VIDEO_H264_SLICE_TYPE_B;
-            hp->primary_pic_type = 2;
-        }
-    }
-
-    hp->pic_order_cnt = pic->display_order - hp->last_idr_frame;
-    if (enc->units.raw_sps.pic_order_cnt_type == 2)
-        hp->pic_order_cnt *= 2;
-
-    hp->units_needed = 0;
-
-    if (enc->unit_elems & UNIT_SEI_IDENTIFIER && pic->encode_order == 0)
-        hp->units_needed |= UNIT_SEI_IDENTIFIER;
-
-    if (enc->unit_elems & UNIT_SEI_TIMING) {
-        enc->sei_pic_timing = (H264RawSEIPicTiming) {
-            .cpb_removal_delay = 2 * (pic->encode_order - hp->last_idr_frame),
-            .dpb_output_delay  = 2 * (pic->display_order - pic->encode_order + ctx->base.max_b_depth),
-        };
-
-        hp->units_needed |= UNIT_SEI_TIMING;
-    }
-
-    if (enc->unit_elems & UNIT_SEI_RECOVERY && pic->type == FF_HW_PICTURE_TYPE_I) {
-        enc->sei_recovery_point = (H264RawSEIRecoveryPoint) {
-            .recovery_frame_cnt = 0,
-            .exact_match_flag   = 1,
-            .broken_link_flag   = ctx->base.b_per_p > 0,
-        };
-
-        hp->units_needed |= UNIT_SEI_RECOVERY;
-    }
-
-    if (enc->unit_elems & UNIT_SEI_A53_CC) {
-        int err;
-        size_t sei_a53cc_len;
-        av_freep(&enc->sei_a53cc_data);
-        err = ff_alloc_a53_sei(pic->input_image, 0, &enc->sei_a53cc_data, &sei_a53cc_len);
-        if (err < 0)
-            return err;
-        if (enc->sei_a53cc_data != NULL) {
-            enc->sei_a53cc.itu_t_t35_country_code = 181;
-            enc->sei_a53cc.data = (uint8_t *)enc->sei_a53cc_data + 1;
-            enc->sei_a53cc.data_length = sei_a53cc_len - 1;
-
-            hp->units_needed |= UNIT_SEI_A53_CC;
-        }
-    }
-
-    return 0;
-}
-
-static void setup_slices(AVCodecContext *avctx,
-                         FFHWBaseEncodePicture *pic)
-{
-    VulkanEncodeH264Context *enc = avctx->priv_data;
-    VulkanEncodeH264Picture *hp = pic->codec_priv;
-
-    hp->slice_wt = (StdVideoEncodeH264WeightTable) {
-        .flags = (StdVideoEncodeH264WeightTableFlags) {
-            .luma_weight_l0_flag = 0,
-            .chroma_weight_l0_flag = 0,
-            .luma_weight_l1_flag = 0,
-            .chroma_weight_l1_flag = 0,
-        },
-        .luma_log2_weight_denom = 0,
-        .chroma_log2_weight_denom = 0,
-        .luma_weight_l0 = { 0 },
-        .luma_offset_l0 = { 0 },
-        .chroma_weight_l0 = { { 0 } },
-        .chroma_offset_l0 = { { 0 } },
-        .luma_weight_l1 = { 0 },
-        .luma_offset_l1 = { 0 },
-        .chroma_weight_l1 = { { 0 } },
-        .chroma_offset_l1 = { { 0 } },
-    };
-
-    hp->slice_hdr = (StdVideoEncodeH264SliceHeader) {
-        .flags = (StdVideoEncodeH264SliceHeaderFlags) {
-            .direct_spatial_mv_pred_flag = 1,
-            /* The vk_samples code does this */
-            .num_ref_idx_active_override_flag =
-                ((enc->units.raw_pps.num_ref_idx_l0_default_active_minus1) &&
-                 (pic->type == FF_HW_PICTURE_TYPE_B)) ? 1 : 0,
-        },
-        .first_mb_in_slice = 1,
-        .slice_type = hp->slice_type,
-        .slice_alpha_c0_offset_div2 = 0,
-        .slice_beta_offset_div2 = 0,
-        .slice_qp_delta = 0, /* Filled in below */
-        /* Reserved */
-        .cabac_init_idc = 0,
-        .disable_deblocking_filter_idc = 0,
-        .pWeightTable = NULL, // &hp->slice_wt,
-    };
-
-    hp->vkslice = (VkVideoEncodeH264NaluSliceInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_INFO_KHR,
-        .pNext = NULL,
-        .constantQp = pic->type == FF_HW_PICTURE_TYPE_B ? enc->fixed_qp_b :
-                      pic->type == FF_HW_PICTURE_TYPE_P ? enc->fixed_qp_p :
-                                                          enc->unit_opts.fixed_qp_idr,
-        .pStdSliceHeader = &hp->slice_hdr,
-    };
-
-    if (enc->common.opts.rc_mode != VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR)
-        hp->vkslice.constantQp = 0;
-
-    hp->slice_hdr.slice_qp_delta = hp->vkslice.constantQp -
-                                   (enc->units.raw_pps.pic_init_qp_minus26 + 26);
-
-    hp->vkh264pic_info.pNaluSliceEntries = &hp->vkslice;
-    hp->vkh264pic_info.naluSliceEntryCount = 1;
-}
-
-static void vk_enc_h264_default_ref_pic_list(AVCodecContext *avctx,
-                                             FFHWBaseEncodePicture *pic,
-                                             FFHWBaseEncodePicture **rpl0,
-                                             FFHWBaseEncodePicture **rpl1,
-                                             int *rpl_size)
-{
-    FFHWBaseEncodePicture *prev;
-    VulkanEncodeH264Picture *hp, *hn, *hc;
-    int i, j, n = 0;
-
-    prev = pic->prev;
-    av_assert0(prev);
-    hp = pic->codec_priv;
-
-    for (i = 0; i < pic->prev->nb_dpb_pics; i++) {
-        hn = prev->dpb[i]->codec_priv;
-        av_assert0(hn->frame_num < hp->frame_num);
-
-        if (pic->type == FF_HW_PICTURE_TYPE_P) {
-            for (j = n; j > 0; j--) {
-                hc = rpl0[j - 1]->codec_priv;
-                av_assert0(hc->frame_num != hn->frame_num);
-                if (hc->frame_num > hn->frame_num)
-                    break;
-                rpl0[j] = rpl0[j - 1];
-            }
-            rpl0[j] = prev->dpb[i];
-
-        } else if (pic->type == FF_HW_PICTURE_TYPE_B) {
-            for (j = n; j > 0; j--) {
-                hc = rpl0[j - 1]->codec_priv;
-                av_assert0(hc->pic_order_cnt != hp->pic_order_cnt);
-                if (hc->pic_order_cnt < hp->pic_order_cnt) {
-                    if (hn->pic_order_cnt > hp->pic_order_cnt ||
-                        hn->pic_order_cnt < hc->pic_order_cnt)
-                        break;
-                } else {
-                    if (hn->pic_order_cnt > hc->pic_order_cnt)
-                        break;
-                }
-                rpl0[j] = rpl0[j - 1];
-            }
-            rpl0[j] = prev->dpb[i];
-
-            for (j = n; j > 0; j--) {
-                hc = rpl1[j - 1]->codec_priv;
-                av_assert0(hc->pic_order_cnt != hp->pic_order_cnt);
-                if (hc->pic_order_cnt > hp->pic_order_cnt) {
-                    if (hn->pic_order_cnt < hp->pic_order_cnt ||
-                        hn->pic_order_cnt > hc->pic_order_cnt)
-                        break;
-                } else {
-                    if (hn->pic_order_cnt < hc->pic_order_cnt)
-                        break;
-                }
-                rpl1[j] = rpl1[j - 1];
-            }
-            rpl1[j] = prev->dpb[i];
-        }
-
-        ++n;
-    }
-
-    if (pic->type == FF_HW_PICTURE_TYPE_B) {
-        for (i = 0; i < n; i++) {
-            if (rpl0[i] != rpl1[i])
-                break;
-        }
-        if (i == n)
-            FFSWAP(FFHWBaseEncodePicture *, rpl1[0], rpl1[1]);
-    }
-
-    if (pic->type == FF_HW_PICTURE_TYPE_P ||
-        pic->type == FF_HW_PICTURE_TYPE_B) {
-        av_log(avctx, AV_LOG_DEBUG, "Default RefPicList0 for fn=%d/poc=%d:",
-               hp->frame_num, hp->pic_order_cnt);
-        for (i = 0; i < n; i++) {
-            hn = rpl0[i]->codec_priv;
-            av_log(avctx, AV_LOG_DEBUG, "  fn=%d/poc=%d",
-                   hn->frame_num, hn->pic_order_cnt);
-        }
-        av_log(avctx, AV_LOG_DEBUG, "\n");
-    }
-    if (pic->type == FF_HW_PICTURE_TYPE_B) {
-        av_log(avctx, AV_LOG_DEBUG, "Default RefPicList1 for fn=%d/poc=%d:",
-               hp->frame_num, hp->pic_order_cnt);
-        for (i = 0; i < n; i++) {
-            hn = rpl1[i]->codec_priv;
-            av_log(avctx, AV_LOG_DEBUG, "  fn=%d/poc=%d",
-                   hn->frame_num, hn->pic_order_cnt);
-        }
-        av_log(avctx, AV_LOG_DEBUG, "\n");
-    }
-
-    *rpl_size = n;
-}
-
-static void setup_refs(AVCodecContext *avctx,
-                       FFHWBaseEncodePicture *pic,
-                       VkVideoEncodeInfoKHR *encode_info)
-{
-    int n, i, j;
-    VulkanEncodeH264Context *enc = avctx->priv_data;
-    VulkanEncodeH264Picture *hp = pic->codec_priv;
-    FFHWBaseEncodePicture *prev = pic->prev;
-    FFHWBaseEncodePicture *def_l0[MAX_DPB_SIZE], *def_l1[MAX_DPB_SIZE];
-    VulkanEncodeH264Picture *href;
-
-    hp->ref_list_info = (StdVideoEncodeH264ReferenceListsInfo) {
-        .flags = (StdVideoEncodeH264ReferenceListsInfoFlags) {
-            .ref_pic_list_modification_flag_l0 = 0,
-            .ref_pic_list_modification_flag_l1 = 0,
-            /* Reserved */
-        },
-        /* May be overridden during setup_slices() */
-        .num_ref_idx_l0_active_minus1 = pic->nb_refs[0] - 1,
-        .num_ref_idx_l1_active_minus1 = pic->nb_refs[1] - 1,
-        /* .RefPicList0 is set in vk_enc_h264_default_ref_pic_list() */
-        /* .RefPicList1 is set in vk_enc_h264_default_ref_pic_list() */
-        /* Reserved */
-        .pRefList0ModOperations = NULL, /* All set below */
-        .refList0ModOpCount = 0,
-        .pRefList1ModOperations = NULL,
-        .refList1ModOpCount = 0,
-        .pRefPicMarkingOperations = NULL,
-        .refPicMarkingOpCount = 0,
-    };
-
-    for (i = 0; i < STD_VIDEO_H264_MAX_NUM_LIST_REF; i++)
-        hp->ref_list_info.RefPicList0[i] = hp->ref_list_info.RefPicList1[i] = -1;
-
-    /* Note: really not sure */
-    for (int i = 0; i < pic->nb_refs[0]; i++) {
-        VkVideoReferenceSlotInfoKHR *slot_info;
-        slot_info = (VkVideoReferenceSlotInfoKHR *)&encode_info->pReferenceSlots[i];
-        hp->ref_list_info.RefPicList0[i] = slot_info->slotIndex;
-    }
-
-    /* Note: really not sure */
-    for (int i = 0; i < pic->nb_refs[1]; i++) {
-        VkVideoReferenceSlotInfoKHR *slot_info;
-        slot_info = (VkVideoReferenceSlotInfoKHR *)&encode_info->pReferenceSlots[pic->nb_refs[0] + i];
-        hp->ref_list_info.RefPicList1[i] = slot_info->slotIndex;
-    }
-
-    hp->h264pic_info.pRefLists = &hp->ref_list_info;
-
-    if (pic->is_reference && pic->type != FF_HW_PICTURE_TYPE_IDR) {
-        FFHWBaseEncodePicture *discard_list[MAX_DPB_SIZE];
-        int discard = 0, keep = 0;
-
-        // Discard everything which is in the DPB of the previous frame but
-        // not in the DPB of this one.
-        for (i = 0; i < prev->nb_dpb_pics; i++) {
-            for (j = 0; j < pic->nb_dpb_pics; j++) {
-                if (prev->dpb[i] == pic->dpb[j])
-                    break;
-            }
-            if (j == pic->nb_dpb_pics) {
-                discard_list[discard] = prev->dpb[i];
-                ++discard;
-            } else {
-                ++keep;
-            }
-        }
-        av_assert0(keep <= enc->units.dpb_frames);
-
-        if (discard == 0) {
-            hp->h264pic_info.flags.adaptive_ref_pic_marking_mode_flag = 0;
-        } else {
-            hp->h264pic_info.flags.adaptive_ref_pic_marking_mode_flag = 1;
-            for (i = 0; i < discard; i++) {
-                VulkanEncodeH264Picture *old = discard_list[i]->codec_priv;
-                av_assert0(old->frame_num < hp->frame_num);
-                hp->mmco[i] = (StdVideoEncodeH264RefPicMarkingEntry) {
-                    .memory_management_control_operation = 1,
-                    .difference_of_pic_nums_minus1 = hp->frame_num - old->frame_num - 1,
-                };
-            }
-            hp->mmco[i] = (StdVideoEncodeH264RefPicMarkingEntry) {
-                .memory_management_control_operation = 0,
-            };
-            hp->ref_list_info.pRefPicMarkingOperations = hp->mmco;
-            hp->ref_list_info.refPicMarkingOpCount = i + 1;
-        }
-    }
-
-    if (pic->type == FF_HW_PICTURE_TYPE_I || pic->type == FF_HW_PICTURE_TYPE_IDR)
-        return;
-
-    // If the intended references are not the first entries of RefPicListN
-    // by default, use ref-pic-list-modification to move them there.
-    vk_enc_h264_default_ref_pic_list(avctx, pic,
-                                     def_l0, def_l1, &n);
-
-    if (pic->type == FF_HW_PICTURE_TYPE_P) {
-        int need_rplm = 0;
-        for (i = 0; i < pic->nb_refs[0]; i++) {
-            av_assert0(pic->refs[0][i]);
-            if (pic->refs[0][i] != (FFHWBaseEncodePicture *)def_l0[i])
-                need_rplm = 1;
-        }
-
-        hp->ref_list_info.flags.ref_pic_list_modification_flag_l0 = need_rplm;
-        if (need_rplm) {
-            int pic_num = hp->frame_num;
-            for (i = 0; i < pic->nb_refs[0]; i++) {
-                href = pic->refs[0][i]->codec_priv;
-                av_assert0(href->frame_num != pic_num);
-                if (href->frame_num < pic_num) {
-                    hp->mods[0][i] = (StdVideoEncodeH264RefListModEntry) {
-                        .modification_of_pic_nums_idc = 0,
-                        .abs_diff_pic_num_minus1 = pic_num - href->frame_num - 1,
-                    };
-                } else {
-                    hp->mods[0][i] = (StdVideoEncodeH264RefListModEntry) {
-                        .modification_of_pic_nums_idc = 1,
-                        .abs_diff_pic_num_minus1 = href->frame_num - pic_num - 1,
-                    };
-                }
-                pic_num = href->frame_num;
-            }
-            hp->ref_list_info.pRefList0ModOperations = hp->mods[0];
-            hp->ref_list_info.refList0ModOpCount = i - 1;
-        }
-    } else {
-        int need_rplm_l0 = 0, need_rplm_l1 = 0;
-        int n0 = 0, n1 = 0;
-        for (i = 0; i < pic->nb_refs[0]; i++) {
-            av_assert0(pic->refs[0][i]);
-            href = pic->refs[0][i]->codec_priv;
-            av_assert0(href->pic_order_cnt < hp->pic_order_cnt);
-            if (pic->refs[0][i] != (FFHWBaseEncodePicture *)def_l0[n0])
-                need_rplm_l0 = 1;
-            ++n0;
-        }
-
-        for (int i = 0; i < pic->nb_refs[1]; i++) {
-            av_assert0(pic->refs[1][i]);
-            href = pic->refs[1][i]->codec_priv;
-            av_assert0(href->pic_order_cnt > hp->pic_order_cnt);
-            if (pic->refs[1][i] != (FFHWBaseEncodePicture *)def_l1[n1])
-                need_rplm_l1 = 1;
-            ++n1;
-        }
-
-        hp->ref_list_info.flags.ref_pic_list_modification_flag_l0 = need_rplm_l0;
-        if (need_rplm_l0) {
-            int pic_num = hp->frame_num;
-            for (i = j = 0; i < pic->nb_refs[0]; i++) {
-                href = pic->refs[0][i]->codec_priv;
-                av_assert0(href->frame_num != pic_num);
-                if (href->frame_num < pic_num) {
-                    hp->mods[0][j] = (StdVideoEncodeH264RefListModEntry) {
-                        .modification_of_pic_nums_idc = 0,
-                        .abs_diff_pic_num_minus1 = pic_num - href->frame_num - 1,
-                    };
-                } else {
-                    hp->mods[0][j] = (StdVideoEncodeH264RefListModEntry) {
-                        .modification_of_pic_nums_idc = 1,
-                        .abs_diff_pic_num_minus1 = href->frame_num - pic_num - 1,
-                    };
-                }
-                pic_num = href->frame_num;
-                ++j;
-            }
-            hp->ref_list_info.pRefList0ModOperations = hp->mods[0];
-            hp->ref_list_info.refList0ModOpCount = j - 1;
-        }
-
-        hp->ref_list_info.flags.ref_pic_list_modification_flag_l1 = need_rplm_l1;
-        if (need_rplm_l1) {
-            int pic_num = hp->frame_num;
-            for (i = j = 0; i < pic->nb_refs[1]; i++) {
-                href = pic->refs[1][i]->codec_priv;
-                av_assert0(href->frame_num != pic_num);
-                if (href->frame_num < pic_num) {
-                    hp->mods[1][j] = (StdVideoEncodeH264RefListModEntry) {
-                        .modification_of_pic_nums_idc = 0,
-                        .abs_diff_pic_num_minus1 = pic_num - href->frame_num - 1,
-                    };
-                } else {
-                    hp->mods[1][j] = (StdVideoEncodeH264RefListModEntry) {
-                        .modification_of_pic_nums_idc = 1,
-                        .abs_diff_pic_num_minus1 = href->frame_num - pic_num - 1,
-                    };
-                }
-                pic_num = href->frame_num;
-                ++j;
-            }
-            hp->ref_list_info.pRefList1ModOperations = hp->mods[1];
-            hp->ref_list_info.refList1ModOpCount = j - 1;
-        }
-    }
-}
-
-static int init_pic_params(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
-                           VkVideoEncodeInfoKHR *encode_info)
-{
-    int err;
-    FFVulkanEncodePicture *vp = pic->priv;
-    VulkanEncodeH264Picture *hp = pic->codec_priv;
-    VkVideoReferenceSlotInfoKHR *ref_slot;
-
-    err = vk_enc_h264_update_pic_info(avctx, pic);
-    if (err < 0)
-        return err;
-
-    hp->vkh264pic_info = (VkVideoEncodeH264PictureInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PICTURE_INFO_KHR,
-        .pNext = NULL,
-        .pNaluSliceEntries = NULL, // Filled in during setup_slices()
-        .naluSliceEntryCount = 0, // Filled in during setup_slices()
-        .pStdPictureInfo = &hp->h264pic_info,
-    };
-
-    hp->h264pic_info = (StdVideoEncodeH264PictureInfo) {
-        .flags = (StdVideoEncodeH264PictureInfoFlags) {
-            .IdrPicFlag = pic->type == FF_HW_PICTURE_TYPE_IDR,
-            .is_reference = pic->is_reference,
-            .no_output_of_prior_pics_flag = 0,
-            .long_term_reference_flag = 0,
-            .adaptive_ref_pic_marking_mode_flag = 0, // Filled in during setup_refs()
-            /* Reserved */
-        },
-        .seq_parameter_set_id = 0,
-        .pic_parameter_set_id = 0,
-        .idr_pic_id = hp->idr_pic_id,
-        .primary_pic_type = pic->type == FF_HW_PICTURE_TYPE_P ? STD_VIDEO_H264_PICTURE_TYPE_P :
-                            pic->type == FF_HW_PICTURE_TYPE_B ? STD_VIDEO_H264_PICTURE_TYPE_B :
-                            pic->type == FF_HW_PICTURE_TYPE_I ? STD_VIDEO_H264_PICTURE_TYPE_I :
-                                                                STD_VIDEO_H264_PICTURE_TYPE_IDR,
-        .frame_num = hp->frame_num,
-        .PicOrderCnt = hp->pic_order_cnt,
-        .temporal_id = 0, /* ? */
-        /* Reserved */
-        .pRefLists = NULL, // Filled in during setup_refs
-    };
-    encode_info->pNext = &hp->vkh264pic_info;
-
-    hp->h264dpb_info = (StdVideoEncodeH264ReferenceInfo) {
-        .flags = (StdVideoEncodeH264ReferenceInfoFlags) {
-            .used_for_long_term_reference = 0,
-            /* Reserved */
-        },
-        .primary_pic_type = hp->h264pic_info.primary_pic_type,
-        .FrameNum = hp->h264pic_info.frame_num,
-        .PicOrderCnt = hp->h264pic_info.PicOrderCnt,
-        .long_term_pic_num = 0,
-        .long_term_frame_idx = 0,
-        .temporal_id = hp->h264pic_info.temporal_id,
-    };
-    hp->vkh264dpb_info = (VkVideoEncodeH264DpbSlotInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_KHR,
-        .pStdReferenceInfo = &hp->h264dpb_info,
-    };
-
-    vp->dpb_slot.pNext = &hp->vkh264dpb_info;
-
-    ref_slot = (VkVideoReferenceSlotInfoKHR *)encode_info->pSetupReferenceSlot;
-    ref_slot->pNext = &hp->vkh264dpb_info;
-
-    setup_refs(avctx, pic, encode_info);
-
-    setup_slices(avctx, pic);
-
-    return 0;
-}
-
-static int init_profile(AVCodecContext *avctx,
-                        VkVideoProfileInfoKHR *profile, void *pnext)
-{
-    VkResult ret;
-    VulkanEncodeH264Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext *ctx = &enc->common;
-    FFVulkanContext *s = &ctx->s;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-    VkVideoEncodeH264CapabilitiesKHR h264_caps = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_KHR,
-    };
-    VkVideoEncodeCapabilitiesKHR enc_caps = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR,
-        .pNext = &h264_caps,
-    };
-    VkVideoCapabilitiesKHR caps = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR,
-        .pNext = &enc_caps,
-    };
-
-    /* In order of preference */
-    int last_supported = AV_PROFILE_UNKNOWN;
-    static const int known_profiles[] = {
-        AV_PROFILE_H264_CONSTRAINED_BASELINE,
-        AV_PROFILE_H264_MAIN,
-        AV_PROFILE_H264_HIGH,
-        AV_PROFILE_H264_HIGH_10,
-    };
-    int nb_profiles = FF_ARRAY_ELEMS(known_profiles);
-
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->frames->sw_format);
-    if (!desc)
-        return AVERROR(EINVAL);
-
-    if (desc->comp[0].depth == 8)
-        nb_profiles = 3;
-
-    enc->profile = (VkVideoEncodeH264ProfileInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_KHR,
-        .pNext = pnext,
-        .stdProfileIdc = ff_vk_h264_profile_to_vk(avctx->profile),
-    };
-    profile->pNext = &enc->profile;
-
-    /* Set level */
-    if (avctx->level == AV_LEVEL_UNKNOWN)
-        avctx->level = enc->common.opts.level;
-
-    /* User has explicitly specified a profile. */
-    if (avctx->profile != AV_PROFILE_UNKNOWN)
-        return 0;
-
-    av_log(avctx, AV_LOG_DEBUG, "Supported profiles:\n");
-    for (int i = 0; i < nb_profiles; i++) {
-        enc->profile.stdProfileIdc = ff_vk_h264_profile_to_vk(known_profiles[i]);
-        ret = vk->GetPhysicalDeviceVideoCapabilitiesKHR(s->hwctx->phys_dev,
-                                                        profile,
-                                                        &caps);
-        if (ret == VK_SUCCESS) {
-            av_log(avctx, AV_LOG_DEBUG, "    %s\n",
-                   avcodec_profile_name(avctx->codec_id, known_profiles[i]));
-            last_supported = known_profiles[i];
-        }
-    }
-
-    if (last_supported == AV_PROFILE_UNKNOWN) {
-        av_log(avctx, AV_LOG_ERROR, "No supported profiles for given format\n");
-        return AVERROR(ENOTSUP);
-    }
-
-    enc->profile.stdProfileIdc = ff_vk_h264_profile_to_vk(last_supported);
-    av_log(avctx, AV_LOG_VERBOSE, "Using profile %s\n",
-           avcodec_profile_name(avctx->codec_id, last_supported));
-    avctx->profile = last_supported;
-
-    return 0;
-}
-
-static int init_enc_options(AVCodecContext *avctx)
-{
-    VulkanEncodeH264Context *enc = avctx->priv_data;
-    FFHWBaseEncodeH264Opts *unit_opts = &enc->unit_opts;
-
-    if (avctx->rc_buffer_size)
-        unit_opts->hrd_buffer_size = avctx->rc_buffer_size;
-    else if (avctx->rc_max_rate > 0)
-        unit_opts->hrd_buffer_size = avctx->rc_max_rate;
-    else
-        unit_opts->hrd_buffer_size = avctx->bit_rate;
-
-    if (avctx->rc_initial_buffer_occupancy) {
-        if (avctx->rc_initial_buffer_occupancy > unit_opts->hrd_buffer_size) {
-            av_log(avctx, AV_LOG_ERROR, "Invalid RC buffer settings: "
-                                        "must have initial buffer size (%d) <= "
-                                        "buffer size (%"PRId64").\n",
-                   avctx->rc_initial_buffer_occupancy, unit_opts->hrd_buffer_size);
-            return AVERROR(EINVAL);
-        }
-        unit_opts->initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
-    } else {
-        unit_opts->initial_buffer_fullness = unit_opts->hrd_buffer_size * 3 / 4;
-    }
-
-    if (enc->common.opts.rc_mode == VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
-        /* HRD info is required for timing */
-        enc->unit_elems &= ~UNIT_SEI_TIMING;
-
-        enc->fixed_qp_p = av_clip(enc->common.explicit_qp,
-                                  enc->caps.minQp, enc->caps.maxQp);
-        if (avctx->i_quant_factor > 0.0)
-            unit_opts->fixed_qp_idr = av_clip((avctx->i_quant_factor * enc->fixed_qp_p +
-                                               avctx->i_quant_offset) + 0.5,
-                                              enc->caps.minQp, enc->caps.maxQp);
-        else
-            unit_opts->fixed_qp_idr = enc->fixed_qp_p;
-
-        if (avctx->b_quant_factor > 0.0)
-            enc->fixed_qp_b = av_clip((avctx->b_quant_factor * enc->fixed_qp_p +
-                                       avctx->b_quant_offset) + 0.5,
-                                      enc->caps.minQp, enc->caps.maxQp);
-        else
-            enc->fixed_qp_b = enc->fixed_qp_p;
-
-        av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
-               "%d / %d / %d for IDR- / P- / B-frames.\n",
-               unit_opts->fixed_qp_idr, enc->fixed_qp_p, enc->fixed_qp_b);
-    } else {
-        unit_opts->fixed_qp_idr = 26;
-        enc->fixed_qp_p = 26;
-        enc->fixed_qp_b = 26;
-    }
-
-    return 0;
-}
-
-static av_cold int init_sequence_headers(AVCodecContext *avctx)
-{
-    int err;
-    VulkanEncodeH264Context *enc = avctx->priv_data;
-
-    FFHWBaseEncodeH264 *units = &enc->units;
-    FFHWBaseEncodeH264Opts *unit_opts = &enc->unit_opts;
-
-    unit_opts->bit_rate  = avctx->bit_rate;
-    unit_opts->mb_width  = FFALIGN(avctx->width,  16) / 16;
-    unit_opts->mb_height = FFALIGN(avctx->height, 16) / 16;
-    unit_opts->flags     = enc->unit_elems & UNIT_SEI_TIMING ? FF_HW_H264_SEI_TIMING : 0;
-
-    /* cabac already set via an option */
-    /* fixed_qp_idr initialized in init_enc_options() */
-    /* hrd_buffer_size initialized in init_enc_options() */
-    /* initial_buffer_fullness initialized in init_enc_options() */
-
-    err = ff_hw_base_encode_init_params_h264(&enc->common.base, avctx,
-                                             units, unit_opts);
-    if (err < 0)
-        return err;
-
-    units->raw_sps.seq_scaling_matrix_present_flag =
-        !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_SCALING_MATRIX_PRESENT_FLAG_SET_BIT_KHR);
-    units->raw_pps.pic_scaling_matrix_present_flag =
-        !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_SCALING_MATRIX_PRESENT_FLAG_SET_BIT_KHR);
-    units->raw_pps.transform_8x8_mode_flag =
-        !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_TRANSFORM_8X8_MODE_FLAG_SET_BIT_KHR);
-
-    return 0;
-}
-
-typedef struct VulkanH264Units {
-    StdVideoH264SequenceParameterSet    vksps;
-    StdVideoH264ScalingLists            vksps_scaling;
-    StdVideoH264HrdParameters           vksps_vui_header;
-    StdVideoH264SequenceParameterSetVui vksps_vui;
-
-    StdVideoH264PictureParameterSet     vkpps;
-    StdVideoH264ScalingLists            vkpps_scaling;
-} VulkanH264Units;
-
-static av_cold int base_unit_to_vk(AVCodecContext *avctx,
-                                   VulkanH264Units *vk_units)
-{
-    VulkanEncodeH264Context *enc = avctx->priv_data;
-
-    FFHWBaseEncodeH264 *units = &enc->units;
-
-    H264RawSPS                          *sps = &units->raw_sps;
-    H264RawHRD                          *hrd = &sps->vui.nal_hrd_parameters;
-    StdVideoH264ScalingLists            *vksps_scaling = &vk_units->vksps_scaling;
-    StdVideoH264HrdParameters           *vksps_vui_header = &vk_units->vksps_vui_header;
-    StdVideoH264SequenceParameterSetVui *vksps_vui = &vk_units->vksps_vui;
-    StdVideoH264SequenceParameterSet    *vksps = &vk_units->vksps;
-
-    H264RawPPS                          *pps = &units->raw_pps;
-    StdVideoH264ScalingLists            *vkpps_scaling = &vk_units->vkpps_scaling;
-    StdVideoH264PictureParameterSet     *vkpps = &vk_units->vkpps;
-
-    *vksps_scaling = (StdVideoH264ScalingLists) {
-        .scaling_list_present_mask = 0x0, // mask
-        .use_default_scaling_matrix_mask = 1,
-    };
-
-    *vksps_vui_header = (StdVideoH264HrdParameters) {
-        .cpb_cnt_minus1 = hrd->cpb_cnt_minus1,
-        .bit_rate_scale = hrd->bit_rate_scale,
-        .cpb_size_scale = hrd->cpb_size_scale,
-        /* Reserved */
-        /* bit_rate/cpb_size/cbr_flag set below */
-        .initial_cpb_removal_delay_length_minus1 = hrd->initial_cpb_removal_delay_length_minus1,
-        .cpb_removal_delay_length_minus1 = hrd->cpb_removal_delay_length_minus1,
-        .dpb_output_delay_length_minus1 = hrd->dpb_output_delay_length_minus1,
-        .time_offset_length = hrd->time_offset_length,
-    };
-
-    for (int i = 0; i < H264_MAX_CPB_CNT; i++) {
-        vksps_vui_header->bit_rate_value_minus1[i] = hrd->bit_rate_value_minus1[i];
-        vksps_vui_header->cpb_size_value_minus1[i] = hrd->cpb_size_value_minus1[i];
-        vksps_vui_header->cbr_flag[i] = hrd->cbr_flag[i];
-    }
-
-    *vksps_vui = (StdVideoH264SequenceParameterSetVui) {
-        .flags = (StdVideoH264SpsVuiFlags) {
-            .aspect_ratio_info_present_flag = sps->vui.aspect_ratio_info_present_flag,
-            .overscan_info_present_flag = sps->vui.overscan_info_present_flag,
-            .overscan_appropriate_flag = sps->vui.overscan_appropriate_flag,
-            .video_signal_type_present_flag = sps->vui.video_signal_type_present_flag,
-            .video_full_range_flag = sps->vui.video_full_range_flag,
-            .color_description_present_flag = sps->vui.colour_description_present_flag,
-            .chroma_loc_info_present_flag = sps->vui.chroma_loc_info_present_flag,
-            .timing_info_present_flag = sps->vui.timing_info_present_flag,
-            .fixed_frame_rate_flag = sps->vui.fixed_frame_rate_flag,
-            .bitstream_restriction_flag = sps->vui.bitstream_restriction_flag,
-            .nal_hrd_parameters_present_flag = sps->vui.nal_hrd_parameters_present_flag,
-            .vcl_hrd_parameters_present_flag = sps->vui.vcl_hrd_parameters_present_flag,
-        },
-        .aspect_ratio_idc = sps->vui.aspect_ratio_idc,
-        .sar_width = sps->vui.sar_width,
-        .sar_height = sps->vui.sar_height,
-        .video_format = sps->vui.video_format,
-        .colour_primaries = sps->vui.colour_primaries,
-        .transfer_characteristics = sps->vui.transfer_characteristics,
-        .matrix_coefficients = sps->vui.matrix_coefficients,
-        .num_units_in_tick = sps->vui.num_units_in_tick,
-        .time_scale = sps->vui.time_scale,
-        .max_num_reorder_frames = sps->vui.max_num_reorder_frames,
-        .max_dec_frame_buffering = sps->vui.max_dec_frame_buffering,
-        .chroma_sample_loc_type_top_field = sps->vui.chroma_sample_loc_type_top_field,
-        .chroma_sample_loc_type_bottom_field = sps->vui.chroma_sample_loc_type_bottom_field,
-        /* Reserved */
-        .pHrdParameters = vksps_vui_header,
-    };
-
-    *vksps = (StdVideoH264SequenceParameterSet) {
-        .flags = (StdVideoH264SpsFlags) {
-            .constraint_set0_flag = sps->constraint_set0_flag,
-            .constraint_set1_flag = sps->constraint_set1_flag,
-            .constraint_set2_flag = sps->constraint_set2_flag,
-            .constraint_set3_flag = sps->constraint_set3_flag,
-            .constraint_set4_flag = sps->constraint_set4_flag,
-            .constraint_set5_flag = sps->constraint_set5_flag,
-            .direct_8x8_inference_flag = sps->direct_8x8_inference_flag,
-            .mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag,
-            .frame_mbs_only_flag = sps->frame_mbs_only_flag,
-            .delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag,
-            .separate_colour_plane_flag = sps->separate_colour_plane_flag,
-            .gaps_in_frame_num_value_allowed_flag = sps->gaps_in_frame_num_allowed_flag,
-            .qpprime_y_zero_transform_bypass_flag = sps->qpprime_y_zero_transform_bypass_flag,
-            .frame_cropping_flag = sps->frame_cropping_flag,
-            .seq_scaling_matrix_present_flag = sps->seq_scaling_matrix_present_flag,
-            .vui_parameters_present_flag = sps->vui_parameters_present_flag,
-        },
-        .profile_idc = ff_vk_h264_profile_to_vk(sps->profile_idc),
-        .level_idc = ff_vk_h264_level_to_vk(sps->level_idc),
-        .chroma_format_idc = sps->chroma_format_idc,
-        .seq_parameter_set_id = sps->seq_parameter_set_id,
-        .bit_depth_luma_minus8 = sps->bit_depth_luma_minus8,
-        .bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8,
-        .log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4,
-        .pic_order_cnt_type = sps->pic_order_cnt_type,
-        .offset_for_non_ref_pic = sps->offset_for_non_ref_pic,
-        .offset_for_top_to_bottom_field = sps->offset_for_top_to_bottom_field,
-        .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4,
-        .num_ref_frames_in_pic_order_cnt_cycle = sps->num_ref_frames_in_pic_order_cnt_cycle,
-        .max_num_ref_frames = sps->max_num_ref_frames,
-        /* Reserved */
-        .pic_width_in_mbs_minus1 = sps->pic_width_in_mbs_minus1,
-        .pic_height_in_map_units_minus1 = sps->pic_height_in_map_units_minus1,
-        .frame_crop_left_offset = sps->frame_crop_left_offset,
-        .frame_crop_right_offset = sps->frame_crop_right_offset,
-        .frame_crop_top_offset = sps->frame_crop_top_offset,
-        .frame_crop_bottom_offset = sps->frame_crop_bottom_offset,
-        /* Reserved */
-        .pOffsetForRefFrame = sps->offset_for_ref_frame,
-        .pScalingLists = vksps_scaling,
-        .pSequenceParameterSetVui = vksps_vui,
-    };
-
-    *vkpps_scaling = (StdVideoH264ScalingLists) {
-        .scaling_list_present_mask = 0x0, // mask
-        .use_default_scaling_matrix_mask = 1,
-    };
-
-    *vkpps = (StdVideoH264PictureParameterSet) {
-        .flags = (StdVideoH264PpsFlags) {
-            .transform_8x8_mode_flag = pps->transform_8x8_mode_flag,
-            .redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag,
-            .constrained_intra_pred_flag = pps->constrained_intra_pred_flag,
-            .deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag,
-            .weighted_pred_flag = pps->weighted_pred_flag,
-            .bottom_field_pic_order_in_frame_present_flag = pps->bottom_field_pic_order_in_frame_present_flag,
-            .entropy_coding_mode_flag = pps->entropy_coding_mode_flag,
-            .pic_scaling_matrix_present_flag = pps->pic_scaling_matrix_present_flag,
-        },
-        .seq_parameter_set_id = pps->seq_parameter_set_id,
-        .pic_parameter_set_id = pps->pic_parameter_set_id,
-        .num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active_minus1,
-        .num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active_minus1,
-        .weighted_bipred_idc = pps->weighted_bipred_idc,
-        .pic_init_qp_minus26 = pps->pic_init_qp_minus26,
-        .pic_init_qs_minus26 = pps->pic_init_qs_minus26,
-        .chroma_qp_index_offset = pps->chroma_qp_index_offset,
-        .second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset,
-        .pScalingLists = vkpps_scaling,
-    };
-
-    return 0;
-}
-
-static int create_session_params(AVCodecContext *avctx)
-{
-    int err;
-    VulkanEncodeH264Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext *ctx = &enc->common;
-    FFVulkanContext *s = &ctx->s;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-
-    VulkanH264Units vk_units = { 0 };
-
-    VkVideoEncodeH264SessionParametersAddInfoKHR h264_params_info;
-    VkVideoEncodeH264SessionParametersCreateInfoKHR h264_params;
-
-    /* Convert it to Vulkan */
-    err = base_unit_to_vk(avctx, &vk_units);
-    if (err < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to convert SPS/PPS units to Vulkan: %s\n",
-               av_err2str(err));
-        return err;
-    }
-
-    /* Destroy the session params */
-    if (ctx->session_params)
-        vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
-                                             ctx->session_params,
-                                             s->hwctx->alloc);
-
-    h264_params_info = (VkVideoEncodeH264SessionParametersAddInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR,
-        .pStdSPSs = &vk_units.vksps,
-        .stdSPSCount = 1,
-        .pStdPPSs = &vk_units.vkpps,
-        .stdPPSCount = 1,
-    };
-    h264_params = (VkVideoEncodeH264SessionParametersCreateInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR,
-        .maxStdSPSCount = 1,
-        .maxStdPPSCount = 1,
-        .pParametersAddInfo = &h264_params_info,
-    };
-
-    return ff_vulkan_encode_create_session_params(avctx, ctx, &h264_params);
-}
-
-static int parse_feedback_units(AVCodecContext *avctx,
-                                const uint8_t *data, size_t size,
-                                int sps_override, int pps_override)
-{
-    int err;
-    VulkanEncodeH264Context *enc = avctx->priv_data;
-
-    CodedBitstreamContext *cbs;
-    CodedBitstreamFragment au = { 0 };
-
-    err = ff_cbs_init(&cbs, AV_CODEC_ID_H264, avctx);
-    if (err < 0)
-        return err;
-
-    err = ff_cbs_read(cbs, &au, NULL, data, size);
-    if (err < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to parse feedback units, bad drivers: %s\n",
-               av_err2str(err));
-        goto fail;
-    }
-
-    /* If PPS has an override, just copy it entirely. */
-    if (pps_override) {
-        for (int i = 0; i < au.nb_units; i++) {
-            if (au.units[i].type == H264_NAL_PPS) {
-                H264RawPPS *pps = au.units[i].content;
-                memcpy(&enc->units.raw_pps, pps, sizeof(*pps));
-                break;
-            }
-        }
-    }
-
-    err = 0;
-fail:
-    ff_cbs_fragment_free(&au);
-    ff_cbs_close(&cbs);
-
-    return err;
-}
-
-static int init_base_units(AVCodecContext *avctx)
-{
-    int err;
-    VkResult ret;
-    VulkanEncodeH264Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext *ctx = &enc->common;
-    FFVulkanContext *s = &ctx->s;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-
-    VkVideoEncodeH264SessionParametersGetInfoKHR h264_params_info;
-    VkVideoEncodeSessionParametersGetInfoKHR params_info;
-    VkVideoEncodeH264SessionParametersFeedbackInfoKHR h264_params_feedback;
-    VkVideoEncodeSessionParametersFeedbackInfoKHR params_feedback;
-
-    void *data = NULL;
-    size_t data_size = 0;
-
-    /* Generate SPS/PPS unit info */
-    err = init_sequence_headers(avctx);
-    if (err < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to initialize SPS/PPS units: %s\n",
-               av_err2str(err));
-        return err;
-    }
-
-    /* Create session parameters from them */
-    err = create_session_params(avctx);
-    if (err < 0)
-        return err;
-
-    h264_params_info = (VkVideoEncodeH264SessionParametersGetInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_GET_INFO_KHR,
-        .writeStdSPS = 1,
-        .writeStdPPS = 1,
-        .stdSPSId = enc->units.raw_sps.seq_parameter_set_id,
-        .stdPPSId = enc->units.raw_pps.pic_parameter_set_id,
-    };
-    params_info = (VkVideoEncodeSessionParametersGetInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_GET_INFO_KHR,
-        .pNext = &h264_params_info,
-        .videoSessionParameters = ctx->session_params,
-    };
-
-    h264_params_feedback = (VkVideoEncodeH264SessionParametersFeedbackInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_FEEDBACK_INFO_KHR,
-    };
-    params_feedback = (VkVideoEncodeSessionParametersFeedbackInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_FEEDBACK_INFO_KHR,
-        .pNext = &h264_params_feedback,
-    };
-
-    ret = vk->GetEncodedVideoSessionParametersKHR(s->hwctx->act_dev, &params_info,
-                                                  &params_feedback,
-                                                  &data_size, data);
-    if (ret == VK_INCOMPLETE ||
-        (ret == VK_SUCCESS) && (data_size > 0)) {
-        data = av_mallocz(data_size);
-        if (!data)
-            return AVERROR(ENOMEM);
-    } else {
-        av_log(avctx, AV_LOG_ERROR, "Unable to get feedback for H.264 units = %"SIZE_SPECIFIER"\n", data_size);
-        return err;
-    }
-
-    ret = vk->GetEncodedVideoSessionParametersKHR(s->hwctx->act_dev, &params_info,
-                                                  &params_feedback,
-                                                  &data_size, data);
-    if (ret != VK_SUCCESS) {
-        av_log(avctx, AV_LOG_ERROR, "Error writing feedback units\n");
-        return err;
-    }
-
-    av_log(avctx, AV_LOG_VERBOSE, "Feedback units written, overrides: %i (SPS: %i PPS: %i)\n",
-           params_feedback.hasOverrides,
-           h264_params_feedback.hasStdSPSOverrides,
-           h264_params_feedback.hasStdPPSOverrides);
-
-    params_feedback.hasOverrides = 1;
-    h264_params_feedback.hasStdPPSOverrides = 1;
-
-    /* No need to sync any overrides */
-    if (!params_feedback.hasOverrides)
-        return 0;
-
-    /* Parse back tne units and override */
-    err = parse_feedback_units(avctx, data, data_size,
-                               h264_params_feedback.hasStdSPSOverrides,
-                               h264_params_feedback.hasStdPPSOverrides);
-    if (err < 0)
-        return err;
-
-    /* Create final session parameters */
-    err = create_session_params(avctx);
-    if (err < 0)
-        return err;
-
-    return 0;
-}
-
-static int vulkan_encode_h264_add_nal(AVCodecContext *avctx,
-                                      CodedBitstreamFragment *au,
-                                      void *nal_unit)
-{
-    H264RawNALUnitHeader *header = nal_unit;
-
-    int err = ff_cbs_insert_unit_content(au, -1,
-                                         header->nal_unit_type, nal_unit, NULL);
-    if (err < 0)
-        av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: "
-               "type = %d.\n", header->nal_unit_type);
-
-    return err;
-}
-
-static int write_access_unit(AVCodecContext *avctx,
-                             uint8_t *data, size_t *data_len,
-                             CodedBitstreamFragment *au)
-{
-    VulkanEncodeH264Context *enc = avctx->priv_data;
-
-    int err = ff_cbs_write_fragment_data(enc->cbs, au);
-    if (err < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n");
-        return err;
-    }
-
-    if (*data_len < au->data_size) {
-        av_log(avctx, AV_LOG_ERROR, "Access unit too large: %zu < %zu.\n",
-               *data_len, au->data_size);
-        return AVERROR(ENOSPC);
-    }
-
-    memcpy(data, au->data, au->data_size);
-    *data_len = au->data_size;
-
-    return 0;
-}
-
-static int write_sequence_headers(AVCodecContext *avctx,
-                                  FFHWBaseEncodePicture *base_pic,
-                                  uint8_t *data, size_t *data_len)
-{
-    int err;
-    VulkanEncodeH264Context *enc = avctx->priv_data;
-    VulkanEncodeH264Picture  *hp = base_pic ? base_pic->codec_priv : NULL;
-    CodedBitstreamFragment   *au = &enc->current_access_unit;
-
-    if (hp && hp->units_needed & UNIT_AUD) {
-        err = vulkan_encode_h264_add_nal(avctx, au, &enc->raw_aud);
-        if (err < 0)
-            goto fail;
-    }
-
-    err = vulkan_encode_h264_add_nal(avctx, au, &enc->units.raw_sps);
-    if (err < 0)
-        goto fail;
-
-    err = vulkan_encode_h264_add_nal(avctx, au, &enc->units.raw_pps);
-    if (err < 0)
-        goto fail;
-
-    err = write_access_unit(avctx, data, data_len, au);
-fail:
-    ff_cbs_fragment_reset(au);
-    return err;
-}
-
-static int write_extra_headers(AVCodecContext *avctx,
-                               FFHWBaseEncodePicture *base_pic,
-                               uint8_t *data, size_t *data_len)
-{
-    int err;
-    VulkanEncodeH264Context *enc = avctx->priv_data;
-    VulkanEncodeH264Picture  *hp = base_pic->codec_priv;
-    CodedBitstreamFragment   *au = &enc->current_access_unit;
-
-    if (hp->units_needed & UNIT_AUD) {
-        err = vulkan_encode_h264_add_nal(avctx, au, &enc->raw_aud);
-        if (err < 0)
-            goto fail;
-    }
-
-    if (hp->units_needed & UNIT_SEI_IDENTIFIER) {
-        err = ff_cbs_sei_add_message(enc->cbs, au, 1,
-                                     SEI_TYPE_USER_DATA_UNREGISTERED,
-                                     &enc->sei_identifier, NULL);
-        if (err < 0)
-            goto fail;
-    }
-
-    if (hp->units_needed & UNIT_SEI_TIMING) {
-        if (base_pic->type == FF_HW_PICTURE_TYPE_IDR) {
-            err = ff_cbs_sei_add_message(enc->cbs, au, 1,
-                                         SEI_TYPE_BUFFERING_PERIOD,
-                                         &enc->units.sei_buffering_period, NULL);
-            if (err < 0)
-                goto fail;
-        }
-        err = ff_cbs_sei_add_message(enc->cbs, au, 1,
-                                     SEI_TYPE_PIC_TIMING,
-                                     &enc->sei_pic_timing, NULL);
-        if (err < 0)
-            goto fail;
-    }
-
-    if (hp->units_needed & UNIT_SEI_RECOVERY) {
-        err = ff_cbs_sei_add_message(enc->cbs, au, 1,
-                                     SEI_TYPE_RECOVERY_POINT,
-                                     &enc->sei_recovery_point, NULL);
-        if (err < 0)
-            goto fail;
-    }
-
-    if (hp->units_needed & UNIT_SEI_A53_CC) {
-        err = ff_cbs_sei_add_message(enc->cbs, au, 1,
-                                     SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35,
-                                     &enc->sei_a53cc, NULL);
-        if (err < 0)
-            goto fail;
-    }
-
-    if (hp->units_needed) {
-        err = write_access_unit(avctx, data, data_len, au);
-        if (err < 0)
-            goto fail;
-    } else {
-        err = 0;
-        *data_len = 0;
-    }
-
-fail:
-    ff_cbs_fragment_reset(au);
-    return err;
-}
-
-static int write_filler(AVCodecContext *avctx, uint32_t filler,
-                        uint8_t *data, size_t *data_len)
-{
-    int err;
-    VulkanEncodeH264Context *enc = avctx->priv_data;
-    CodedBitstreamFragment   *au = &enc->current_access_unit;
-
-    H264RawFiller raw_filler = {
-        .nal_unit_header = {
-            .nal_unit_type = H264_NAL_FILLER_DATA,
-        },
-        .filler_size = filler,
-    };
-
-    err = vulkan_encode_h264_add_nal(avctx, au, &raw_filler);
-    if (err < 0)
-        goto fail;
-
-    err = write_access_unit(avctx, data, data_len, au);
-fail:
-    ff_cbs_fragment_reset(au);
-    return err;
-}
-
-static const FFVulkanCodec enc_cb = {
-    .flags = FF_HW_FLAG_B_PICTURES |
-             FF_HW_FLAG_B_PICTURE_REFERENCES |
-             FF_HW_FLAG_NON_IDR_KEY_PICTURES,
-    .picture_priv_data_size = sizeof(VulkanEncodeH264Picture),
-    .filler_header_size = 6,
-    .init_profile = init_profile,
-    .init_pic_rc = init_pic_rc,
-    .init_pic_params = init_pic_params,
-    .write_sequence_headers = write_sequence_headers,
-    .write_extra_headers = write_extra_headers,
-    .write_filler = write_filler,
-};
-
-static av_cold int vulkan_encode_h264_init(AVCodecContext *avctx)
-{
-    int err, ref_l0, ref_l1;
-    VulkanEncodeH264Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext *ctx = &enc->common;
-    FFVulkanContext *s = &ctx->s;
-    FFHWBaseEncodeContext *base_ctx = &ctx->base;
-    int flags;
-
-    if (avctx->profile == AV_PROFILE_UNKNOWN)
-        avctx->profile = enc->common.opts.profile;
-
-    enc->caps = (VkVideoEncodeH264CapabilitiesKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_KHR,
-    };
-
-    enc->quality_props = (VkVideoEncodeH264QualityLevelPropertiesKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_QUALITY_LEVEL_PROPERTIES_KHR,
-    };
-
-    err = ff_vulkan_encode_init(avctx, &enc->common,
-                                &ff_vk_enc_h264_desc, &enc_cb,
-                                &enc->caps, &enc->quality_props);
-    if (err < 0)
-        return err;
-
-    av_log(avctx, AV_LOG_VERBOSE, "H264 encoder capabilities:\n");
-    av_log(avctx, AV_LOG_VERBOSE, "    Standard capability flags:\n");
-    av_log(avctx, AV_LOG_VERBOSE, "        separate_color_plane: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_SEPARATE_COLOR_PLANE_FLAG_SET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        qprime_y_zero_transform_bypass: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_QPPRIME_Y_ZERO_TRANSFORM_BYPASS_FLAG_SET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        scaling_lists: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_SCALING_MATRIX_PRESENT_FLAG_SET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        chroma_qp_index_offset: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_CHROMA_QP_INDEX_OFFSET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        second_chroma_qp_index_offset: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_SECOND_CHROMA_QP_INDEX_OFFSET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        pic_init_qp: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_PIC_INIT_QP_MINUS26_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        weighted:%s%s%s\n",
-           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_WEIGHTED_PRED_FLAG_SET_BIT_KHR ?
-               " pred" : "",
-           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_WEIGHTED_BIPRED_IDC_EXPLICIT_BIT_KHR ?
-               " bipred_explicit" : "",
-           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_WEIGHTED_BIPRED_IDC_IMPLICIT_BIT_KHR ?
-               " bipred_implicit" : "");
-    av_log(avctx, AV_LOG_VERBOSE, "        8x8_transforms: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_TRANSFORM_8X8_MODE_FLAG_SET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        disable_direct_spatial_mv_pred: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_DIRECT_SPATIAL_MV_PRED_FLAG_UNSET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        coder:%s%s\n",
-           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_ENTROPY_CODING_MODE_FLAG_UNSET_BIT_KHR ?
-               " cabac" : "",
-           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_ENTROPY_CODING_MODE_FLAG_SET_BIT_KHR ?
-               " cavlc" : "");
-    av_log(avctx, AV_LOG_VERBOSE, "        direct_8x8_inference: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_DIRECT_8X8_INFERENCE_FLAG_UNSET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        constrained_intra_pred: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_CONSTRAINED_INTRA_PRED_FLAG_SET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        deblock:%s%s%s\n",
-           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_DISABLED_BIT_KHR ?
-               " filter_disabling" : "",
-           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_ENABLED_BIT_KHR ?
-               " filter_enabling" : "",
-           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_PARTIAL_BIT_KHR ?
-               " filter_partial" : "");
-
-    av_log(avctx, AV_LOG_VERBOSE, "    Capability flags:\n");
-    av_log(avctx, AV_LOG_VERBOSE, "        hdr_compliance: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        pred_weight_table_generated: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        row_unaligned_slice: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        different_slice_type: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        b_frame_in_l0_list: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        b_frame_in_l1_list: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        per_pict_type_min_max_qp: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        per_slice_constant_qp: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PER_SLICE_CONSTANT_QP_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        generate_prefix_nalu: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_KHR));
-
-    av_log(avctx, AV_LOG_VERBOSE, "    Capabilities:\n");
-    av_log(avctx, AV_LOG_VERBOSE, "        maxLevelIdc: %i\n",
-           enc->caps.maxLevelIdc);
-    av_log(avctx, AV_LOG_VERBOSE, "        maxSliceCount: %i\n",
-           enc->caps.maxSliceCount);
-    av_log(avctx, AV_LOG_VERBOSE, "        max(P/B)PictureL0ReferenceCount: %i P's; %i B's\n",
-           enc->caps.maxPPictureL0ReferenceCount,
-           enc->caps.maxBPictureL0ReferenceCount);
-    av_log(avctx, AV_LOG_VERBOSE, "        maxL1ReferenceCount: %i\n",
-           enc->caps.maxL1ReferenceCount);
-    av_log(avctx, AV_LOG_VERBOSE, "        maxTemporalLayerCount: %i\n",
-           enc->caps.maxTemporalLayerCount);
-    av_log(avctx, AV_LOG_VERBOSE, "        expectDyadicTemporalLayerPattern: %i\n",
-           enc->caps.expectDyadicTemporalLayerPattern);
-    av_log(avctx, AV_LOG_VERBOSE, "        min/max Qp: [%i, %i]\n",
-           enc->caps.minQp, enc->caps.maxQp);
-    av_log(avctx, AV_LOG_VERBOSE, "        prefersGopRemainingFrames: %i\n",
-           enc->caps.prefersGopRemainingFrames);
-    av_log(avctx, AV_LOG_VERBOSE, "        requiresGopRemainingFrames: %i\n",
-           enc->caps.requiresGopRemainingFrames);
-
-    err = init_enc_options(avctx);
-    if (err < 0)
-        return err;
-
-    flags = ctx->codec->flags;
-    if (!enc->caps.maxPPictureL0ReferenceCount &&
-        !enc->caps.maxBPictureL0ReferenceCount &&
-        !enc->caps.maxL1ReferenceCount) {
-        /* Intra-only */
-        flags |= FF_HW_FLAG_INTRA_ONLY;
-        ref_l0 = ref_l1 = 0;
-    } else if (!enc->caps.maxPPictureL0ReferenceCount) {
-        /* No P-frames? How. */
-        base_ctx->p_to_gpb = 1;
-        ref_l0 = enc->caps.maxBPictureL0ReferenceCount;
-        ref_l1 = enc->caps.maxL1ReferenceCount;
-    } else if (!enc->caps.maxBPictureL0ReferenceCount &&
-               !enc->caps.maxL1ReferenceCount) {
-        /* No B-frames */
-        flags &= ~(FF_HW_FLAG_B_PICTURES | FF_HW_FLAG_B_PICTURE_REFERENCES);
-        ref_l0 = enc->caps.maxPPictureL0ReferenceCount;
-        ref_l1 = 0;
-    } else {
-        /* P and B frames */
-        ref_l0 = FFMIN(enc->caps.maxPPictureL0ReferenceCount,
-                       enc->caps.maxBPictureL0ReferenceCount);
-        ref_l1 = enc->caps.maxL1ReferenceCount;
-    }
-
-    err = ff_hw_base_init_gop_structure(base_ctx, avctx, ref_l0, ref_l1,
-                                        flags, 0);
-    if (err < 0)
-        return err;
-
-    base_ctx->output_delay = base_ctx->b_per_p;
-    base_ctx->decode_delay = base_ctx->max_b_depth;
-
-    /* Prepare SEI */
-    if (enc->unit_elems & UNIT_SEI_IDENTIFIER) {
-        int len;
-
-        memcpy(enc->sei_identifier.uuid_iso_iec_11578,
-               vulkan_encode_h264_sei_identifier_uuid,
-               sizeof(enc->sei_identifier.uuid_iso_iec_11578));
-
-        len = snprintf(NULL, 0,
-                       "%s / Vulkan video %i.%i.%i / %s %i.%i.%i / %s",
-                       LIBAVCODEC_IDENT,
-                       CODEC_VER(ff_vk_enc_h264_desc.ext_props.specVersion),
-                       s->driver_props.driverName,
-                       CODEC_VER(s->props.properties.driverVersion),
-                       s->props.properties.deviceName);
-
-        if (len >= 0) {
-            enc->sei_identifier_string = av_malloc(len + 1);
-            if (!enc->sei_identifier_string)
-                return AVERROR(ENOMEM);
-
-            len = snprintf(enc->sei_identifier_string, len + 1,
-                           "%s / Vulkan video %i.%i.%i / %s %i.%i.%i / %s",
-                           LIBAVCODEC_IDENT,
-                           CODEC_VER(ff_vk_enc_h264_desc.ext_props.specVersion),
-                           s->driver_props.driverName,
-                           CODEC_VER(s->props.properties.driverVersion),
-                           s->props.properties.deviceName);
-
-            enc->sei_identifier.data        = enc->sei_identifier_string;
-            enc->sei_identifier.data_length = len + 1;
-        }
-    }
-
-    /* Init CBS */
-    err = ff_cbs_init(&enc->cbs, AV_CODEC_ID_H264, avctx);
-    if (err < 0)
-        return err;
-
-    /* Create units and session parameters */
-    err = init_base_units(avctx);
-    if (err < 0)
-        return err;
-
-    /* Write out extradata */
-    err = ff_vulkan_write_global_header(avctx, &enc->common);
-    if (err < 0)
-        return err;
-
-    return 0;
-}
-
-static av_cold int vulkan_encode_h264_close(AVCodecContext *avctx)
-{
-    VulkanEncodeH264Context *enc = avctx->priv_data;
-    ff_vulkan_encode_uninit(&enc->common);
-    return 0;
-}
-
-#define OFFSET(x) offsetof(VulkanEncodeH264Context, x)
-#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
-static const AVOption vulkan_encode_h264_options[] = {
-    HW_BASE_ENCODE_COMMON_OPTIONS,
-    VULKAN_ENCODE_COMMON_OPTIONS,
-
-    { "profile", "Set profile (profile_idc and constraint_set*_flag)",
-      OFFSET(common.opts.profile), AV_OPT_TYPE_INT,
-      { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, 0xffff, FLAGS, .unit = "profile" },
-
-#define PROFILE(name, value)  name, NULL, 0, AV_OPT_TYPE_CONST, \
-      { .i64 = value }, 0, 0, FLAGS, .unit = "profile"
-    { PROFILE("constrained_baseline", AV_PROFILE_H264_CONSTRAINED_BASELINE) },
-    { PROFILE("main",                 AV_PROFILE_H264_MAIN) },
-    { PROFILE("high",                 AV_PROFILE_H264_HIGH) },
-    { PROFILE("high444p",             AV_PROFILE_H264_HIGH_10) },
-#undef PROFILE
-
-    { "level", "Set level (level_idc)",
-      OFFSET(common.opts.level), AV_OPT_TYPE_INT,
-      { .i64 = AV_LEVEL_UNKNOWN }, AV_LEVEL_UNKNOWN, 0xff, FLAGS, .unit = "level" },
-
-#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
-      { .i64 = value }, 0, 0, FLAGS, .unit = "level"
-    { LEVEL("1",   10) },
-    { LEVEL("1.1", 11) },
-    { LEVEL("1.2", 12) },
-    { LEVEL("1.3", 13) },
-    { LEVEL("2",   20) },
-    { LEVEL("2.1", 21) },
-    { LEVEL("2.2", 22) },
-    { LEVEL("3",   30) },
-    { LEVEL("3.1", 31) },
-    { LEVEL("3.2", 32) },
-    { LEVEL("4",   40) },
-    { LEVEL("4.1", 41) },
-    { LEVEL("4.2", 42) },
-    { LEVEL("5",   50) },
-    { LEVEL("5.1", 51) },
-    { LEVEL("5.2", 52) },
-    { LEVEL("6",   60) },
-    { LEVEL("6.1", 61) },
-    { LEVEL("6.2", 62) },
-#undef LEVEL
-
-    { "coder", "Entropy coder type", OFFSET(unit_opts.cabac), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, FLAGS, "coder" },
-        { "cabac", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, FLAGS, "coder" },
-        { "vlc",   NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS, "coder" },
-
-    { "units", "Set units to include", OFFSET(unit_elems), AV_OPT_TYPE_FLAGS, { .i64 = UNIT_AUD | UNIT_SEI_IDENTIFIER | UNIT_SEI_RECOVERY | UNIT_SEI_TIMING | UNIT_SEI_A53_CC }, 0, INT_MAX, FLAGS, "units" },
-        { "aud",        "Include AUD units", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_AUD }, INT_MIN, INT_MAX, FLAGS, "units" },
-        { "identifier", "Include encoder version identifier", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_SEI_IDENTIFIER }, INT_MIN, INT_MAX, FLAGS, "units" },
-        { "timing",     "Include timing parameters (buffering_period and pic_timing)", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_SEI_TIMING }, INT_MIN, INT_MAX, FLAGS, "units" },
-        { "recovery",   "Include recovery points where appropriate", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_SEI_RECOVERY }, INT_MIN, INT_MAX, FLAGS, "units" },
-        { "a53_cc",     "Include A/53 caption data", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_SEI_A53_CC }, INT_MIN, INT_MAX, FLAGS, "units" },
-
-    { NULL },
-};
-
-static const FFCodecDefault vulkan_encode_h264_defaults[] = {
-    { "b",              "0"   },
-    { "bf",             "2"   },
-    { "g",              "300" },
-    { "i_qfactor",      "1"   },
-    { "i_qoffset",      "0"   },
-    { "b_qfactor",      "1"   },
-    { "b_qoffset",      "0"   },
-    { "qmin",           "-1"  },
-    { "qmax",           "-1"  },
-    { "refs",           "0"   },
-    { NULL },
-};
-
-static const AVClass vulkan_encode_h264_class = {
-    .class_name = "h264_vulkan",
-    .item_name  = av_default_item_name,
-    .option     = vulkan_encode_h264_options,
-    .version    = LIBAVUTIL_VERSION_INT,
-};
-
-const FFCodec ff_h264_vulkan_encoder = {
-    .p.name         = "h264_vulkan",
-    CODEC_LONG_NAME("H.264/AVC (Vulkan)"),
-    .p.type         = AVMEDIA_TYPE_VIDEO,
-    .p.id           = AV_CODEC_ID_H264,
-    .priv_data_size = sizeof(VulkanEncodeH264Context),
-    .init           = &vulkan_encode_h264_init,
-    FF_CODEC_RECEIVE_PACKET_CB(&ff_vulkan_encode_receive_packet),
-    .close          = &vulkan_encode_h264_close,
-    .p.priv_class   = &vulkan_encode_h264_class,
-    .p.capabilities = AV_CODEC_CAP_DELAY |
-                      AV_CODEC_CAP_HARDWARE |
-                      AV_CODEC_CAP_DR1 |
-                      AV_CODEC_CAP_ENCODER_FLUSH |
-                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
-    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
-    .defaults       = vulkan_encode_h264_defaults,
-    CODEC_PIXFMTS(AV_PIX_FMT_VULKAN),
-    .hw_configs     = ff_vulkan_encode_hw_configs,
-    .p.wrapper_name = "vulkan",
-};
-- 
2.49.1


From c12426040081c4d92223f7b4fc61209bf1fb37e4 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:33:54 +0000
Subject: [PATCH 076/118] Changing vulkan file directory

---
 libavcodec/vulkan/vulkan_encode_h264.c | 1668 ++++++++++++++++++++++++
 1 file changed, 1668 insertions(+)
 create mode 100644 libavcodec/vulkan/vulkan_encode_h264.c

diff --git a/libavcodec/vulkan/vulkan_encode_h264.c b/libavcodec/vulkan/vulkan_encode_h264.c
new file mode 100644
index 0000000000..33f319cbcc
--- /dev/null
+++ b/libavcodec/vulkan/vulkan_encode_h264.c
@@ -0,0 +1,1668 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/internal.h"
+#include "libavutil/opt.h"
+#include "libavutil/mem.h"
+
+#include "libavcodec/cbs.h"
+#include "libavcodec/cbs_h264.h"
+#include "libavcodec/atsc_a53.h"
+
+#include "libavcodec/h264_levels.h"
+#include "libavcodec/h2645data.h"
+#include "libavcodec/codec_internal.h"
+#include "libavcodec/version.h"
+#include "libavcodec/hw_base_encode_h264.h"
+
+#include "vulkan_encode.h"
+
+enum UnitElems {
+    UNIT_AUD            = 1 << 0,
+    UNIT_SEI_TIMING     = 1 << 1,
+    UNIT_SEI_IDENTIFIER = 1 << 2,
+    UNIT_SEI_RECOVERY   = 1 << 3,
+    UNIT_SEI_A53_CC     = 1 << 4,
+};
+
+const FFVulkanEncodeDescriptor ff_vk_enc_h264_desc = {
+    .codec_id         = AV_CODEC_ID_H264,
+    .encode_extension = FF_VK_EXT_VIDEO_ENCODE_H264,
+    .encode_op        = VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR,
+    .ext_props = {
+        .extensionName = VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_EXTENSION_NAME,
+        .specVersion   = VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION,
+    },
+};
+
+/* Random (version 4) ISO 11578 UUID. */
+static const uint8_t vulkan_encode_h264_sei_identifier_uuid[16] = {
+    0x03, 0xfd, 0xf2, 0x0a, 0x5d, 0x4c, 0x05, 0x48,
+    0x20, 0x98, 0xca, 0x6b, 0x0c, 0x95, 0x30, 0x1c,
+};
+
+typedef struct VulkanEncodeH264Picture {
+    int frame_num;
+    int64_t last_idr_frame;
+    uint16_t idr_pic_id;
+    int primary_pic_type;
+    int slice_type;
+    int pic_order_cnt;
+
+    enum UnitElems units_needed;
+
+    VkVideoEncodeH264RateControlInfoKHR vkrc_info;
+    VkVideoEncodeH264RateControlLayerInfoKHR vkrc_layer_info;
+    VkVideoEncodeH264GopRemainingFrameInfoKHR vkrc_remaining;
+
+    StdVideoEncodeH264WeightTable slice_wt;
+    StdVideoEncodeH264SliceHeader slice_hdr;
+    VkVideoEncodeH264NaluSliceInfoKHR vkslice;
+
+    StdVideoEncodeH264PictureInfo   h264pic_info;
+    VkVideoEncodeH264PictureInfoKHR vkh264pic_info;
+
+    StdVideoEncodeH264ReferenceInfo h264dpb_info;
+    VkVideoEncodeH264DpbSlotInfoKHR vkh264dpb_info;
+
+    StdVideoEncodeH264RefListModEntry mods[MAX_REFERENCE_LIST_NUM][H264_MAX_RPLM_COUNT];
+    StdVideoEncodeH264RefPicMarkingEntry mmco[H264_MAX_RPLM_COUNT];
+    StdVideoEncodeH264ReferenceListsInfo ref_list_info;
+} VulkanEncodeH264Picture;
+
+typedef struct VulkanEncodeH264Context {
+    FFVulkanEncodeContext common;
+
+    FFHWBaseEncodeH264 units;
+    FFHWBaseEncodeH264Opts unit_opts;
+
+    enum UnitElems unit_elems;
+
+    uint8_t fixed_qp_p;
+    uint8_t fixed_qp_b;
+
+    VkVideoEncodeH264ProfileInfoKHR profile;
+
+    VkVideoEncodeH264CapabilitiesKHR caps;
+    VkVideoEncodeH264QualityLevelPropertiesKHR quality_props;
+
+    CodedBitstreamContext *cbs;
+    CodedBitstreamFragment current_access_unit;
+
+    H264RawAUD                  raw_aud;
+
+    SEIRawUserDataUnregistered  sei_identifier;
+    H264RawSEIPicTiming         sei_pic_timing;
+    H264RawSEIRecoveryPoint     sei_recovery_point;
+    SEIRawUserDataRegistered    sei_a53cc;
+    void                       *sei_a53cc_data;
+    char                       *sei_identifier_string;
+} VulkanEncodeH264Context;
+
+static int init_pic_rc(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
+                       VkVideoEncodeRateControlInfoKHR *rc_info,
+                       VkVideoEncodeRateControlLayerInfoKHR *rc_layer)
+{
+    VulkanEncodeH264Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext   *ctx = &enc->common;
+    VulkanEncodeH264Picture  *hp = pic->codec_priv;
+
+    hp->vkrc_info = (VkVideoEncodeH264RateControlInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_KHR,
+        .flags = VK_VIDEO_ENCODE_H264_RATE_CONTROL_REFERENCE_PATTERN_FLAT_BIT_KHR |
+                 VK_VIDEO_ENCODE_H264_RATE_CONTROL_REGULAR_GOP_BIT_KHR,
+        .idrPeriod = ctx->base.gop_size,
+        .gopFrameCount = ctx->base.gop_size,
+        .consecutiveBFrameCount = FFMAX(ctx->base.b_per_p - 1, 0),
+        .temporalLayerCount = 0,
+    };
+    rc_info->pNext = &hp->vkrc_info;
+
+    if (rc_info->rateControlMode > VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
+        rc_info->virtualBufferSizeInMs = (enc->unit_opts.hrd_buffer_size * 1000LL) / avctx->bit_rate;
+        rc_info->initialVirtualBufferSizeInMs = (enc->unit_opts.initial_buffer_fullness * 1000LL) / avctx->bit_rate;
+
+        hp->vkrc_layer_info = (VkVideoEncodeH264RateControlLayerInfoKHR) {
+            .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_KHR,
+
+            .useMinQp  = avctx->qmin > 0,
+            .minQp.qpI = avctx->qmin > 0 ? avctx->qmin : 0,
+            .minQp.qpP = avctx->qmin > 0 ? avctx->qmin : 0,
+            .minQp.qpB = avctx->qmin > 0 ? avctx->qmin : 0,
+
+            .useMaxQp  = avctx->qmax > 0,
+            .maxQp.qpI = avctx->qmax > 0 ? avctx->qmax : 0,
+            .maxQp.qpP = avctx->qmax > 0 ? avctx->qmax : 0,
+            .maxQp.qpB = avctx->qmax > 0 ? avctx->qmax : 0,
+
+            .useMaxFrameSize = 0,
+        };
+        rc_layer->pNext = &hp->vkrc_layer_info;
+        hp->vkrc_info.temporalLayerCount = 1;
+    }
+
+    return 0;
+}
+
+static int vk_enc_h264_update_pic_info(AVCodecContext *avctx,
+                                       FFHWBaseEncodePicture *pic)
+{
+    VulkanEncodeH264Context   *enc = avctx->priv_data;
+    FFVulkanEncodeContext     *ctx = &enc->common;
+    VulkanEncodeH264Picture    *hp = pic->codec_priv;
+    FFHWBaseEncodePicture    *prev = pic->prev;
+    VulkanEncodeH264Picture *hprev = prev ? prev->codec_priv : NULL;
+
+    if (pic->type == FF_HW_PICTURE_TYPE_IDR) {
+        av_assert0(pic->display_order == pic->encode_order);
+
+        hp->frame_num      = 0;
+        hp->last_idr_frame = pic->display_order;
+        hp->idr_pic_id     = hprev ? hprev->idr_pic_id + 1 : 0;
+
+        hp->primary_pic_type = 0;
+        hp->slice_type       = STD_VIDEO_H264_SLICE_TYPE_I;
+    } else {
+        av_assert0(prev);
+
+        hp->frame_num = hprev->frame_num + prev->is_reference;
+
+        hp->last_idr_frame = hprev->last_idr_frame;
+        hp->idr_pic_id     = hprev->idr_pic_id;
+
+        if (pic->type == FF_HW_PICTURE_TYPE_I) {
+            hp->slice_type       = STD_VIDEO_H264_SLICE_TYPE_I;
+            hp->primary_pic_type = 0;
+        } else if (pic->type == FF_HW_PICTURE_TYPE_P) {
+            hp->slice_type       = STD_VIDEO_H264_SLICE_TYPE_P;
+            hp->primary_pic_type = 1;
+        } else {
+            hp->slice_type       = STD_VIDEO_H264_SLICE_TYPE_B;
+            hp->primary_pic_type = 2;
+        }
+    }
+
+    hp->pic_order_cnt = pic->display_order - hp->last_idr_frame;
+    if (enc->units.raw_sps.pic_order_cnt_type == 2)
+        hp->pic_order_cnt *= 2;
+
+    hp->units_needed = 0;
+
+    if (enc->unit_elems & UNIT_SEI_IDENTIFIER && pic->encode_order == 0)
+        hp->units_needed |= UNIT_SEI_IDENTIFIER;
+
+    if (enc->unit_elems & UNIT_SEI_TIMING) {
+        enc->sei_pic_timing = (H264RawSEIPicTiming) {
+            .cpb_removal_delay = 2 * (pic->encode_order - hp->last_idr_frame),
+            .dpb_output_delay  = 2 * (pic->display_order - pic->encode_order + ctx->base.max_b_depth),
+        };
+
+        hp->units_needed |= UNIT_SEI_TIMING;
+    }
+
+    if (enc->unit_elems & UNIT_SEI_RECOVERY && pic->type == FF_HW_PICTURE_TYPE_I) {
+        enc->sei_recovery_point = (H264RawSEIRecoveryPoint) {
+            .recovery_frame_cnt = 0,
+            .exact_match_flag   = 1,
+            .broken_link_flag   = ctx->base.b_per_p > 0,
+        };
+
+        hp->units_needed |= UNIT_SEI_RECOVERY;
+    }
+
+    if (enc->unit_elems & UNIT_SEI_A53_CC) {
+        int err;
+        size_t sei_a53cc_len;
+        av_freep(&enc->sei_a53cc_data);
+        err = ff_alloc_a53_sei(pic->input_image, 0, &enc->sei_a53cc_data, &sei_a53cc_len);
+        if (err < 0)
+            return err;
+        if (enc->sei_a53cc_data != NULL) {
+            enc->sei_a53cc.itu_t_t35_country_code = 181;
+            enc->sei_a53cc.data = (uint8_t *)enc->sei_a53cc_data + 1;
+            enc->sei_a53cc.data_length = sei_a53cc_len - 1;
+
+            hp->units_needed |= UNIT_SEI_A53_CC;
+        }
+    }
+
+    return 0;
+}
+
+static void setup_slices(AVCodecContext *avctx,
+                         FFHWBaseEncodePicture *pic)
+{
+    VulkanEncodeH264Context *enc = avctx->priv_data;
+    VulkanEncodeH264Picture *hp = pic->codec_priv;
+
+    hp->slice_wt = (StdVideoEncodeH264WeightTable) {
+        .flags = (StdVideoEncodeH264WeightTableFlags) {
+            .luma_weight_l0_flag = 0,
+            .chroma_weight_l0_flag = 0,
+            .luma_weight_l1_flag = 0,
+            .chroma_weight_l1_flag = 0,
+        },
+        .luma_log2_weight_denom = 0,
+        .chroma_log2_weight_denom = 0,
+        .luma_weight_l0 = { 0 },
+        .luma_offset_l0 = { 0 },
+        .chroma_weight_l0 = { { 0 } },
+        .chroma_offset_l0 = { { 0 } },
+        .luma_weight_l1 = { 0 },
+        .luma_offset_l1 = { 0 },
+        .chroma_weight_l1 = { { 0 } },
+        .chroma_offset_l1 = { { 0 } },
+    };
+
+    hp->slice_hdr = (StdVideoEncodeH264SliceHeader) {
+        .flags = (StdVideoEncodeH264SliceHeaderFlags) {
+            .direct_spatial_mv_pred_flag = 1,
+            /* The vk_samples code does this */
+            .num_ref_idx_active_override_flag =
+                ((enc->units.raw_pps.num_ref_idx_l0_default_active_minus1) &&
+                 (pic->type == FF_HW_PICTURE_TYPE_B)) ? 1 : 0,
+        },
+        .first_mb_in_slice = 1,
+        .slice_type = hp->slice_type,
+        .slice_alpha_c0_offset_div2 = 0,
+        .slice_beta_offset_div2 = 0,
+        .slice_qp_delta = 0, /* Filled in below */
+        /* Reserved */
+        .cabac_init_idc = 0,
+        .disable_deblocking_filter_idc = 0,
+        .pWeightTable = NULL, // &hp->slice_wt,
+    };
+
+    hp->vkslice = (VkVideoEncodeH264NaluSliceInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_INFO_KHR,
+        .pNext = NULL,
+        .constantQp = pic->type == FF_HW_PICTURE_TYPE_B ? enc->fixed_qp_b :
+                      pic->type == FF_HW_PICTURE_TYPE_P ? enc->fixed_qp_p :
+                                                          enc->unit_opts.fixed_qp_idr,
+        .pStdSliceHeader = &hp->slice_hdr,
+    };
+
+    if (enc->common.opts.rc_mode != VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR)
+        hp->vkslice.constantQp = 0;
+
+    hp->slice_hdr.slice_qp_delta = hp->vkslice.constantQp -
+                                   (enc->units.raw_pps.pic_init_qp_minus26 + 26);
+
+    hp->vkh264pic_info.pNaluSliceEntries = &hp->vkslice;
+    hp->vkh264pic_info.naluSliceEntryCount = 1;
+}
+
+static void vk_enc_h264_default_ref_pic_list(AVCodecContext *avctx,
+                                             FFHWBaseEncodePicture *pic,
+                                             FFHWBaseEncodePicture **rpl0,
+                                             FFHWBaseEncodePicture **rpl1,
+                                             int *rpl_size)
+{
+    FFHWBaseEncodePicture *prev;
+    VulkanEncodeH264Picture *hp, *hn, *hc;
+    int i, j, n = 0;
+
+    prev = pic->prev;
+    av_assert0(prev);
+    hp = pic->codec_priv;
+
+    for (i = 0; i < pic->prev->nb_dpb_pics; i++) {
+        hn = prev->dpb[i]->codec_priv;
+        av_assert0(hn->frame_num < hp->frame_num);
+
+        if (pic->type == FF_HW_PICTURE_TYPE_P) {
+            for (j = n; j > 0; j--) {
+                hc = rpl0[j - 1]->codec_priv;
+                av_assert0(hc->frame_num != hn->frame_num);
+                if (hc->frame_num > hn->frame_num)
+                    break;
+                rpl0[j] = rpl0[j - 1];
+            }
+            rpl0[j] = prev->dpb[i];
+
+        } else if (pic->type == FF_HW_PICTURE_TYPE_B) {
+            for (j = n; j > 0; j--) {
+                hc = rpl0[j - 1]->codec_priv;
+                av_assert0(hc->pic_order_cnt != hp->pic_order_cnt);
+                if (hc->pic_order_cnt < hp->pic_order_cnt) {
+                    if (hn->pic_order_cnt > hp->pic_order_cnt ||
+                        hn->pic_order_cnt < hc->pic_order_cnt)
+                        break;
+                } else {
+                    if (hn->pic_order_cnt > hc->pic_order_cnt)
+                        break;
+                }
+                rpl0[j] = rpl0[j - 1];
+            }
+            rpl0[j] = prev->dpb[i];
+
+            for (j = n; j > 0; j--) {
+                hc = rpl1[j - 1]->codec_priv;
+                av_assert0(hc->pic_order_cnt != hp->pic_order_cnt);
+                if (hc->pic_order_cnt > hp->pic_order_cnt) {
+                    if (hn->pic_order_cnt < hp->pic_order_cnt ||
+                        hn->pic_order_cnt > hc->pic_order_cnt)
+                        break;
+                } else {
+                    if (hn->pic_order_cnt < hc->pic_order_cnt)
+                        break;
+                }
+                rpl1[j] = rpl1[j - 1];
+            }
+            rpl1[j] = prev->dpb[i];
+        }
+
+        ++n;
+    }
+
+    if (pic->type == FF_HW_PICTURE_TYPE_B) {
+        for (i = 0; i < n; i++) {
+            if (rpl0[i] != rpl1[i])
+                break;
+        }
+        if (i == n)
+            FFSWAP(FFHWBaseEncodePicture *, rpl1[0], rpl1[1]);
+    }
+
+    if (pic->type == FF_HW_PICTURE_TYPE_P ||
+        pic->type == FF_HW_PICTURE_TYPE_B) {
+        av_log(avctx, AV_LOG_DEBUG, "Default RefPicList0 for fn=%d/poc=%d:",
+               hp->frame_num, hp->pic_order_cnt);
+        for (i = 0; i < n; i++) {
+            hn = rpl0[i]->codec_priv;
+            av_log(avctx, AV_LOG_DEBUG, "  fn=%d/poc=%d",
+                   hn->frame_num, hn->pic_order_cnt);
+        }
+        av_log(avctx, AV_LOG_DEBUG, "\n");
+    }
+    if (pic->type == FF_HW_PICTURE_TYPE_B) {
+        av_log(avctx, AV_LOG_DEBUG, "Default RefPicList1 for fn=%d/poc=%d:",
+               hp->frame_num, hp->pic_order_cnt);
+        for (i = 0; i < n; i++) {
+            hn = rpl1[i]->codec_priv;
+            av_log(avctx, AV_LOG_DEBUG, "  fn=%d/poc=%d",
+                   hn->frame_num, hn->pic_order_cnt);
+        }
+        av_log(avctx, AV_LOG_DEBUG, "\n");
+    }
+
+    *rpl_size = n;
+}
+
+static void setup_refs(AVCodecContext *avctx,
+                       FFHWBaseEncodePicture *pic,
+                       VkVideoEncodeInfoKHR *encode_info)
+{
+    int n, i, j;
+    VulkanEncodeH264Context *enc = avctx->priv_data;
+    VulkanEncodeH264Picture *hp = pic->codec_priv;
+    FFHWBaseEncodePicture *prev = pic->prev;
+    FFHWBaseEncodePicture *def_l0[MAX_DPB_SIZE], *def_l1[MAX_DPB_SIZE];
+    VulkanEncodeH264Picture *href;
+
+    hp->ref_list_info = (StdVideoEncodeH264ReferenceListsInfo) {
+        .flags = (StdVideoEncodeH264ReferenceListsInfoFlags) {
+            .ref_pic_list_modification_flag_l0 = 0,
+            .ref_pic_list_modification_flag_l1 = 0,
+            /* Reserved */
+        },
+        /* May be overridden during setup_slices() */
+        .num_ref_idx_l0_active_minus1 = pic->nb_refs[0] - 1,
+        .num_ref_idx_l1_active_minus1 = pic->nb_refs[1] - 1,
+        /* .RefPicList0 is set in vk_enc_h264_default_ref_pic_list() */
+        /* .RefPicList1 is set in vk_enc_h264_default_ref_pic_list() */
+        /* Reserved */
+        .pRefList0ModOperations = NULL, /* All set below */
+        .refList0ModOpCount = 0,
+        .pRefList1ModOperations = NULL,
+        .refList1ModOpCount = 0,
+        .pRefPicMarkingOperations = NULL,
+        .refPicMarkingOpCount = 0,
+    };
+
+    for (i = 0; i < STD_VIDEO_H264_MAX_NUM_LIST_REF; i++)
+        hp->ref_list_info.RefPicList0[i] = hp->ref_list_info.RefPicList1[i] = -1;
+
+    /* Note: really not sure */
+    for (int i = 0; i < pic->nb_refs[0]; i++) {
+        VkVideoReferenceSlotInfoKHR *slot_info;
+        slot_info = (VkVideoReferenceSlotInfoKHR *)&encode_info->pReferenceSlots[i];
+        hp->ref_list_info.RefPicList0[i] = slot_info->slotIndex;
+    }
+
+    /* Note: really not sure */
+    for (int i = 0; i < pic->nb_refs[1]; i++) {
+        VkVideoReferenceSlotInfoKHR *slot_info;
+        slot_info = (VkVideoReferenceSlotInfoKHR *)&encode_info->pReferenceSlots[pic->nb_refs[0] + i];
+        hp->ref_list_info.RefPicList1[i] = slot_info->slotIndex;
+    }
+
+    hp->h264pic_info.pRefLists = &hp->ref_list_info;
+
+    if (pic->is_reference && pic->type != FF_HW_PICTURE_TYPE_IDR) {
+        FFHWBaseEncodePicture *discard_list[MAX_DPB_SIZE];
+        int discard = 0, keep = 0;
+
+        // Discard everything which is in the DPB of the previous frame but
+        // not in the DPB of this one.
+        for (i = 0; i < prev->nb_dpb_pics; i++) {
+            for (j = 0; j < pic->nb_dpb_pics; j++) {
+                if (prev->dpb[i] == pic->dpb[j])
+                    break;
+            }
+            if (j == pic->nb_dpb_pics) {
+                discard_list[discard] = prev->dpb[i];
+                ++discard;
+            } else {
+                ++keep;
+            }
+        }
+        av_assert0(keep <= enc->units.dpb_frames);
+
+        if (discard == 0) {
+            hp->h264pic_info.flags.adaptive_ref_pic_marking_mode_flag = 0;
+        } else {
+            hp->h264pic_info.flags.adaptive_ref_pic_marking_mode_flag = 1;
+            for (i = 0; i < discard; i++) {
+                VulkanEncodeH264Picture *old = discard_list[i]->codec_priv;
+                av_assert0(old->frame_num < hp->frame_num);
+                hp->mmco[i] = (StdVideoEncodeH264RefPicMarkingEntry) {
+                    .memory_management_control_operation = 1,
+                    .difference_of_pic_nums_minus1 = hp->frame_num - old->frame_num - 1,
+                };
+            }
+            hp->mmco[i] = (StdVideoEncodeH264RefPicMarkingEntry) {
+                .memory_management_control_operation = 0,
+            };
+            hp->ref_list_info.pRefPicMarkingOperations = hp->mmco;
+            hp->ref_list_info.refPicMarkingOpCount = i + 1;
+        }
+    }
+
+    if (pic->type == FF_HW_PICTURE_TYPE_I || pic->type == FF_HW_PICTURE_TYPE_IDR)
+        return;
+
+    // If the intended references are not the first entries of RefPicListN
+    // by default, use ref-pic-list-modification to move them there.
+    vk_enc_h264_default_ref_pic_list(avctx, pic,
+                                     def_l0, def_l1, &n);
+
+    if (pic->type == FF_HW_PICTURE_TYPE_P) {
+        int need_rplm = 0;
+        for (i = 0; i < pic->nb_refs[0]; i++) {
+            av_assert0(pic->refs[0][i]);
+            if (pic->refs[0][i] != (FFHWBaseEncodePicture *)def_l0[i])
+                need_rplm = 1;
+        }
+
+        hp->ref_list_info.flags.ref_pic_list_modification_flag_l0 = need_rplm;
+        if (need_rplm) {
+            int pic_num = hp->frame_num;
+            for (i = 0; i < pic->nb_refs[0]; i++) {
+                href = pic->refs[0][i]->codec_priv;
+                av_assert0(href->frame_num != pic_num);
+                if (href->frame_num < pic_num) {
+                    hp->mods[0][i] = (StdVideoEncodeH264RefListModEntry) {
+                        .modification_of_pic_nums_idc = 0,
+                        .abs_diff_pic_num_minus1 = pic_num - href->frame_num - 1,
+                    };
+                } else {
+                    hp->mods[0][i] = (StdVideoEncodeH264RefListModEntry) {
+                        .modification_of_pic_nums_idc = 1,
+                        .abs_diff_pic_num_minus1 = href->frame_num - pic_num - 1,
+                    };
+                }
+                pic_num = href->frame_num;
+            }
+            hp->ref_list_info.pRefList0ModOperations = hp->mods[0];
+            hp->ref_list_info.refList0ModOpCount = i - 1;
+        }
+    } else {
+        int need_rplm_l0 = 0, need_rplm_l1 = 0;
+        int n0 = 0, n1 = 0;
+        for (i = 0; i < pic->nb_refs[0]; i++) {
+            av_assert0(pic->refs[0][i]);
+            href = pic->refs[0][i]->codec_priv;
+            av_assert0(href->pic_order_cnt < hp->pic_order_cnt);
+            if (pic->refs[0][i] != (FFHWBaseEncodePicture *)def_l0[n0])
+                need_rplm_l0 = 1;
+            ++n0;
+        }
+
+        for (int i = 0; i < pic->nb_refs[1]; i++) {
+            av_assert0(pic->refs[1][i]);
+            href = pic->refs[1][i]->codec_priv;
+            av_assert0(href->pic_order_cnt > hp->pic_order_cnt);
+            if (pic->refs[1][i] != (FFHWBaseEncodePicture *)def_l1[n1])
+                need_rplm_l1 = 1;
+            ++n1;
+        }
+
+        hp->ref_list_info.flags.ref_pic_list_modification_flag_l0 = need_rplm_l0;
+        if (need_rplm_l0) {
+            int pic_num = hp->frame_num;
+            for (i = j = 0; i < pic->nb_refs[0]; i++) {
+                href = pic->refs[0][i]->codec_priv;
+                av_assert0(href->frame_num != pic_num);
+                if (href->frame_num < pic_num) {
+                    hp->mods[0][j] = (StdVideoEncodeH264RefListModEntry) {
+                        .modification_of_pic_nums_idc = 0,
+                        .abs_diff_pic_num_minus1 = pic_num - href->frame_num - 1,
+                    };
+                } else {
+                    hp->mods[0][j] = (StdVideoEncodeH264RefListModEntry) {
+                        .modification_of_pic_nums_idc = 1,
+                        .abs_diff_pic_num_minus1 = href->frame_num - pic_num - 1,
+                    };
+                }
+                pic_num = href->frame_num;
+                ++j;
+            }
+            hp->ref_list_info.pRefList0ModOperations = hp->mods[0];
+            hp->ref_list_info.refList0ModOpCount = j - 1;
+        }
+
+        hp->ref_list_info.flags.ref_pic_list_modification_flag_l1 = need_rplm_l1;
+        if (need_rplm_l1) {
+            int pic_num = hp->frame_num;
+            for (i = j = 0; i < pic->nb_refs[1]; i++) {
+                href = pic->refs[1][i]->codec_priv;
+                av_assert0(href->frame_num != pic_num);
+                if (href->frame_num < pic_num) {
+                    hp->mods[1][j] = (StdVideoEncodeH264RefListModEntry) {
+                        .modification_of_pic_nums_idc = 0,
+                        .abs_diff_pic_num_minus1 = pic_num - href->frame_num - 1,
+                    };
+                } else {
+                    hp->mods[1][j] = (StdVideoEncodeH264RefListModEntry) {
+                        .modification_of_pic_nums_idc = 1,
+                        .abs_diff_pic_num_minus1 = href->frame_num - pic_num - 1,
+                    };
+                }
+                pic_num = href->frame_num;
+                ++j;
+            }
+            hp->ref_list_info.pRefList1ModOperations = hp->mods[1];
+            hp->ref_list_info.refList1ModOpCount = j - 1;
+        }
+    }
+}
+
+static int init_pic_params(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
+                           VkVideoEncodeInfoKHR *encode_info)
+{
+    int err;
+    FFVulkanEncodePicture *vp = pic->priv;
+    VulkanEncodeH264Picture *hp = pic->codec_priv;
+    VkVideoReferenceSlotInfoKHR *ref_slot;
+
+    err = vk_enc_h264_update_pic_info(avctx, pic);
+    if (err < 0)
+        return err;
+
+    hp->vkh264pic_info = (VkVideoEncodeH264PictureInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PICTURE_INFO_KHR,
+        .pNext = NULL,
+        .pNaluSliceEntries = NULL, // Filled in during setup_slices()
+        .naluSliceEntryCount = 0, // Filled in during setup_slices()
+        .pStdPictureInfo = &hp->h264pic_info,
+    };
+
+    hp->h264pic_info = (StdVideoEncodeH264PictureInfo) {
+        .flags = (StdVideoEncodeH264PictureInfoFlags) {
+            .IdrPicFlag = pic->type == FF_HW_PICTURE_TYPE_IDR,
+            .is_reference = pic->is_reference,
+            .no_output_of_prior_pics_flag = 0,
+            .long_term_reference_flag = 0,
+            .adaptive_ref_pic_marking_mode_flag = 0, // Filled in during setup_refs()
+            /* Reserved */
+        },
+        .seq_parameter_set_id = 0,
+        .pic_parameter_set_id = 0,
+        .idr_pic_id = hp->idr_pic_id,
+        .primary_pic_type = pic->type == FF_HW_PICTURE_TYPE_P ? STD_VIDEO_H264_PICTURE_TYPE_P :
+                            pic->type == FF_HW_PICTURE_TYPE_B ? STD_VIDEO_H264_PICTURE_TYPE_B :
+                            pic->type == FF_HW_PICTURE_TYPE_I ? STD_VIDEO_H264_PICTURE_TYPE_I :
+                                                                STD_VIDEO_H264_PICTURE_TYPE_IDR,
+        .frame_num = hp->frame_num,
+        .PicOrderCnt = hp->pic_order_cnt,
+        .temporal_id = 0, /* ? */
+        /* Reserved */
+        .pRefLists = NULL, // Filled in during setup_refs
+    };
+    encode_info->pNext = &hp->vkh264pic_info;
+
+    hp->h264dpb_info = (StdVideoEncodeH264ReferenceInfo) {
+        .flags = (StdVideoEncodeH264ReferenceInfoFlags) {
+            .used_for_long_term_reference = 0,
+            /* Reserved */
+        },
+        .primary_pic_type = hp->h264pic_info.primary_pic_type,
+        .FrameNum = hp->h264pic_info.frame_num,
+        .PicOrderCnt = hp->h264pic_info.PicOrderCnt,
+        .long_term_pic_num = 0,
+        .long_term_frame_idx = 0,
+        .temporal_id = hp->h264pic_info.temporal_id,
+    };
+    hp->vkh264dpb_info = (VkVideoEncodeH264DpbSlotInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_KHR,
+        .pStdReferenceInfo = &hp->h264dpb_info,
+    };
+
+    vp->dpb_slot.pNext = &hp->vkh264dpb_info;
+
+    ref_slot = (VkVideoReferenceSlotInfoKHR *)encode_info->pSetupReferenceSlot;
+    ref_slot->pNext = &hp->vkh264dpb_info;
+
+    setup_refs(avctx, pic, encode_info);
+
+    setup_slices(avctx, pic);
+
+    return 0;
+}
+
+static int init_profile(AVCodecContext *avctx,
+                        VkVideoProfileInfoKHR *profile, void *pnext)
+{
+    VkResult ret;
+    VulkanEncodeH264Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext *ctx = &enc->common;
+    FFVulkanContext *s = &ctx->s;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+    VkVideoEncodeH264CapabilitiesKHR h264_caps = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_KHR,
+    };
+    VkVideoEncodeCapabilitiesKHR enc_caps = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR,
+        .pNext = &h264_caps,
+    };
+    VkVideoCapabilitiesKHR caps = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR,
+        .pNext = &enc_caps,
+    };
+
+    /* In order of preference */
+    int last_supported = AV_PROFILE_UNKNOWN;
+    static const int known_profiles[] = {
+        AV_PROFILE_H264_CONSTRAINED_BASELINE,
+        AV_PROFILE_H264_MAIN,
+        AV_PROFILE_H264_HIGH,
+        AV_PROFILE_H264_HIGH_10,
+    };
+    int nb_profiles = FF_ARRAY_ELEMS(known_profiles);
+
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->frames->sw_format);
+    if (!desc)
+        return AVERROR(EINVAL);
+
+    if (desc->comp[0].depth == 8)
+        nb_profiles = 3;
+
+    enc->profile = (VkVideoEncodeH264ProfileInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_KHR,
+        .pNext = pnext,
+        .stdProfileIdc = ff_vk_h264_profile_to_vk(avctx->profile),
+    };
+    profile->pNext = &enc->profile;
+
+    /* Set level */
+    if (avctx->level == AV_LEVEL_UNKNOWN)
+        avctx->level = enc->common.opts.level;
+
+    /* User has explicitly specified a profile. */
+    if (avctx->profile != AV_PROFILE_UNKNOWN)
+        return 0;
+
+    av_log(avctx, AV_LOG_DEBUG, "Supported profiles:\n");
+    for (int i = 0; i < nb_profiles; i++) {
+        enc->profile.stdProfileIdc = ff_vk_h264_profile_to_vk(known_profiles[i]);
+        ret = vk->GetPhysicalDeviceVideoCapabilitiesKHR(s->hwctx->phys_dev,
+                                                        profile,
+                                                        &caps);
+        if (ret == VK_SUCCESS) {
+            av_log(avctx, AV_LOG_DEBUG, "    %s\n",
+                   avcodec_profile_name(avctx->codec_id, known_profiles[i]));
+            last_supported = known_profiles[i];
+        }
+    }
+
+    if (last_supported == AV_PROFILE_UNKNOWN) {
+        av_log(avctx, AV_LOG_ERROR, "No supported profiles for given format\n");
+        return AVERROR(ENOTSUP);
+    }
+
+    enc->profile.stdProfileIdc = ff_vk_h264_profile_to_vk(last_supported);
+    av_log(avctx, AV_LOG_VERBOSE, "Using profile %s\n",
+           avcodec_profile_name(avctx->codec_id, last_supported));
+    avctx->profile = last_supported;
+
+    return 0;
+}
+
+static int init_enc_options(AVCodecContext *avctx)
+{
+    VulkanEncodeH264Context *enc = avctx->priv_data;
+    FFHWBaseEncodeH264Opts *unit_opts = &enc->unit_opts;
+
+    if (avctx->rc_buffer_size)
+        unit_opts->hrd_buffer_size = avctx->rc_buffer_size;
+    else if (avctx->rc_max_rate > 0)
+        unit_opts->hrd_buffer_size = avctx->rc_max_rate;
+    else
+        unit_opts->hrd_buffer_size = avctx->bit_rate;
+
+    if (avctx->rc_initial_buffer_occupancy) {
+        if (avctx->rc_initial_buffer_occupancy > unit_opts->hrd_buffer_size) {
+            av_log(avctx, AV_LOG_ERROR, "Invalid RC buffer settings: "
+                                        "must have initial buffer size (%d) <= "
+                                        "buffer size (%"PRId64").\n",
+                   avctx->rc_initial_buffer_occupancy, unit_opts->hrd_buffer_size);
+            return AVERROR(EINVAL);
+        }
+        unit_opts->initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
+    } else {
+        unit_opts->initial_buffer_fullness = unit_opts->hrd_buffer_size * 3 / 4;
+    }
+
+    if (enc->common.opts.rc_mode == VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
+        /* HRD info is required for timing */
+        enc->unit_elems &= ~UNIT_SEI_TIMING;
+
+        enc->fixed_qp_p = av_clip(enc->common.explicit_qp,
+                                  enc->caps.minQp, enc->caps.maxQp);
+        if (avctx->i_quant_factor > 0.0)
+            unit_opts->fixed_qp_idr = av_clip((avctx->i_quant_factor * enc->fixed_qp_p +
+                                               avctx->i_quant_offset) + 0.5,
+                                              enc->caps.minQp, enc->caps.maxQp);
+        else
+            unit_opts->fixed_qp_idr = enc->fixed_qp_p;
+
+        if (avctx->b_quant_factor > 0.0)
+            enc->fixed_qp_b = av_clip((avctx->b_quant_factor * enc->fixed_qp_p +
+                                       avctx->b_quant_offset) + 0.5,
+                                      enc->caps.minQp, enc->caps.maxQp);
+        else
+            enc->fixed_qp_b = enc->fixed_qp_p;
+
+        av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
+               "%d / %d / %d for IDR- / P- / B-frames.\n",
+               unit_opts->fixed_qp_idr, enc->fixed_qp_p, enc->fixed_qp_b);
+    } else {
+        unit_opts->fixed_qp_idr = 26;
+        enc->fixed_qp_p = 26;
+        enc->fixed_qp_b = 26;
+    }
+
+    return 0;
+}
+
+static av_cold int init_sequence_headers(AVCodecContext *avctx)
+{
+    int err;
+    VulkanEncodeH264Context *enc = avctx->priv_data;
+
+    FFHWBaseEncodeH264 *units = &enc->units;
+    FFHWBaseEncodeH264Opts *unit_opts = &enc->unit_opts;
+
+    unit_opts->bit_rate  = avctx->bit_rate;
+    unit_opts->mb_width  = FFALIGN(avctx->width,  16) / 16;
+    unit_opts->mb_height = FFALIGN(avctx->height, 16) / 16;
+    unit_opts->flags     = enc->unit_elems & UNIT_SEI_TIMING ? FF_HW_H264_SEI_TIMING : 0;
+
+    /* cabac already set via an option */
+    /* fixed_qp_idr initialized in init_enc_options() */
+    /* hrd_buffer_size initialized in init_enc_options() */
+    /* initial_buffer_fullness initialized in init_enc_options() */
+
+    err = ff_hw_base_encode_init_params_h264(&enc->common.base, avctx,
+                                             units, unit_opts);
+    if (err < 0)
+        return err;
+
+    units->raw_sps.seq_scaling_matrix_present_flag =
+        !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_SCALING_MATRIX_PRESENT_FLAG_SET_BIT_KHR);
+    units->raw_pps.pic_scaling_matrix_present_flag =
+        !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_SCALING_MATRIX_PRESENT_FLAG_SET_BIT_KHR);
+    units->raw_pps.transform_8x8_mode_flag =
+        !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_TRANSFORM_8X8_MODE_FLAG_SET_BIT_KHR);
+
+    return 0;
+}
+
+typedef struct VulkanH264Units {
+    StdVideoH264SequenceParameterSet    vksps;
+    StdVideoH264ScalingLists            vksps_scaling;
+    StdVideoH264HrdParameters           vksps_vui_header;
+    StdVideoH264SequenceParameterSetVui vksps_vui;
+
+    StdVideoH264PictureParameterSet     vkpps;
+    StdVideoH264ScalingLists            vkpps_scaling;
+} VulkanH264Units;
+
+static av_cold int base_unit_to_vk(AVCodecContext *avctx,
+                                   VulkanH264Units *vk_units)
+{
+    VulkanEncodeH264Context *enc = avctx->priv_data;
+
+    FFHWBaseEncodeH264 *units = &enc->units;
+
+    H264RawSPS                          *sps = &units->raw_sps;
+    H264RawHRD                          *hrd = &sps->vui.nal_hrd_parameters;
+    StdVideoH264ScalingLists            *vksps_scaling = &vk_units->vksps_scaling;
+    StdVideoH264HrdParameters           *vksps_vui_header = &vk_units->vksps_vui_header;
+    StdVideoH264SequenceParameterSetVui *vksps_vui = &vk_units->vksps_vui;
+    StdVideoH264SequenceParameterSet    *vksps = &vk_units->vksps;
+
+    H264RawPPS                          *pps = &units->raw_pps;
+    StdVideoH264ScalingLists            *vkpps_scaling = &vk_units->vkpps_scaling;
+    StdVideoH264PictureParameterSet     *vkpps = &vk_units->vkpps;
+
+    *vksps_scaling = (StdVideoH264ScalingLists) {
+        .scaling_list_present_mask = 0x0, // mask
+        .use_default_scaling_matrix_mask = 1,
+    };
+
+    *vksps_vui_header = (StdVideoH264HrdParameters) {
+        .cpb_cnt_minus1 = hrd->cpb_cnt_minus1,
+        .bit_rate_scale = hrd->bit_rate_scale,
+        .cpb_size_scale = hrd->cpb_size_scale,
+        /* Reserved */
+        /* bit_rate/cpb_size/cbr_flag set below */
+        .initial_cpb_removal_delay_length_minus1 = hrd->initial_cpb_removal_delay_length_minus1,
+        .cpb_removal_delay_length_minus1 = hrd->cpb_removal_delay_length_minus1,
+        .dpb_output_delay_length_minus1 = hrd->dpb_output_delay_length_minus1,
+        .time_offset_length = hrd->time_offset_length,
+    };
+
+    for (int i = 0; i < H264_MAX_CPB_CNT; i++) {
+        vksps_vui_header->bit_rate_value_minus1[i] = hrd->bit_rate_value_minus1[i];
+        vksps_vui_header->cpb_size_value_minus1[i] = hrd->cpb_size_value_minus1[i];
+        vksps_vui_header->cbr_flag[i] = hrd->cbr_flag[i];
+    }
+
+    *vksps_vui = (StdVideoH264SequenceParameterSetVui) {
+        .flags = (StdVideoH264SpsVuiFlags) {
+            .aspect_ratio_info_present_flag = sps->vui.aspect_ratio_info_present_flag,
+            .overscan_info_present_flag = sps->vui.overscan_info_present_flag,
+            .overscan_appropriate_flag = sps->vui.overscan_appropriate_flag,
+            .video_signal_type_present_flag = sps->vui.video_signal_type_present_flag,
+            .video_full_range_flag = sps->vui.video_full_range_flag,
+            .color_description_present_flag = sps->vui.colour_description_present_flag,
+            .chroma_loc_info_present_flag = sps->vui.chroma_loc_info_present_flag,
+            .timing_info_present_flag = sps->vui.timing_info_present_flag,
+            .fixed_frame_rate_flag = sps->vui.fixed_frame_rate_flag,
+            .bitstream_restriction_flag = sps->vui.bitstream_restriction_flag,
+            .nal_hrd_parameters_present_flag = sps->vui.nal_hrd_parameters_present_flag,
+            .vcl_hrd_parameters_present_flag = sps->vui.vcl_hrd_parameters_present_flag,
+        },
+        .aspect_ratio_idc = sps->vui.aspect_ratio_idc,
+        .sar_width = sps->vui.sar_width,
+        .sar_height = sps->vui.sar_height,
+        .video_format = sps->vui.video_format,
+        .colour_primaries = sps->vui.colour_primaries,
+        .transfer_characteristics = sps->vui.transfer_characteristics,
+        .matrix_coefficients = sps->vui.matrix_coefficients,
+        .num_units_in_tick = sps->vui.num_units_in_tick,
+        .time_scale = sps->vui.time_scale,
+        .max_num_reorder_frames = sps->vui.max_num_reorder_frames,
+        .max_dec_frame_buffering = sps->vui.max_dec_frame_buffering,
+        .chroma_sample_loc_type_top_field = sps->vui.chroma_sample_loc_type_top_field,
+        .chroma_sample_loc_type_bottom_field = sps->vui.chroma_sample_loc_type_bottom_field,
+        /* Reserved */
+        .pHrdParameters = vksps_vui_header,
+    };
+
+    *vksps = (StdVideoH264SequenceParameterSet) {
+        .flags = (StdVideoH264SpsFlags) {
+            .constraint_set0_flag = sps->constraint_set0_flag,
+            .constraint_set1_flag = sps->constraint_set1_flag,
+            .constraint_set2_flag = sps->constraint_set2_flag,
+            .constraint_set3_flag = sps->constraint_set3_flag,
+            .constraint_set4_flag = sps->constraint_set4_flag,
+            .constraint_set5_flag = sps->constraint_set5_flag,
+            .direct_8x8_inference_flag = sps->direct_8x8_inference_flag,
+            .mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag,
+            .frame_mbs_only_flag = sps->frame_mbs_only_flag,
+            .delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag,
+            .separate_colour_plane_flag = sps->separate_colour_plane_flag,
+            .gaps_in_frame_num_value_allowed_flag = sps->gaps_in_frame_num_allowed_flag,
+            .qpprime_y_zero_transform_bypass_flag = sps->qpprime_y_zero_transform_bypass_flag,
+            .frame_cropping_flag = sps->frame_cropping_flag,
+            .seq_scaling_matrix_present_flag = sps->seq_scaling_matrix_present_flag,
+            .vui_parameters_present_flag = sps->vui_parameters_present_flag,
+        },
+        .profile_idc = ff_vk_h264_profile_to_vk(sps->profile_idc),
+        .level_idc = ff_vk_h264_level_to_vk(sps->level_idc),
+        .chroma_format_idc = sps->chroma_format_idc,
+        .seq_parameter_set_id = sps->seq_parameter_set_id,
+        .bit_depth_luma_minus8 = sps->bit_depth_luma_minus8,
+        .bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8,
+        .log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4,
+        .pic_order_cnt_type = sps->pic_order_cnt_type,
+        .offset_for_non_ref_pic = sps->offset_for_non_ref_pic,
+        .offset_for_top_to_bottom_field = sps->offset_for_top_to_bottom_field,
+        .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4,
+        .num_ref_frames_in_pic_order_cnt_cycle = sps->num_ref_frames_in_pic_order_cnt_cycle,
+        .max_num_ref_frames = sps->max_num_ref_frames,
+        /* Reserved */
+        .pic_width_in_mbs_minus1 = sps->pic_width_in_mbs_minus1,
+        .pic_height_in_map_units_minus1 = sps->pic_height_in_map_units_minus1,
+        .frame_crop_left_offset = sps->frame_crop_left_offset,
+        .frame_crop_right_offset = sps->frame_crop_right_offset,
+        .frame_crop_top_offset = sps->frame_crop_top_offset,
+        .frame_crop_bottom_offset = sps->frame_crop_bottom_offset,
+        /* Reserved */
+        .pOffsetForRefFrame = sps->offset_for_ref_frame,
+        .pScalingLists = vksps_scaling,
+        .pSequenceParameterSetVui = vksps_vui,
+    };
+
+    *vkpps_scaling = (StdVideoH264ScalingLists) {
+        .scaling_list_present_mask = 0x0, // mask
+        .use_default_scaling_matrix_mask = 1,
+    };
+
+    *vkpps = (StdVideoH264PictureParameterSet) {
+        .flags = (StdVideoH264PpsFlags) {
+            .transform_8x8_mode_flag = pps->transform_8x8_mode_flag,
+            .redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag,
+            .constrained_intra_pred_flag = pps->constrained_intra_pred_flag,
+            .deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag,
+            .weighted_pred_flag = pps->weighted_pred_flag,
+            .bottom_field_pic_order_in_frame_present_flag = pps->bottom_field_pic_order_in_frame_present_flag,
+            .entropy_coding_mode_flag = pps->entropy_coding_mode_flag,
+            .pic_scaling_matrix_present_flag = pps->pic_scaling_matrix_present_flag,
+        },
+        .seq_parameter_set_id = pps->seq_parameter_set_id,
+        .pic_parameter_set_id = pps->pic_parameter_set_id,
+        .num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active_minus1,
+        .num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active_minus1,
+        .weighted_bipred_idc = pps->weighted_bipred_idc,
+        .pic_init_qp_minus26 = pps->pic_init_qp_minus26,
+        .pic_init_qs_minus26 = pps->pic_init_qs_minus26,
+        .chroma_qp_index_offset = pps->chroma_qp_index_offset,
+        .second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset,
+        .pScalingLists = vkpps_scaling,
+    };
+
+    return 0;
+}
+
+static int create_session_params(AVCodecContext *avctx)
+{
+    int err;
+    VulkanEncodeH264Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext *ctx = &enc->common;
+    FFVulkanContext *s = &ctx->s;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+
+    VulkanH264Units vk_units = { 0 };
+
+    VkVideoEncodeH264SessionParametersAddInfoKHR h264_params_info;
+    VkVideoEncodeH264SessionParametersCreateInfoKHR h264_params;
+
+    /* Convert it to Vulkan */
+    err = base_unit_to_vk(avctx, &vk_units);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to convert SPS/PPS units to Vulkan: %s\n",
+               av_err2str(err));
+        return err;
+    }
+
+    /* Destroy the session params */
+    if (ctx->session_params)
+        vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
+                                             ctx->session_params,
+                                             s->hwctx->alloc);
+
+    h264_params_info = (VkVideoEncodeH264SessionParametersAddInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR,
+        .pStdSPSs = &vk_units.vksps,
+        .stdSPSCount = 1,
+        .pStdPPSs = &vk_units.vkpps,
+        .stdPPSCount = 1,
+    };
+    h264_params = (VkVideoEncodeH264SessionParametersCreateInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR,
+        .maxStdSPSCount = 1,
+        .maxStdPPSCount = 1,
+        .pParametersAddInfo = &h264_params_info,
+    };
+
+    return ff_vulkan_encode_create_session_params(avctx, ctx, &h264_params);
+}
+
+static int parse_feedback_units(AVCodecContext *avctx,
+                                const uint8_t *data, size_t size,
+                                int sps_override, int pps_override)
+{
+    int err;
+    VulkanEncodeH264Context *enc = avctx->priv_data;
+
+    CodedBitstreamContext *cbs;
+    CodedBitstreamFragment au = { 0 };
+
+    err = ff_cbs_init(&cbs, AV_CODEC_ID_H264, avctx);
+    if (err < 0)
+        return err;
+
+    err = ff_cbs_read(cbs, &au, NULL, data, size);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to parse feedback units, bad drivers: %s\n",
+               av_err2str(err));
+        goto fail;
+    }
+
+    /* If PPS has an override, just copy it entirely. */
+    if (pps_override) {
+        for (int i = 0; i < au.nb_units; i++) {
+            if (au.units[i].type == H264_NAL_PPS) {
+                H264RawPPS *pps = au.units[i].content;
+                memcpy(&enc->units.raw_pps, pps, sizeof(*pps));
+                break;
+            }
+        }
+    }
+
+    err = 0;
+fail:
+    ff_cbs_fragment_free(&au);
+    ff_cbs_close(&cbs);
+
+    return err;
+}
+
+static int init_base_units(AVCodecContext *avctx)
+{
+    int err;
+    VkResult ret;
+    VulkanEncodeH264Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext *ctx = &enc->common;
+    FFVulkanContext *s = &ctx->s;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+
+    VkVideoEncodeH264SessionParametersGetInfoKHR h264_params_info;
+    VkVideoEncodeSessionParametersGetInfoKHR params_info;
+    VkVideoEncodeH264SessionParametersFeedbackInfoKHR h264_params_feedback;
+    VkVideoEncodeSessionParametersFeedbackInfoKHR params_feedback;
+
+    void *data = NULL;
+    size_t data_size = 0;
+
+    /* Generate SPS/PPS unit info */
+    err = init_sequence_headers(avctx);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to initialize SPS/PPS units: %s\n",
+               av_err2str(err));
+        return err;
+    }
+
+    /* Create session parameters from them */
+    err = create_session_params(avctx);
+    if (err < 0)
+        return err;
+
+    h264_params_info = (VkVideoEncodeH264SessionParametersGetInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_GET_INFO_KHR,
+        .writeStdSPS = 1,
+        .writeStdPPS = 1,
+        .stdSPSId = enc->units.raw_sps.seq_parameter_set_id,
+        .stdPPSId = enc->units.raw_pps.pic_parameter_set_id,
+    };
+    params_info = (VkVideoEncodeSessionParametersGetInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_GET_INFO_KHR,
+        .pNext = &h264_params_info,
+        .videoSessionParameters = ctx->session_params,
+    };
+
+    h264_params_feedback = (VkVideoEncodeH264SessionParametersFeedbackInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_FEEDBACK_INFO_KHR,
+    };
+    params_feedback = (VkVideoEncodeSessionParametersFeedbackInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_FEEDBACK_INFO_KHR,
+        .pNext = &h264_params_feedback,
+    };
+
+    ret = vk->GetEncodedVideoSessionParametersKHR(s->hwctx->act_dev, &params_info,
+                                                  &params_feedback,
+                                                  &data_size, data);
+    if (ret == VK_INCOMPLETE ||
+        (ret == VK_SUCCESS) && (data_size > 0)) {
+        data = av_mallocz(data_size);
+        if (!data)
+            return AVERROR(ENOMEM);
+    } else {
+        av_log(avctx, AV_LOG_ERROR, "Unable to get feedback for H.264 units = %"SIZE_SPECIFIER"\n", data_size);
+        return err;
+    }
+
+    ret = vk->GetEncodedVideoSessionParametersKHR(s->hwctx->act_dev, &params_info,
+                                                  &params_feedback,
+                                                  &data_size, data);
+    if (ret != VK_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Error writing feedback units\n");
+        return err;
+    }
+
+    av_log(avctx, AV_LOG_VERBOSE, "Feedback units written, overrides: %i (SPS: %i PPS: %i)\n",
+           params_feedback.hasOverrides,
+           h264_params_feedback.hasStdSPSOverrides,
+           h264_params_feedback.hasStdPPSOverrides);
+
+    params_feedback.hasOverrides = 1;
+    h264_params_feedback.hasStdPPSOverrides = 1;
+
+    /* No need to sync any overrides */
+    if (!params_feedback.hasOverrides)
+        return 0;
+
+    /* Parse back tne units and override */
+    err = parse_feedback_units(avctx, data, data_size,
+                               h264_params_feedback.hasStdSPSOverrides,
+                               h264_params_feedback.hasStdPPSOverrides);
+    if (err < 0)
+        return err;
+
+    /* Create final session parameters */
+    err = create_session_params(avctx);
+    if (err < 0)
+        return err;
+
+    return 0;
+}
+
+static int vulkan_encode_h264_add_nal(AVCodecContext *avctx,
+                                      CodedBitstreamFragment *au,
+                                      void *nal_unit)
+{
+    H264RawNALUnitHeader *header = nal_unit;
+
+    int err = ff_cbs_insert_unit_content(au, -1,
+                                         header->nal_unit_type, nal_unit, NULL);
+    if (err < 0)
+        av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: "
+               "type = %d.\n", header->nal_unit_type);
+
+    return err;
+}
+
+static int write_access_unit(AVCodecContext *avctx,
+                             uint8_t *data, size_t *data_len,
+                             CodedBitstreamFragment *au)
+{
+    VulkanEncodeH264Context *enc = avctx->priv_data;
+
+    int err = ff_cbs_write_fragment_data(enc->cbs, au);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n");
+        return err;
+    }
+
+    if (*data_len < au->data_size) {
+        av_log(avctx, AV_LOG_ERROR, "Access unit too large: %"SIZE_SPECIFIER" < %"SIZE_SPECIFIER".\n",
+               *data_len, au->data_size);
+        return AVERROR(ENOSPC);
+    }
+
+    memcpy(data, au->data, au->data_size);
+    *data_len = au->data_size;
+
+    return 0;
+}
+
+static int write_sequence_headers(AVCodecContext *avctx,
+                                  FFHWBaseEncodePicture *base_pic,
+                                  uint8_t *data, size_t *data_len)
+{
+    int err;
+    VulkanEncodeH264Context *enc = avctx->priv_data;
+    VulkanEncodeH264Picture  *hp = base_pic ? base_pic->codec_priv : NULL;
+    CodedBitstreamFragment   *au = &enc->current_access_unit;
+
+    if (hp && hp->units_needed & UNIT_AUD) {
+        err = vulkan_encode_h264_add_nal(avctx, au, &enc->raw_aud);
+        if (err < 0)
+            goto fail;
+    }
+
+    err = vulkan_encode_h264_add_nal(avctx, au, &enc->units.raw_sps);
+    if (err < 0)
+        goto fail;
+
+    err = vulkan_encode_h264_add_nal(avctx, au, &enc->units.raw_pps);
+    if (err < 0)
+        goto fail;
+
+    err = write_access_unit(avctx, data, data_len, au);
+fail:
+    ff_cbs_fragment_reset(au);
+    return err;
+}
+
+static int write_extra_headers(AVCodecContext *avctx,
+                               FFHWBaseEncodePicture *base_pic,
+                               uint8_t *data, size_t *data_len)
+{
+    int err;
+    VulkanEncodeH264Context *enc = avctx->priv_data;
+    VulkanEncodeH264Picture  *hp = base_pic->codec_priv;
+    CodedBitstreamFragment   *au = &enc->current_access_unit;
+
+    if (hp->units_needed & UNIT_AUD) {
+        err = vulkan_encode_h264_add_nal(avctx, au, &enc->raw_aud);
+        if (err < 0)
+            goto fail;
+    }
+
+    if (hp->units_needed & UNIT_SEI_IDENTIFIER) {
+        err = ff_cbs_sei_add_message(enc->cbs, au, 1,
+                                     SEI_TYPE_USER_DATA_UNREGISTERED,
+                                     &enc->sei_identifier, NULL);
+        if (err < 0)
+            goto fail;
+    }
+
+    if (hp->units_needed & UNIT_SEI_TIMING) {
+        if (base_pic->type == FF_HW_PICTURE_TYPE_IDR) {
+            err = ff_cbs_sei_add_message(enc->cbs, au, 1,
+                                         SEI_TYPE_BUFFERING_PERIOD,
+                                         &enc->units.sei_buffering_period, NULL);
+            if (err < 0)
+                goto fail;
+        }
+        err = ff_cbs_sei_add_message(enc->cbs, au, 1,
+                                     SEI_TYPE_PIC_TIMING,
+                                     &enc->sei_pic_timing, NULL);
+        if (err < 0)
+            goto fail;
+    }
+
+    if (hp->units_needed & UNIT_SEI_RECOVERY) {
+        err = ff_cbs_sei_add_message(enc->cbs, au, 1,
+                                     SEI_TYPE_RECOVERY_POINT,
+                                     &enc->sei_recovery_point, NULL);
+        if (err < 0)
+            goto fail;
+    }
+
+    if (hp->units_needed & UNIT_SEI_A53_CC) {
+        err = ff_cbs_sei_add_message(enc->cbs, au, 1,
+                                     SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35,
+                                     &enc->sei_a53cc, NULL);
+        if (err < 0)
+            goto fail;
+    }
+
+    if (hp->units_needed) {
+        err = write_access_unit(avctx, data, data_len, au);
+        if (err < 0)
+            goto fail;
+    } else {
+        err = 0;
+        *data_len = 0;
+    }
+
+fail:
+    ff_cbs_fragment_reset(au);
+    return err;
+}
+
+static int write_filler(AVCodecContext *avctx, uint32_t filler,
+                        uint8_t *data, size_t *data_len)
+{
+    int err;
+    VulkanEncodeH264Context *enc = avctx->priv_data;
+    CodedBitstreamFragment   *au = &enc->current_access_unit;
+
+    H264RawFiller raw_filler = {
+        .nal_unit_header = {
+            .nal_unit_type = H264_NAL_FILLER_DATA,
+        },
+        .filler_size = filler,
+    };
+
+    err = vulkan_encode_h264_add_nal(avctx, au, &raw_filler);
+    if (err < 0)
+        goto fail;
+
+    err = write_access_unit(avctx, data, data_len, au);
+fail:
+    ff_cbs_fragment_reset(au);
+    return err;
+}
+
+static const FFVulkanCodec enc_cb = {
+    .flags = FF_HW_FLAG_B_PICTURES |
+             FF_HW_FLAG_B_PICTURE_REFERENCES |
+             FF_HW_FLAG_NON_IDR_KEY_PICTURES,
+    .picture_priv_data_size = sizeof(VulkanEncodeH264Picture),
+    .filler_header_size = 6,
+    .init_profile = init_profile,
+    .init_pic_rc = init_pic_rc,
+    .init_pic_params = init_pic_params,
+    .write_sequence_headers = write_sequence_headers,
+    .write_extra_headers = write_extra_headers,
+    .write_filler = write_filler,
+};
+
+static av_cold int vulkan_encode_h264_init(AVCodecContext *avctx)
+{
+    int err, ref_l0, ref_l1;
+    VulkanEncodeH264Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext *ctx = &enc->common;
+    FFVulkanContext *s = &ctx->s;
+    FFHWBaseEncodeContext *base_ctx = &ctx->base;
+    int flags;
+
+    if (avctx->profile == AV_PROFILE_UNKNOWN)
+        avctx->profile = enc->common.opts.profile;
+
+    enc->caps = (VkVideoEncodeH264CapabilitiesKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_KHR,
+    };
+
+    enc->quality_props = (VkVideoEncodeH264QualityLevelPropertiesKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_QUALITY_LEVEL_PROPERTIES_KHR,
+    };
+
+    err = ff_vulkan_encode_init(avctx, &enc->common,
+                                &ff_vk_enc_h264_desc, &enc_cb,
+                                &enc->caps, &enc->quality_props);
+    if (err < 0)
+        return err;
+
+    av_log(avctx, AV_LOG_VERBOSE, "H264 encoder capabilities:\n");
+    av_log(avctx, AV_LOG_VERBOSE, "    Standard capability flags:\n");
+    av_log(avctx, AV_LOG_VERBOSE, "        separate_color_plane: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_SEPARATE_COLOR_PLANE_FLAG_SET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        qprime_y_zero_transform_bypass: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_QPPRIME_Y_ZERO_TRANSFORM_BYPASS_FLAG_SET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        scaling_lists: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_SCALING_MATRIX_PRESENT_FLAG_SET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        chroma_qp_index_offset: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_CHROMA_QP_INDEX_OFFSET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        second_chroma_qp_index_offset: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_SECOND_CHROMA_QP_INDEX_OFFSET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        pic_init_qp: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_PIC_INIT_QP_MINUS26_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        weighted:%s%s%s\n",
+           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_WEIGHTED_PRED_FLAG_SET_BIT_KHR ?
+               " pred" : "",
+           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_WEIGHTED_BIPRED_IDC_EXPLICIT_BIT_KHR ?
+               " bipred_explicit" : "",
+           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_WEIGHTED_BIPRED_IDC_IMPLICIT_BIT_KHR ?
+               " bipred_implicit" : "");
+    av_log(avctx, AV_LOG_VERBOSE, "        8x8_transforms: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_TRANSFORM_8X8_MODE_FLAG_SET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        disable_direct_spatial_mv_pred: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_DIRECT_SPATIAL_MV_PRED_FLAG_UNSET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        coder:%s%s\n",
+           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_ENTROPY_CODING_MODE_FLAG_UNSET_BIT_KHR ?
+               " cabac" : "",
+           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_ENTROPY_CODING_MODE_FLAG_SET_BIT_KHR ?
+               " cavlc" : "");
+    av_log(avctx, AV_LOG_VERBOSE, "        direct_8x8_inference: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_DIRECT_8X8_INFERENCE_FLAG_UNSET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        constrained_intra_pred: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_CONSTRAINED_INTRA_PRED_FLAG_SET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        deblock:%s%s%s\n",
+           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_DISABLED_BIT_KHR ?
+               " filter_disabling" : "",
+           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_ENABLED_BIT_KHR ?
+               " filter_enabling" : "",
+           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H264_STD_DEBLOCKING_FILTER_PARTIAL_BIT_KHR ?
+               " filter_partial" : "");
+
+    av_log(avctx, AV_LOG_VERBOSE, "    Capability flags:\n");
+    av_log(avctx, AV_LOG_VERBOSE, "        hdr_compliance: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        pred_weight_table_generated: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        row_unaligned_slice: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        different_slice_type: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        b_frame_in_l0_list: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        b_frame_in_l1_list: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        per_pict_type_min_max_qp: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        per_slice_constant_qp: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PER_SLICE_CONSTANT_QP_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        generate_prefix_nalu: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_KHR));
+
+    av_log(avctx, AV_LOG_VERBOSE, "    Capabilities:\n");
+    av_log(avctx, AV_LOG_VERBOSE, "        maxLevelIdc: %i\n",
+           enc->caps.maxLevelIdc);
+    av_log(avctx, AV_LOG_VERBOSE, "        maxSliceCount: %i\n",
+           enc->caps.maxSliceCount);
+    av_log(avctx, AV_LOG_VERBOSE, "        max(P/B)PictureL0ReferenceCount: %i P's; %i B's\n",
+           enc->caps.maxPPictureL0ReferenceCount,
+           enc->caps.maxBPictureL0ReferenceCount);
+    av_log(avctx, AV_LOG_VERBOSE, "        maxL1ReferenceCount: %i\n",
+           enc->caps.maxL1ReferenceCount);
+    av_log(avctx, AV_LOG_VERBOSE, "        maxTemporalLayerCount: %i\n",
+           enc->caps.maxTemporalLayerCount);
+    av_log(avctx, AV_LOG_VERBOSE, "        expectDyadicTemporalLayerPattern: %i\n",
+           enc->caps.expectDyadicTemporalLayerPattern);
+    av_log(avctx, AV_LOG_VERBOSE, "        min/max Qp: [%i, %i]\n",
+           enc->caps.minQp, enc->caps.maxQp);
+    av_log(avctx, AV_LOG_VERBOSE, "        prefersGopRemainingFrames: %i\n",
+           enc->caps.prefersGopRemainingFrames);
+    av_log(avctx, AV_LOG_VERBOSE, "        requiresGopRemainingFrames: %i\n",
+           enc->caps.requiresGopRemainingFrames);
+
+    err = init_enc_options(avctx);
+    if (err < 0)
+        return err;
+
+    flags = ctx->codec->flags;
+    if (!enc->caps.maxPPictureL0ReferenceCount &&
+        !enc->caps.maxBPictureL0ReferenceCount &&
+        !enc->caps.maxL1ReferenceCount) {
+        /* Intra-only */
+        flags |= FF_HW_FLAG_INTRA_ONLY;
+        ref_l0 = ref_l1 = 0;
+    } else if (!enc->caps.maxPPictureL0ReferenceCount) {
+        /* No P-frames? How. */
+        base_ctx->p_to_gpb = 1;
+        ref_l0 = enc->caps.maxBPictureL0ReferenceCount;
+        ref_l1 = enc->caps.maxL1ReferenceCount;
+    } else if (!enc->caps.maxBPictureL0ReferenceCount &&
+               !enc->caps.maxL1ReferenceCount) {
+        /* No B-frames */
+        flags &= ~(FF_HW_FLAG_B_PICTURES | FF_HW_FLAG_B_PICTURE_REFERENCES);
+        ref_l0 = enc->caps.maxPPictureL0ReferenceCount;
+        ref_l1 = 0;
+    } else {
+        /* P and B frames */
+        ref_l0 = FFMIN(enc->caps.maxPPictureL0ReferenceCount,
+                       enc->caps.maxBPictureL0ReferenceCount);
+        ref_l1 = enc->caps.maxL1ReferenceCount;
+    }
+
+    err = ff_hw_base_init_gop_structure(base_ctx, avctx, ref_l0, ref_l1,
+                                        flags, 0);
+    if (err < 0)
+        return err;
+
+    base_ctx->output_delay = base_ctx->b_per_p;
+    base_ctx->decode_delay = base_ctx->max_b_depth;
+
+    /* Prepare SEI */
+    if (enc->unit_elems & UNIT_SEI_IDENTIFIER) {
+        int len;
+
+        memcpy(enc->sei_identifier.uuid_iso_iec_11578,
+               vulkan_encode_h264_sei_identifier_uuid,
+               sizeof(enc->sei_identifier.uuid_iso_iec_11578));
+
+        len = snprintf(NULL, 0,
+                       "%s / Vulkan video %i.%i.%i / %s %i.%i.%i / %s",
+                       LIBAVCODEC_IDENT,
+                       CODEC_VER(ff_vk_enc_h264_desc.ext_props.specVersion),
+                       s->driver_props.driverName,
+                       CODEC_VER(s->props.properties.driverVersion),
+                       s->props.properties.deviceName);
+
+        if (len >= 0) {
+            enc->sei_identifier_string = av_malloc(len + 1);
+            if (!enc->sei_identifier_string)
+                return AVERROR(ENOMEM);
+
+            len = snprintf(enc->sei_identifier_string, len + 1,
+                           "%s / Vulkan video %i.%i.%i / %s %i.%i.%i / %s",
+                           LIBAVCODEC_IDENT,
+                           CODEC_VER(ff_vk_enc_h264_desc.ext_props.specVersion),
+                           s->driver_props.driverName,
+                           CODEC_VER(s->props.properties.driverVersion),
+                           s->props.properties.deviceName);
+
+            enc->sei_identifier.data        = enc->sei_identifier_string;
+            enc->sei_identifier.data_length = len + 1;
+        }
+    }
+
+    /* Init CBS */
+    err = ff_cbs_init(&enc->cbs, AV_CODEC_ID_H264, avctx);
+    if (err < 0)
+        return err;
+
+    /* Create units and session parameters */
+    err = init_base_units(avctx);
+    if (err < 0)
+        return err;
+
+    /* Write out extradata */
+    err = ff_vulkan_write_global_header(avctx, &enc->common);
+    if (err < 0)
+        return err;
+
+    return 0;
+}
+
+static av_cold int vulkan_encode_h264_close(AVCodecContext *avctx)
+{
+    VulkanEncodeH264Context *enc = avctx->priv_data;
+    ff_vulkan_encode_uninit(&enc->common);
+    return 0;
+}
+
+#define OFFSET(x) offsetof(VulkanEncodeH264Context, x)
+#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
+static const AVOption vulkan_encode_h264_options[] = {
+    HW_BASE_ENCODE_COMMON_OPTIONS,
+    VULKAN_ENCODE_COMMON_OPTIONS,
+
+    { "profile", "Set profile (profile_idc and constraint_set*_flag)",
+      OFFSET(common.opts.profile), AV_OPT_TYPE_INT,
+      { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, 0xffff, FLAGS, .unit = "profile" },
+
+#define PROFILE(name, value)  name, NULL, 0, AV_OPT_TYPE_CONST, \
+      { .i64 = value }, 0, 0, FLAGS, .unit = "profile"
+    { PROFILE("constrained_baseline", AV_PROFILE_H264_CONSTRAINED_BASELINE) },
+    { PROFILE("main",                 AV_PROFILE_H264_MAIN) },
+    { PROFILE("high",                 AV_PROFILE_H264_HIGH) },
+    { PROFILE("high444p",             AV_PROFILE_H264_HIGH_10) },
+#undef PROFILE
+
+    { "level", "Set level (level_idc)",
+      OFFSET(common.opts.level), AV_OPT_TYPE_INT,
+      { .i64 = AV_LEVEL_UNKNOWN }, AV_LEVEL_UNKNOWN, 0xff, FLAGS, .unit = "level" },
+
+#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
+      { .i64 = value }, 0, 0, FLAGS, .unit = "level"
+    { LEVEL("1",   10) },
+    { LEVEL("1.1", 11) },
+    { LEVEL("1.2", 12) },
+    { LEVEL("1.3", 13) },
+    { LEVEL("2",   20) },
+    { LEVEL("2.1", 21) },
+    { LEVEL("2.2", 22) },
+    { LEVEL("3",   30) },
+    { LEVEL("3.1", 31) },
+    { LEVEL("3.2", 32) },
+    { LEVEL("4",   40) },
+    { LEVEL("4.1", 41) },
+    { LEVEL("4.2", 42) },
+    { LEVEL("5",   50) },
+    { LEVEL("5.1", 51) },
+    { LEVEL("5.2", 52) },
+    { LEVEL("6",   60) },
+    { LEVEL("6.1", 61) },
+    { LEVEL("6.2", 62) },
+#undef LEVEL
+
+    { "coder", "Entropy coder type", OFFSET(unit_opts.cabac), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, FLAGS, "coder" },
+        { "cabac", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, FLAGS, "coder" },
+        { "vlc",   NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS, "coder" },
+
+    { "units", "Set units to include", OFFSET(unit_elems), AV_OPT_TYPE_FLAGS, { .i64 = UNIT_AUD | UNIT_SEI_IDENTIFIER | UNIT_SEI_RECOVERY | UNIT_SEI_TIMING | UNIT_SEI_A53_CC }, 0, INT_MAX, FLAGS, "units" },
+        { "aud",        "Include AUD units", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_AUD }, INT_MIN, INT_MAX, FLAGS, "units" },
+        { "identifier", "Include encoder version identifier", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_SEI_IDENTIFIER }, INT_MIN, INT_MAX, FLAGS, "units" },
+        { "timing",     "Include timing parameters (buffering_period and pic_timing)", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_SEI_TIMING }, INT_MIN, INT_MAX, FLAGS, "units" },
+        { "recovery",   "Include recovery points where appropriate", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_SEI_RECOVERY }, INT_MIN, INT_MAX, FLAGS, "units" },
+        { "a53_cc",     "Include A/53 caption data", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_SEI_A53_CC }, INT_MIN, INT_MAX, FLAGS, "units" },
+
+    { NULL },
+};
+
+static const FFCodecDefault vulkan_encode_h264_defaults[] = {
+    { "b",              "0"   },
+    { "bf",             "2"   },
+    { "g",              "300" },
+    { "i_qfactor",      "1"   },
+    { "i_qoffset",      "0"   },
+    { "b_qfactor",      "1"   },
+    { "b_qoffset",      "0"   },
+    { "qmin",           "-1"  },
+    { "qmax",           "-1"  },
+    { "refs",           "0"   },
+    { NULL },
+};
+
+static const AVClass vulkan_encode_h264_class = {
+    .class_name = "h264_vulkan",
+    .item_name  = av_default_item_name,
+    .option     = vulkan_encode_h264_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+const FFCodec ff_h264_vulkan_encoder = {
+    .p.name         = "h264_vulkan",
+    CODEC_LONG_NAME("H.264/AVC (Vulkan)"),
+    .p.type         = AVMEDIA_TYPE_VIDEO,
+    .p.id           = AV_CODEC_ID_H264,
+    .priv_data_size = sizeof(VulkanEncodeH264Context),
+    .init           = &vulkan_encode_h264_init,
+    FF_CODEC_RECEIVE_PACKET_CB(&ff_vulkan_encode_receive_packet),
+    .close          = &vulkan_encode_h264_close,
+    .p.priv_class   = &vulkan_encode_h264_class,
+    .p.capabilities = AV_CODEC_CAP_DELAY |
+                      AV_CODEC_CAP_HARDWARE |
+                      AV_CODEC_CAP_DR1 |
+                      AV_CODEC_CAP_ENCODER_FLUSH |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
+    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
+    .defaults       = vulkan_encode_h264_defaults,
+    CODEC_PIXFMTS(AV_PIX_FMT_VULKAN),
+    .hw_configs     = ff_vulkan_encode_hw_configs,
+    .p.wrapper_name = "vulkan",
+};
-- 
2.49.1


From 1f4495b10a28899cb25ce33031a5d9af2b2f958c Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:34:16 +0000
Subject: [PATCH 077/118] Changing vulkan file directory

---
 libavcodec/vulkan_encode_h265.c | 1795 -------------------------------
 1 file changed, 1795 deletions(-)
 delete mode 100644 libavcodec/vulkan_encode_h265.c

diff --git a/libavcodec/vulkan_encode_h265.c b/libavcodec/vulkan_encode_h265.c
deleted file mode 100644
index c30b7e8f93..0000000000
--- a/libavcodec/vulkan_encode_h265.c
+++ /dev/null
@@ -1,1795 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/internal.h"
-#include "libavutil/opt.h"
-#include "libavutil/mem.h"
-
-#include "cbs.h"
-#include "cbs_h265.h"
-#include "atsc_a53.h"
-#include "libavutil/mastering_display_metadata.h"
-
-#include "codec_internal.h"
-#include "version.h"
-#include "hw_base_encode_h265.h"
-
-#include "vulkan_encode.h"
-
-enum UnitElems {
-    UNIT_AUD                     = 1 << 0,
-    UNIT_SEI_MASTERING_DISPLAY   = 1 << 1,
-    UNIT_SEI_CONTENT_LIGHT_LEVEL = 1 << 2,
-    UNIT_SEI_A53_CC              = 1 << 3,
-};
-
-const FFVulkanEncodeDescriptor ff_vk_enc_h265_desc = {
-    .codec_id         = AV_CODEC_ID_H265,
-    .encode_extension = FF_VK_EXT_VIDEO_ENCODE_H265,
-    .encode_op        = VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR,
-    .ext_props = {
-        .extensionName = VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_EXTENSION_NAME,
-        .specVersion   = VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION,
-    },
-};
-
-typedef struct VulkanEncodeH265Picture {
-    int frame_num;
-    int64_t last_idr_frame;
-    uint16_t idr_pic_id;
-    int primary_pic_type;
-    int slice_type;
-    int pic_order_cnt;
-    int pic_type;
-
-    enum UnitElems units_needed;
-
-    VkVideoEncodeH265RateControlInfoKHR vkrc_info;
-    VkVideoEncodeH265RateControlLayerInfoKHR vkrc_layer_info;
-
-    StdVideoEncodeH265PictureInfo   h265pic_info;
-    VkVideoEncodeH265PictureInfoKHR vkh265pic_info;
-
-    StdVideoEncodeH265WeightTable slice_wt;
-    StdVideoEncodeH265SliceSegmentHeader slice_hdr;
-    VkVideoEncodeH265NaluSliceSegmentInfoKHR vkslice;
-
-    StdVideoEncodeH265ReferenceInfo h265dpb_info;
-    VkVideoEncodeH265DpbSlotInfoKHR vkh265dpb_info;
-
-    StdVideoEncodeH265ReferenceListsInfo ref_list_info;
-    StdVideoEncodeH265LongTermRefPics l_rps;
-    StdVideoH265ShortTermRefPicSet s_rps;
-} VulkanEncodeH265Picture;
-
-typedef struct VulkanEncodeH265Context {
-    FFVulkanEncodeContext common;
-
-    FFHWBaseEncodeH265 units;
-    FFHWBaseEncodeH265Opts unit_opts;
-
-    enum UnitElems unit_elems;
-
-    uint8_t fixed_qp_idr;
-    uint8_t fixed_qp_p;
-    uint8_t fixed_qp_b;
-
-    uint64_t hrd_buffer_size;
-    uint64_t initial_buffer_fullness;
-
-    VkVideoEncodeH265ProfileInfoKHR profile;
-
-    VkVideoEncodeH265CapabilitiesKHR caps;
-    VkVideoEncodeH265QualityLevelPropertiesKHR quality_props;
-
-    CodedBitstreamContext *cbs;
-    CodedBitstreamFragment current_access_unit;
-
-    H265RawAUD                         raw_aud;
-
-    SEIRawMasteringDisplayColourVolume sei_mastering_display;
-    SEIRawContentLightLevelInfo        sei_content_light_level;
-    SEIRawUserDataRegistered           sei_a53cc;
-    void                              *sei_a53cc_data;
-} VulkanEncodeH265Context;
-
-static int init_pic_rc(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
-                       VkVideoEncodeRateControlInfoKHR *rc_info,
-                       VkVideoEncodeRateControlLayerInfoKHR *rc_layer)
-{
-    VulkanEncodeH265Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext   *ctx = &enc->common;
-    VulkanEncodeH265Picture  *hp = pic->codec_priv;
-
-    hp->vkrc_info = (VkVideoEncodeH265RateControlInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_KHR,
-        .flags = VK_VIDEO_ENCODE_H265_RATE_CONTROL_REFERENCE_PATTERN_FLAT_BIT_KHR |
-                 VK_VIDEO_ENCODE_H265_RATE_CONTROL_REGULAR_GOP_BIT_KHR,
-        .idrPeriod = ctx->base.gop_size,
-        .gopFrameCount = ctx->base.gop_size,
-        .consecutiveBFrameCount = FFMAX(ctx->base.b_per_p - 1, 0),
-        .subLayerCount = 0,
-    };
-    rc_info->pNext = &hp->vkrc_info;
-
-    if (rc_info->rateControlMode > VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
-        rc_info->virtualBufferSizeInMs = (enc->hrd_buffer_size * 1000LL) / avctx->bit_rate;
-        rc_info->initialVirtualBufferSizeInMs = (enc->initial_buffer_fullness * 1000LL) / avctx->bit_rate;
-
-        hp->vkrc_layer_info = (VkVideoEncodeH265RateControlLayerInfoKHR) {
-            .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_KHR,
-
-            .useMinQp  = avctx->qmin > 0,
-            .minQp.qpI = avctx->qmin > 0 ? avctx->qmin : 0,
-            .minQp.qpP = avctx->qmin > 0 ? avctx->qmin : 0,
-            .minQp.qpB = avctx->qmin > 0 ? avctx->qmin : 0,
-
-            .useMaxQp  = avctx->qmax > 0,
-            .maxQp.qpI = avctx->qmax > 0 ? avctx->qmax : 0,
-            .maxQp.qpP = avctx->qmax > 0 ? avctx->qmax : 0,
-            .maxQp.qpB = avctx->qmax > 0 ? avctx->qmax : 0,
-
-            .useMaxFrameSize = 0,
-        };
-        rc_layer->pNext = &hp->vkrc_layer_info;
-        hp->vkrc_info.subLayerCount = 1;
-    }
-
-    return 0;
-}
-
-static int vk_enc_h265_update_pic_info(AVCodecContext *avctx,
-                                       FFHWBaseEncodePicture *pic)
-{
-    VulkanEncodeH265Context   *enc = avctx->priv_data;
-    VulkanEncodeH265Picture    *hp = pic->codec_priv;
-    FFHWBaseEncodePicture    *prev = pic->prev;
-    VulkanEncodeH265Picture *hprev = prev ? prev->codec_priv : NULL;
-
-    if (pic->type == FF_HW_PICTURE_TYPE_IDR) {
-        av_assert0(pic->display_order == pic->encode_order);
-
-        hp->last_idr_frame = pic->display_order;
-
-        hp->slice_type     = STD_VIDEO_H265_SLICE_TYPE_I;
-        hp->pic_type       = STD_VIDEO_H265_PICTURE_TYPE_IDR;
-    } else {
-        av_assert0(prev);
-        hp->last_idr_frame = hprev->last_idr_frame;
-
-        if (pic->type == FF_HW_PICTURE_TYPE_I) {
-            hp->slice_type     = STD_VIDEO_H265_SLICE_TYPE_I;
-            hp->pic_type       = STD_VIDEO_H265_PICTURE_TYPE_I;
-        } else if (pic->type == FF_HW_PICTURE_TYPE_P) {
-            av_assert0(pic->refs[0]);
-            hp->slice_type     = STD_VIDEO_H265_SLICE_TYPE_P;
-            hp->pic_type       = STD_VIDEO_H265_PICTURE_TYPE_P;
-        } else {
-            FFHWBaseEncodePicture *irap_ref;
-            av_assert0(pic->refs[0][0] && pic->refs[1][0]);
-            for (irap_ref = pic; irap_ref; irap_ref = irap_ref->refs[1][0]) {
-                if (irap_ref->type == FF_HW_PICTURE_TYPE_I)
-                    break;
-            }
-            hp->slice_type = STD_VIDEO_H265_SLICE_TYPE_B;
-            hp->pic_type   = STD_VIDEO_H265_PICTURE_TYPE_B;
-        }
-    }
-    hp->pic_order_cnt = pic->display_order - hp->last_idr_frame;
-
-    hp->units_needed = 0;
-
-    if (enc->unit_elems & UNIT_AUD) {
-        hp->units_needed |= UNIT_AUD;
-        enc->raw_aud = (H265RawAUD) {
-            .nal_unit_header = {
-                .nal_unit_type         = HEVC_NAL_AUD,
-                .nuh_layer_id          = 0,
-                .nuh_temporal_id_plus1 = 1,
-            },
-            .pic_type = hp->pic_type,
-        };
-    }
-
-    // Only look for the metadata on I/IDR frame on the output. We
-    // may force an IDR frame on the output where the metadata gets
-    // changed on the input frame.
-    if ((enc->unit_elems & UNIT_SEI_MASTERING_DISPLAY) &&
-        (pic->type == FF_HW_PICTURE_TYPE_I || pic->type == FF_HW_PICTURE_TYPE_IDR)) {
-        AVFrameSideData *sd =
-            av_frame_get_side_data(pic->input_image,
-                                   AV_FRAME_DATA_MASTERING_DISPLAY_METADATA);
-
-        if (sd) {
-            AVMasteringDisplayMetadata *mdm = (AVMasteringDisplayMetadata *)sd->data;
-
-            // SEI is needed when both the primaries and luminance are set
-            if (mdm->has_primaries && mdm->has_luminance) {
-                SEIRawMasteringDisplayColourVolume *mdcv =
-                    &enc->sei_mastering_display;
-                const int mapping[3] = {1, 2, 0};
-                const int chroma_den = 50000;
-                const int luma_den   = 10000;
-
-                for (int i = 0; i < 3; i++) {
-                    const int j = mapping[i];
-                    mdcv->display_primaries_x[i] =
-                        FFMIN(lrint(chroma_den *
-                                    av_q2d(mdm->display_primaries[j][0])),
-                              chroma_den);
-                    mdcv->display_primaries_y[i] =
-                        FFMIN(lrint(chroma_den *
-                                    av_q2d(mdm->display_primaries[j][1])),
-                              chroma_den);
-                }
-
-                mdcv->white_point_x =
-                    FFMIN(lrint(chroma_den * av_q2d(mdm->white_point[0])),
-                          chroma_den);
-                mdcv->white_point_y =
-                    FFMIN(lrint(chroma_den * av_q2d(mdm->white_point[1])),
-                          chroma_den);
-
-                mdcv->max_display_mastering_luminance =
-                    lrint(luma_den * av_q2d(mdm->max_luminance));
-                mdcv->min_display_mastering_luminance =
-                    FFMIN(lrint(luma_den * av_q2d(mdm->min_luminance)),
-                          mdcv->max_display_mastering_luminance);
-
-                hp->units_needed |= UNIT_SEI_MASTERING_DISPLAY;
-            }
-        }
-    }
-
-    if ((enc->unit_elems & UNIT_SEI_CONTENT_LIGHT_LEVEL) &&
-        (pic->type == FF_HW_PICTURE_TYPE_I || pic->type == FF_HW_PICTURE_TYPE_IDR)) {
-        AVFrameSideData *sd = av_frame_get_side_data(pic->input_image,
-                                                     AV_FRAME_DATA_CONTENT_LIGHT_LEVEL);
-
-        if (sd) {
-            AVContentLightMetadata *clm = (AVContentLightMetadata *)sd->data;
-            SEIRawContentLightLevelInfo *clli = &enc->sei_content_light_level;
-
-            clli->max_content_light_level     = FFMIN(clm->MaxCLL,  65535);
-            clli->max_pic_average_light_level = FFMIN(clm->MaxFALL, 65535);
-
-            hp->units_needed |= UNIT_SEI_CONTENT_LIGHT_LEVEL;
-        }
-    }
-
-    if (enc->unit_elems & UNIT_SEI_A53_CC) {
-        int err;
-        size_t sei_a53cc_len;
-        av_freep(&enc->sei_a53cc_data);
-        err = ff_alloc_a53_sei(pic->input_image, 0, &enc->sei_a53cc_data, &sei_a53cc_len);
-        if (err < 0)
-            return err;
-        if (enc->sei_a53cc_data != NULL) {
-            enc->sei_a53cc.itu_t_t35_country_code = 181;
-            enc->sei_a53cc.data = (uint8_t *)enc->sei_a53cc_data + 1;
-            enc->sei_a53cc.data_length = sei_a53cc_len - 1;
-
-            hp->units_needed |= UNIT_SEI_A53_CC;
-        }
-    }
-
-    return 0;
-}
-
-static void setup_slices(AVCodecContext *avctx,
-                         FFHWBaseEncodePicture *pic)
-{
-    VulkanEncodeH265Context *enc = avctx->priv_data;
-    VulkanEncodeH265Picture *hp = pic->codec_priv;
-
-    hp->slice_wt = (StdVideoEncodeH265WeightTable) {
-        .flags = (StdVideoEncodeH265WeightTableFlags) {
-            .luma_weight_l0_flag = 0,
-            .chroma_weight_l0_flag = 0,
-            .luma_weight_l1_flag = 0,
-            .chroma_weight_l1_flag = 0,
-        },
-        .luma_log2_weight_denom = 0,
-        .delta_chroma_log2_weight_denom = 0,
-        .delta_luma_weight_l0 = { 0 },
-        .luma_offset_l0 = { 0 },
-        .delta_chroma_weight_l0 = { { 0 } },
-        .delta_chroma_offset_l0 = { { 0 } },
-        .delta_luma_weight_l1 = { 0 },
-        .luma_offset_l1 = { 0 },
-        .delta_chroma_weight_l1 = { { 0 } },
-        .delta_chroma_offset_l1 = { { 0 } },
-    };
-
-    hp->slice_hdr = (StdVideoEncodeH265SliceSegmentHeader) {
-        .flags = (StdVideoEncodeH265SliceSegmentHeaderFlags) {
-            .first_slice_segment_in_pic_flag = 1,
-            .dependent_slice_segment_flag = 0,
-            .slice_sao_luma_flag = enc->units.raw_sps.sample_adaptive_offset_enabled_flag,
-            .slice_sao_chroma_flag = enc->units.raw_sps.sample_adaptive_offset_enabled_flag,
-            .num_ref_idx_active_override_flag = 0,
-            .mvd_l1_zero_flag = 0,
-            .cabac_init_flag = 0,
-            .cu_chroma_qp_offset_enabled_flag = 0,
-            .deblocking_filter_override_flag = 0,
-            .slice_deblocking_filter_disabled_flag = 0,
-            .collocated_from_l0_flag = 1,
-            .slice_loop_filter_across_slices_enabled_flag = 0,
-            /* Reserved */
-        },
-        .slice_type = hp->slice_type,
-        .slice_segment_address = 0,
-        .collocated_ref_idx = 0,
-        .MaxNumMergeCand = 5,
-        .slice_cb_qp_offset = 0,
-        .slice_cr_qp_offset = 0,
-        .slice_beta_offset_div2 = 0,
-        .slice_tc_offset_div2 = 0,
-        .slice_act_y_qp_offset = 0,
-        .slice_act_cb_qp_offset = 0,
-        .slice_act_cr_qp_offset = 0,
-        .slice_qp_delta = 0, /* Filled in below */
-        /* Reserved */
-        .pWeightTable = NULL, // &hp->slice_wt,
-    };
-
-    hp->vkslice = (VkVideoEncodeH265NaluSliceSegmentInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_KHR,
-        .pNext = NULL,
-        .constantQp = pic->type == FF_HW_PICTURE_TYPE_B ? enc->fixed_qp_b :
-                      pic->type == FF_HW_PICTURE_TYPE_P ? enc->fixed_qp_p :
-                                                          enc->fixed_qp_idr,
-        .pStdSliceSegmentHeader = &hp->slice_hdr,
-    };
-
-    if (enc->common.opts.rc_mode != VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR)
-        hp->vkslice.constantQp = 0;
-
-    hp->slice_hdr.slice_qp_delta = hp->vkslice.constantQp -
-                                   (enc->units.raw_pps.init_qp_minus26 + 26);
-
-    hp->vkh265pic_info.pNaluSliceSegmentEntries = &hp->vkslice;
-    hp->vkh265pic_info.naluSliceSegmentEntryCount = 1;
-}
-
-static void setup_refs(AVCodecContext *avctx,
-                       FFHWBaseEncodePicture *pic,
-                       VkVideoEncodeInfoKHR *encode_info)
-{
-    int i, j;
-    VulkanEncodeH265Context *enc = avctx->priv_data;
-    VulkanEncodeH265Picture *hp = pic->codec_priv;
-
-    hp->ref_list_info = (StdVideoEncodeH265ReferenceListsInfo) {
-        .flags = (StdVideoEncodeH265ReferenceListsInfoFlags) {
-            .ref_pic_list_modification_flag_l0 = 0,
-            .ref_pic_list_modification_flag_l1 = 0,
-            /* Reserved */
-        },
-        /* May be overridden during setup_slices() */
-        .num_ref_idx_l0_active_minus1 = pic->nb_refs[0] - 1,
-        .num_ref_idx_l1_active_minus1 = pic->nb_refs[1] - 1,
-        /* Reserved */
-        .list_entry_l0 = { 0 },
-        .list_entry_l1 = { 0 },
-    };
-
-    for (i = 0; i < STD_VIDEO_H265_MAX_NUM_LIST_REF; i++)
-        hp->ref_list_info.RefPicList0[i] = hp->ref_list_info.RefPicList1[i] = -1;
-
-    /* Note: really not sure */
-    for (i = 0; i < pic->nb_refs[0]; i++) {
-        VkVideoReferenceSlotInfoKHR *slot_info;
-        slot_info = (VkVideoReferenceSlotInfoKHR *)&encode_info->pReferenceSlots[i];
-        hp->ref_list_info.RefPicList0[i] = slot_info->slotIndex;
-    }
-
-    /* Note: really not sure */
-    for (i = 0; i < pic->nb_refs[1]; i++) {
-        VkVideoReferenceSlotInfoKHR *slot_info;
-        slot_info = (VkVideoReferenceSlotInfoKHR *)&encode_info->pReferenceSlots[pic->nb_refs[0] + i];
-        hp->ref_list_info.RefPicList1[i] = slot_info->slotIndex;
-    }
-
-    hp->h265pic_info.pRefLists = &hp->ref_list_info;
-
-    if (pic->type != FF_HW_PICTURE_TYPE_IDR) {
-        StdVideoH265ShortTermRefPicSet *rps;
-        VulkanEncodeH265Picture *strp;
-        int rps_poc[MAX_DPB_SIZE];
-        int rps_used[MAX_DPB_SIZE];
-        int poc, rps_pics;
-
-        hp->h265pic_info.flags.short_term_ref_pic_set_sps_flag = 0;
-
-        rps = &hp->s_rps;
-        memset(rps, 0, sizeof(*rps));
-
-        rps_pics = 0;
-        for (i = 0; i < MAX_REFERENCE_LIST_NUM; i++) {
-            for (j = 0; j < pic->nb_refs[i]; j++) {
-                strp = pic->refs[i][j]->codec_priv;
-                rps_poc[rps_pics]  = strp->pic_order_cnt;
-                rps_used[rps_pics] = 1;
-                ++rps_pics;
-            }
-        }
-
-        for (i = 0; i < pic->nb_dpb_pics; i++) {
-            if (pic->dpb[i] == pic)
-                continue;
-
-            for (j = 0; j < pic->nb_refs[0]; j++) {
-                if (pic->dpb[i] == pic->refs[0][j])
-                    break;
-            }
-            if (j < pic->nb_refs[0])
-                continue;
-
-            for (j = 0; j < pic->nb_refs[1]; j++) {
-                if (pic->dpb[i] == pic->refs[1][j])
-                    break;
-            }
-            if (j < pic->nb_refs[1])
-                continue;
-
-            strp = pic->dpb[i]->codec_priv;
-            rps_poc[rps_pics]  = strp->pic_order_cnt;
-            rps_used[rps_pics] = 0;
-            ++rps_pics;
-        }
-
-        for (i = 1; i < rps_pics; i++) {
-            for (j = i; j > 0; j--) {
-                if (rps_poc[j] > rps_poc[j - 1])
-                    break;
-                av_assert0(rps_poc[j] != rps_poc[j - 1]);
-                FFSWAP(int, rps_poc[j],  rps_poc[j - 1]);
-                FFSWAP(int, rps_used[j], rps_used[j - 1]);
-            }
-        }
-
-        av_log(avctx, AV_LOG_DEBUG, "RPS for POC %d:", hp->pic_order_cnt);
-        for (i = 0; i < rps_pics; i++)
-            av_log(avctx, AV_LOG_DEBUG, " (%d,%d)", rps_poc[i], rps_used[i]);
-
-        av_log(avctx, AV_LOG_DEBUG, "\n");
-
-        for (i = 0; i < rps_pics; i++) {
-            av_assert0(rps_poc[i] != hp->pic_order_cnt);
-            if (rps_poc[i] > hp->pic_order_cnt)
-                break;
-        }
-
-        rps->num_negative_pics = i;
-        rps->used_by_curr_pic_s0_flag = 0x0;
-        poc = hp->pic_order_cnt;
-        for (j = i - 1; j >= 0; j--) {
-            rps->delta_poc_s0_minus1[i - 1 - j] = poc - rps_poc[j] - 1;
-            rps->used_by_curr_pic_s0_flag |= rps_used[j] << (i - 1 - j);
-            poc = rps_poc[j];
-        }
-
-        rps->num_positive_pics = rps_pics - i;
-        rps->used_by_curr_pic_s1_flag = 0x0;
-        poc = hp->pic_order_cnt;
-        for (j = i; j < rps_pics; j++) {
-            rps->delta_poc_s1_minus1[j - i] = rps_poc[j] - poc - 1;
-            rps->used_by_curr_pic_s1_flag |= rps_used[j] << (j - i);
-            poc = rps_poc[j];
-        }
-
-        hp->l_rps.num_long_term_sps  = 0;
-        hp->l_rps.num_long_term_pics = 0;
-
-        // when this flag is not present, it is inerred to 1.
-        hp->slice_hdr.flags.collocated_from_l0_flag = 1;
-        hp->h265pic_info.flags.slice_temporal_mvp_enabled_flag =
-            enc->units.raw_sps.sps_temporal_mvp_enabled_flag;
-        if (hp->h265pic_info.flags.slice_temporal_mvp_enabled_flag) {
-            if (hp->slice_hdr.slice_type == STD_VIDEO_H265_SLICE_TYPE_B)
-                hp->slice_hdr.flags.collocated_from_l0_flag = 1;
-            hp->slice_hdr.collocated_ref_idx = 0;
-        }
-
-        hp->slice_hdr.flags.num_ref_idx_active_override_flag = 0;
-        hp->ref_list_info.num_ref_idx_l0_active_minus1 = enc->units.raw_pps.num_ref_idx_l0_default_active_minus1;
-        hp->ref_list_info.num_ref_idx_l1_active_minus1 = enc->units.raw_pps.num_ref_idx_l1_default_active_minus1;
-    }
-
-    hp->h265pic_info.pShortTermRefPicSet = &hp->s_rps;
-    hp->h265pic_info.pLongTermRefPics = &hp->l_rps;
-}
-
-static int init_pic_params(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
-                           VkVideoEncodeInfoKHR *encode_info)
-{
-    int err;
-    VulkanEncodeH265Context *enc = avctx->priv_data;
-    FFVulkanEncodePicture *vp = pic->priv;
-    VulkanEncodeH265Picture *hp = pic->codec_priv;
-    VkVideoReferenceSlotInfoKHR *ref_slot;
-
-    err = vk_enc_h265_update_pic_info(avctx, pic);
-    if (err < 0)
-        return err;
-
-    hp->vkh265pic_info = (VkVideoEncodeH265PictureInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PICTURE_INFO_KHR,
-        .pNext = NULL,
-        .pNaluSliceSegmentEntries = NULL, // Filled in during setup_slices()
-        .naluSliceSegmentEntryCount = 0, // Filled in during setup_slices()
-        .pStdPictureInfo = &hp->h265pic_info,
-    };
-
-    hp->h265pic_info = (StdVideoEncodeH265PictureInfo) {
-        .flags = (StdVideoEncodeH265PictureInfoFlags) {
-            .is_reference = pic->is_reference,
-            .IrapPicFlag = pic->type == FF_HW_PICTURE_TYPE_IDR,
-            .used_for_long_term_reference = 0,
-            .discardable_flag = 0,
-            .cross_layer_bla_flag = 0,
-            .pic_output_flag = 1,
-            .no_output_of_prior_pics_flag = 0,
-            .short_term_ref_pic_set_sps_flag = 0,
-            .slice_temporal_mvp_enabled_flag = enc->units.raw_sps.sps_temporal_mvp_enabled_flag,
-            /* Reserved */
-        },
-        .pic_type = hp->pic_type,
-        .sps_video_parameter_set_id = 0,
-        .pps_seq_parameter_set_id = 0,
-        .pps_pic_parameter_set_id = 0,
-        .short_term_ref_pic_set_idx = 0,
-        .PicOrderCntVal = hp->pic_order_cnt,
-        .TemporalId = 0,
-        /* Reserved */
-        .pRefLists = NULL, // Filled in during setup_refs
-        .pShortTermRefPicSet = NULL,
-        .pLongTermRefPics = NULL,
-    };
-    encode_info->pNext = &hp->vkh265pic_info;
-
-    hp->h265dpb_info = (StdVideoEncodeH265ReferenceInfo) {
-        .flags = (StdVideoEncodeH265ReferenceInfoFlags) {
-            .used_for_long_term_reference = 0,
-            .unused_for_reference = 0,
-            /* Reserved */
-        },
-        .pic_type = hp->h265pic_info.pic_type,
-        .PicOrderCntVal = hp->h265pic_info.PicOrderCntVal,
-        .TemporalId = hp->h265pic_info.TemporalId,
-    };
-    hp->vkh265dpb_info = (VkVideoEncodeH265DpbSlotInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_KHR,
-        .pStdReferenceInfo = &hp->h265dpb_info,
-    };
-
-    vp->dpb_slot.pNext = &hp->vkh265dpb_info;
-
-    ref_slot = (VkVideoReferenceSlotInfoKHR *)encode_info->pSetupReferenceSlot;
-    ref_slot->pNext = &hp->vkh265dpb_info;
-
-    setup_refs(avctx, pic, encode_info);
-
-    setup_slices(avctx, pic);
-
-    return 0;
-}
-
-static int init_profile(AVCodecContext *avctx,
-                        VkVideoProfileInfoKHR *profile, void *pnext)
-{
-    VkResult ret;
-    VulkanEncodeH265Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext *ctx = &enc->common;
-    FFVulkanContext *s = &ctx->s;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-    VkVideoEncodeH265CapabilitiesKHR h265_caps = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_KHR,
-    };
-    VkVideoEncodeCapabilitiesKHR enc_caps = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR,
-        .pNext = &h265_caps,
-    };
-    VkVideoCapabilitiesKHR caps = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR,
-        .pNext = &enc_caps,
-    };
-
-    /* In order of preference */
-    int last_supported = AV_PROFILE_UNKNOWN;
-    static const int known_profiles[] = {
-        AV_PROFILE_HEVC_MAIN,
-        AV_PROFILE_HEVC_MAIN_10,
-        AV_PROFILE_HEVC_REXT,
-    };
-    int nb_profiles = FF_ARRAY_ELEMS(known_profiles);
-
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->frames->sw_format);
-    if (!desc)
-        return AVERROR(EINVAL);
-
-    if (s->frames->sw_format == AV_PIX_FMT_NV12)
-        nb_profiles = 1;
-    else if (s->frames->sw_format == AV_PIX_FMT_P010)
-        nb_profiles = 2;
-
-    enc->profile = (VkVideoEncodeH265ProfileInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_KHR,
-        .pNext = pnext,
-        .stdProfileIdc = ff_vk_h265_profile_to_vk(avctx->profile),
-    };
-    profile->pNext = &enc->profile;
-
-    /* Set level */
-    if (avctx->level == AV_LEVEL_UNKNOWN)
-        avctx->level = enc->common.opts.level;
-
-    /* User has explicitly specified a profile. */
-    if (avctx->profile != AV_PROFILE_UNKNOWN)
-        return 0;
-
-    av_log(avctx, AV_LOG_DEBUG, "Supported profiles:\n");
-    for (int i = 0; i < nb_profiles; i++) {
-        enc->profile.stdProfileIdc = ff_vk_h265_profile_to_vk(known_profiles[i]);
-        ret = vk->GetPhysicalDeviceVideoCapabilitiesKHR(s->hwctx->phys_dev,
-                                                        profile,
-                                                        &caps);
-        if (ret == VK_SUCCESS) {
-            av_log(avctx, AV_LOG_DEBUG, "    %s\n",
-                   avcodec_profile_name(avctx->codec_id, known_profiles[i]));
-            last_supported = known_profiles[i];
-        }
-    }
-
-    if (last_supported == AV_PROFILE_UNKNOWN) {
-        av_log(avctx, AV_LOG_ERROR, "No supported profiles for given format\n");
-        return AVERROR(ENOTSUP);
-    }
-
-    enc->profile.stdProfileIdc = ff_vk_h265_profile_to_vk(last_supported);
-    av_log(avctx, AV_LOG_VERBOSE, "Using profile %s\n",
-           avcodec_profile_name(avctx->codec_id, last_supported));
-    avctx->profile = last_supported;
-
-    return 0;
-}
-
-static int init_enc_options(AVCodecContext *avctx)
-{
-    VulkanEncodeH265Context *enc = avctx->priv_data;
-
-    if (avctx->rc_buffer_size)
-        enc->hrd_buffer_size = avctx->rc_buffer_size;
-    else if (avctx->rc_max_rate > 0)
-        enc->hrd_buffer_size = avctx->rc_max_rate;
-    else
-        enc->hrd_buffer_size = avctx->bit_rate;
-
-    if (avctx->rc_initial_buffer_occupancy) {
-        if (avctx->rc_initial_buffer_occupancy > enc->hrd_buffer_size) {
-            av_log(avctx, AV_LOG_ERROR, "Invalid RC buffer settings: "
-                                        "must have initial buffer size (%d) <= "
-                                        "buffer size (%"PRId64").\n",
-                   avctx->rc_initial_buffer_occupancy, enc->hrd_buffer_size);
-            return AVERROR(EINVAL);
-        }
-        enc->initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
-    } else {
-        enc->initial_buffer_fullness = enc->hrd_buffer_size * 3 / 4;
-    }
-
-    if (enc->common.opts.rc_mode == VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
-        enc->fixed_qp_p = av_clip(enc->common.opts.qp,
-                                  enc->caps.minQp, enc->caps.maxQp);
-
-        if (avctx->i_quant_factor > 0.0)
-            enc->fixed_qp_idr = av_clip((avctx->i_quant_factor * enc->fixed_qp_p +
-                                         avctx->i_quant_offset) + 0.5,
-                                        enc->caps.minQp, enc->caps.maxQp);
-        else
-            enc->fixed_qp_idr = enc->fixed_qp_p;
-
-        if (avctx->b_quant_factor > 0.0)
-            enc->fixed_qp_b = av_clip((avctx->b_quant_factor * enc->fixed_qp_p +
-                                       avctx->b_quant_offset) + 0.5,
-                                      enc->caps.minQp, enc->caps.maxQp);
-        else
-            enc->fixed_qp_b = enc->fixed_qp_p;
-
-        av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
-               "%d / %d / %d for IDR- / P- / B-frames.\n",
-               enc->fixed_qp_idr, enc->fixed_qp_p, enc->fixed_qp_b);
-    } else {
-        enc->fixed_qp_idr = 26;
-        enc->fixed_qp_p = 26;
-        enc->fixed_qp_b = 26;
-    }
-
-    return 0;
-}
-
-static av_cold int init_sequence_headers(AVCodecContext *avctx)
-{
-    int err;
-    VulkanEncodeH265Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext *ctx = &enc->common;
-    FFHWBaseEncodeContext *base_ctx = &ctx->base;
-
-    FFHWBaseEncodeH265 *units = &enc->units;
-    FFHWBaseEncodeH265Opts *unit_opts = &enc->unit_opts;
-
-    int max_ctb_size;
-    unsigned min_tb_size;
-    unsigned max_tb_size;
-    unsigned max_transform_hierarchy;
-
-    unit_opts->tier = enc->common.opts.tier;
-    unit_opts->fixed_qp_idr = enc->fixed_qp_idr;
-    unit_opts->cu_qp_delta_enabled_flag = enc->common.opts.rc_mode != VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
-
-    unit_opts->nb_slices = 1;
-
-    unit_opts->slice_block_rows = (avctx->height + base_ctx->slice_block_height - 1) /
-                                  base_ctx->slice_block_height;
-    unit_opts->slice_block_cols = (avctx->width  + base_ctx->slice_block_width  - 1) /
-                                  base_ctx->slice_block_width;
-
-    /* cabac already set via an option */
-    /* fixed_qp_idr initialized in init_enc_options() */
-    /* hrd_buffer_size initialized in init_enc_options() */
-    /* initial_buffer_fullness initialized in init_enc_options() */
-
-    err = ff_hw_base_encode_init_params_h265(&enc->common.base, avctx,
-                                             units, unit_opts);
-    if (err < 0)
-        return err;
-
-    units->raw_sps.sample_adaptive_offset_enabled_flag =
-      !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG_SET_BIT_KHR);
-    units->raw_pps.transform_skip_enabled_flag =
-      !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_TRANSFORM_SKIP_ENABLED_FLAG_SET_BIT_KHR);
-
-    max_ctb_size = 16;
-
-    /* coding blocks from 8x8 to max CTB size. */
-    if (enc->caps.ctbSizes & VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_KHR)
-        max_ctb_size = 64;
-    else if (enc->caps.ctbSizes & VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_KHR)
-        max_ctb_size = 32;
-
-    min_tb_size = 0;
-    max_tb_size = 0;
-    if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_KHR)
-        min_tb_size = 4;
-    else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_KHR)
-        min_tb_size = 8;
-    else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_KHR)
-        min_tb_size = 16;
-    else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR)
-        min_tb_size = 32;
-
-    if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR)
-        max_tb_size = 32;
-    else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_KHR)
-        max_tb_size = 16;
-    else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_KHR)
-        max_tb_size = 8;
-    else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_KHR)
-        max_tb_size = 4;
-
-    units->raw_sps.log2_min_luma_coding_block_size_minus3 = 0;
-    units->raw_sps.log2_diff_max_min_luma_coding_block_size = av_log2(max_ctb_size) - 3;
-    units->raw_sps.log2_min_luma_transform_block_size_minus2 = av_log2(min_tb_size) - 2;
-    units->raw_sps.log2_diff_max_min_luma_transform_block_size = av_log2(max_tb_size) - av_log2(min_tb_size);
-
-    max_transform_hierarchy = av_log2(max_ctb_size) - av_log2(min_tb_size);
-    units->raw_sps.max_transform_hierarchy_depth_intra = max_transform_hierarchy;
-    units->raw_sps.max_transform_hierarchy_depth_intra = max_transform_hierarchy;
-
-    units->raw_sps.vui.bitstream_restriction_flag = 0;
-    units->raw_sps.vui.max_bytes_per_pic_denom = 2;
-    units->raw_sps.vui.max_bits_per_min_cu_denom = 1;
-
-    units->raw_sps.sps_temporal_mvp_enabled_flag = 0;
-
-    if (base_ctx->gop_size & base_ctx->gop_size - 1 == 0)
-        units->raw_sps.log2_max_pic_order_cnt_lsb_minus4 = FFMAX(av_log2(base_ctx->gop_size) - 4, 0);
-    else
-        units->raw_sps.log2_max_pic_order_cnt_lsb_minus4 = FFMAX(av_log2(base_ctx->gop_size) - 3, 0);
-
-    return 0;
-}
-
-typedef struct VulkanH265Units {
-    StdVideoH265SequenceParameterSet    sps;
-    StdVideoH265ShortTermRefPicSet      str[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE];
-    StdVideoH265LongTermRefPicsSps      ltr;
-    StdVideoH265ProfileTierLevel        ptl_sps;
-    StdVideoH265DecPicBufMgr            dpbm_sps;
-
-    StdVideoH265HrdParameters           vui_header_sps;
-    StdVideoH265SequenceParameterSetVui vui_sps;
-
-    StdVideoH265SubLayerHrdParameters   slhdrnal[HEVC_MAX_SUB_LAYERS];
-    StdVideoH265SubLayerHrdParameters   slhdrvcl[HEVC_MAX_SUB_LAYERS];
-
-    StdVideoH265PictureParameterSet     pps;
-    StdVideoH265ScalingLists            pps_scaling;
-
-    StdVideoH265VideoParameterSet       vps;
-    StdVideoH265ProfileTierLevel        ptl_vps;
-    StdVideoH265DecPicBufMgr            dpbm_vps;
-    StdVideoH265HrdParameters           vui_header_vps;
-} VulkanH265Units;
-
-static av_cold int base_unit_to_vk(AVCodecContext *avctx,
-                                   VulkanH265Units *vk_units)
-{
-    VulkanEncodeH265Context *enc = avctx->priv_data;
-
-    H265RawSPS                           *sps = &enc->units.raw_sps;
-    StdVideoH265SequenceParameterSet   *vksps = &vk_units->sps;
-    StdVideoH265ShortTermRefPicSet       *str =  vk_units->str;
-    StdVideoH265LongTermRefPicsSps       *ltr = &vk_units->ltr;
-    StdVideoH265ProfileTierLevel         *ptl_sps = &vk_units->ptl_sps;
-    StdVideoH265DecPicBufMgr            *dpbm_sps = &vk_units->dpbm_sps;
-
-    StdVideoH265HrdParameters           *vui_header_sps = &vk_units->vui_header_sps;
-    StdVideoH265SequenceParameterSetVui *vui_sps = &vk_units->vui_sps;
-
-    StdVideoH265SubLayerHrdParameters *slhdrnal = vk_units->slhdrnal;
-    StdVideoH265SubLayerHrdParameters *slhdrvcl = vk_units->slhdrvcl;
-
-    H265RawPPS                          *pps = &enc->units.raw_pps;
-    StdVideoH265PictureParameterSet   *vkpps = &vk_units->pps;
-
-    H265RawVPS                           *vps = &enc->units.raw_vps;
-    StdVideoH265VideoParameterSet      *vkvps = &vk_units->vps;
-    StdVideoH265ProfileTierLevel     *ptl_vps = &vk_units->ptl_vps;
-    StdVideoH265DecPicBufMgr        *dpbm_vps = &vk_units->dpbm_vps;
-    StdVideoH265HrdParameters *vui_header_vps = &vk_units->vui_header_vps;
-
-    /* SPS */
-    for (int i = 0; i < HEVC_MAX_SUB_LAYERS; i++) {
-        memcpy(&slhdrnal[i], &sps->vui.hrd_parameters.nal_sub_layer_hrd_parameters[i], sizeof(*slhdrnal));
-        memcpy(&slhdrvcl[i], &sps->vui.hrd_parameters.vcl_sub_layer_hrd_parameters[i], sizeof(*slhdrvcl));
-        slhdrnal[i].cbr_flag = 0x0;
-        slhdrvcl[i].cbr_flag = 0x0;
-        for (int j = 0; j < HEVC_MAX_CPB_CNT; j++) {
-            slhdrnal[i].cbr_flag |= sps->vui.hrd_parameters.nal_sub_layer_hrd_parameters[i].cbr_flag[j] << i;
-            slhdrvcl[i].cbr_flag |= sps->vui.hrd_parameters.vcl_sub_layer_hrd_parameters[i].cbr_flag[j] << i;
-        }
-    }
-
-    *vui_header_sps = (StdVideoH265HrdParameters) {
-        .flags = (StdVideoH265HrdFlags) {
-            .nal_hrd_parameters_present_flag = sps->vui.hrd_parameters.nal_hrd_parameters_present_flag,
-            .vcl_hrd_parameters_present_flag = sps->vui.hrd_parameters.vcl_hrd_parameters_present_flag,
-            .sub_pic_hrd_params_present_flag = sps->vui.hrd_parameters.sub_pic_hrd_params_present_flag,
-            .sub_pic_cpb_params_in_pic_timing_sei_flag = sps->vui.hrd_parameters.sub_pic_cpb_params_in_pic_timing_sei_flag,
-            .fixed_pic_rate_general_flag = 0x0,
-            .fixed_pic_rate_within_cvs_flag = 0x0,
-            .low_delay_hrd_flag = 0x0,
-        },
-        .tick_divisor_minus2 = sps->vui.hrd_parameters.tick_divisor_minus2,
-        .du_cpb_removal_delay_increment_length_minus1 = sps->vui.hrd_parameters.du_cpb_removal_delay_increment_length_minus1,
-        .dpb_output_delay_du_length_minus1 = sps->vui.hrd_parameters.dpb_output_delay_du_length_minus1,
-        .bit_rate_scale = sps->vui.hrd_parameters.bit_rate_scale,
-        .cpb_size_scale = sps->vui.hrd_parameters.cpb_size_scale,
-        .cpb_size_du_scale = sps->vui.hrd_parameters.cpb_size_du_scale,
-        .initial_cpb_removal_delay_length_minus1 = sps->vui.hrd_parameters.initial_cpb_removal_delay_length_minus1,
-        .au_cpb_removal_delay_length_minus1 = sps->vui.hrd_parameters.au_cpb_removal_delay_length_minus1,
-        .dpb_output_delay_length_minus1 = sps->vui.hrd_parameters.dpb_output_delay_length_minus1,
-        /* Reserved - 3*16 bits */
-        .pSubLayerHrdParametersNal = slhdrnal,
-        .pSubLayerHrdParametersVcl = slhdrvcl,
-    };
-
-    for (int i = 0; i < HEVC_MAX_SUB_LAYERS; i++) {
-        vui_header_sps->flags.fixed_pic_rate_general_flag |= sps->vui.hrd_parameters.fixed_pic_rate_general_flag[i] << i;
-        vui_header_sps->flags.fixed_pic_rate_within_cvs_flag |= sps->vui.hrd_parameters.fixed_pic_rate_within_cvs_flag[i] << i;
-        vui_header_sps->flags.low_delay_hrd_flag |= sps->vui.hrd_parameters.low_delay_hrd_flag[i] << i;
-    }
-
-    for (int i = 0; i < STD_VIDEO_H265_SUBLAYERS_LIST_SIZE; i++) {
-        dpbm_sps->max_latency_increase_plus1[i] = sps->sps_max_latency_increase_plus1[i];
-        dpbm_sps->max_dec_pic_buffering_minus1[i] = sps->sps_max_dec_pic_buffering_minus1[i];
-        dpbm_sps->max_num_reorder_pics[i] = sps->sps_max_num_reorder_pics[i];
-    }
-
-    *ptl_sps = (StdVideoH265ProfileTierLevel) {
-        .flags = (StdVideoH265ProfileTierLevelFlags) {
-            .general_tier_flag = sps->profile_tier_level.general_tier_flag,
-            .general_progressive_source_flag = sps->profile_tier_level.general_progressive_source_flag,
-            .general_interlaced_source_flag = sps->profile_tier_level.general_interlaced_source_flag,
-            .general_non_packed_constraint_flag = sps->profile_tier_level.general_non_packed_constraint_flag,
-            .general_frame_only_constraint_flag = sps->profile_tier_level.general_frame_only_constraint_flag,
-        },
-        .general_profile_idc = ff_vk_h265_profile_to_vk(sps->profile_tier_level.general_profile_idc),
-        .general_level_idc = ff_vk_h265_level_to_vk(sps->profile_tier_level.general_level_idc),
-    };
-
-    for (int i = 0; i < STD_VIDEO_H265_MAX_SHORT_TERM_REF_PIC_SETS; i++) {
-        const H265RawSTRefPicSet *st_rps = &sps->st_ref_pic_set[i];
-
-        str[i] = (StdVideoH265ShortTermRefPicSet) {
-            .flags = (StdVideoH265ShortTermRefPicSetFlags) {
-                .inter_ref_pic_set_prediction_flag = st_rps->inter_ref_pic_set_prediction_flag,
-                .delta_rps_sign = st_rps->delta_rps_sign,
-            },
-            .delta_idx_minus1 = st_rps->delta_idx_minus1,
-            .use_delta_flag = 0x0,
-            .abs_delta_rps_minus1 = st_rps->abs_delta_rps_minus1,
-            .used_by_curr_pic_flag    = 0x0,
-            .used_by_curr_pic_s0_flag = 0x0,
-            .used_by_curr_pic_s1_flag = 0x0,
-            /* Reserved */
-            /* Reserved */
-            /* Reserved */
-            .num_negative_pics = st_rps->num_negative_pics,
-            .num_positive_pics = st_rps->num_positive_pics,
-        };
-
-        for (int j = 0; j < HEVC_MAX_REFS; j++) {
-            str[i].use_delta_flag |= st_rps->use_delta_flag[j] << i;
-            str[i].used_by_curr_pic_flag |= st_rps->used_by_curr_pic_flag[j] << i;
-            str[i].used_by_curr_pic_s0_flag |= st_rps->used_by_curr_pic_s0_flag[j] << i;
-            str[i].used_by_curr_pic_s1_flag |= st_rps->used_by_curr_pic_s1_flag[j] << i;
-            str[i].delta_poc_s0_minus1[j] = st_rps->delta_poc_s0_minus1[j];
-            str[i].delta_poc_s1_minus1[j] = st_rps->delta_poc_s1_minus1[j];
-        }
-    }
-
-    ltr->used_by_curr_pic_lt_sps_flag = 0;
-    for (int i = 0; i < STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS; i++) {
-        ltr->used_by_curr_pic_lt_sps_flag |= sps->lt_ref_pic_poc_lsb_sps[i] << i;
-        ltr->lt_ref_pic_poc_lsb_sps[i] = sps->lt_ref_pic_poc_lsb_sps[i];
-    }
-
-    *vksps = (StdVideoH265SequenceParameterSet) {
-        .flags = (StdVideoH265SpsFlags) {
-            .sps_temporal_id_nesting_flag = sps->sps_temporal_id_nesting_flag,
-            .separate_colour_plane_flag = sps->separate_colour_plane_flag,
-            .conformance_window_flag = sps->conformance_window_flag,
-            .sps_sub_layer_ordering_info_present_flag = sps->sps_sub_layer_ordering_info_present_flag,
-            .scaling_list_enabled_flag = sps->scaling_list_enabled_flag,
-            .sps_scaling_list_data_present_flag = sps->sps_scaling_list_data_present_flag,
-            .amp_enabled_flag = sps->amp_enabled_flag,
-            .sample_adaptive_offset_enabled_flag = sps->sample_adaptive_offset_enabled_flag,
-            .pcm_enabled_flag = sps->pcm_enabled_flag,
-            .pcm_loop_filter_disabled_flag = sps->pcm_loop_filter_disabled_flag,
-            .long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag,
-            .sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag,
-            .strong_intra_smoothing_enabled_flag = sps->strong_intra_smoothing_enabled_flag,
-            .vui_parameters_present_flag = sps->vui_parameters_present_flag,
-            .sps_extension_present_flag = sps->sps_extension_present_flag,
-            .sps_range_extension_flag = sps->sps_range_extension_flag,
-            .transform_skip_rotation_enabled_flag = sps->transform_skip_rotation_enabled_flag,
-            .transform_skip_context_enabled_flag = sps->transform_skip_context_enabled_flag,
-            .implicit_rdpcm_enabled_flag = sps->implicit_rdpcm_enabled_flag,
-            .explicit_rdpcm_enabled_flag = sps->explicit_rdpcm_enabled_flag,
-            .extended_precision_processing_flag = sps->extended_precision_processing_flag,
-            .intra_smoothing_disabled_flag = sps->intra_smoothing_disabled_flag,
-            .high_precision_offsets_enabled_flag = sps->high_precision_offsets_enabled_flag,
-            .persistent_rice_adaptation_enabled_flag = sps->persistent_rice_adaptation_enabled_flag,
-            .cabac_bypass_alignment_enabled_flag = sps->cabac_bypass_alignment_enabled_flag,
-            .sps_scc_extension_flag = sps->sps_scc_extension_flag,
-            .sps_curr_pic_ref_enabled_flag = sps->sps_curr_pic_ref_enabled_flag,
-            .palette_mode_enabled_flag = sps->palette_mode_enabled_flag,
-            .sps_palette_predictor_initializers_present_flag = sps->sps_palette_predictor_initializer_present_flag,
-            .intra_boundary_filtering_disabled_flag = sps->intra_boundary_filtering_disable_flag,
-        },
-        .chroma_format_idc = sps->chroma_format_idc,
-        .pic_width_in_luma_samples = sps->pic_width_in_luma_samples,
-        .pic_height_in_luma_samples = sps->pic_height_in_luma_samples,
-        .sps_video_parameter_set_id = sps->sps_video_parameter_set_id,
-        .sps_max_sub_layers_minus1 = sps->sps_max_sub_layers_minus1,
-        .sps_seq_parameter_set_id = sps->sps_seq_parameter_set_id,
-        .bit_depth_luma_minus8 = sps->bit_depth_luma_minus8,
-        .bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8,
-        .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4,
-        .log2_min_luma_coding_block_size_minus3 = sps->log2_min_luma_coding_block_size_minus3,
-        .log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_luma_coding_block_size,
-        .log2_min_luma_transform_block_size_minus2 = sps->log2_min_luma_transform_block_size_minus2,
-        .log2_diff_max_min_luma_transform_block_size = sps->log2_diff_max_min_luma_transform_block_size,
-        .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter,
-        .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra,
-        .num_short_term_ref_pic_sets = sps->num_short_term_ref_pic_sets,
-        .num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps,
-        .pcm_sample_bit_depth_luma_minus1 = sps->pcm_sample_bit_depth_luma_minus1,
-        .pcm_sample_bit_depth_chroma_minus1 = sps->pcm_sample_bit_depth_chroma_minus1,
-        .log2_min_pcm_luma_coding_block_size_minus3 = sps->log2_min_pcm_luma_coding_block_size_minus3,
-        .log2_diff_max_min_pcm_luma_coding_block_size = sps->log2_diff_max_min_pcm_luma_coding_block_size,
-        /* Reserved */
-        /* Reserved */
-        .palette_max_size = sps->palette_max_size,
-        .delta_palette_max_predictor_size = sps->delta_palette_max_predictor_size,
-        .motion_vector_resolution_control_idc = sps->motion_vector_resolution_control_idc,
-        .sps_num_palette_predictor_initializers_minus1 = sps->sps_num_palette_predictor_initializer_minus1,
-        .conf_win_left_offset = sps->conf_win_left_offset,
-        .conf_win_right_offset = sps->conf_win_right_offset,
-        .conf_win_top_offset = sps->conf_win_top_offset,
-        .conf_win_bottom_offset = sps->conf_win_bottom_offset,
-        .pProfileTierLevel = ptl_sps,
-        .pDecPicBufMgr = dpbm_sps,
-        .pScalingLists = NULL,
-        .pShortTermRefPicSet = str,
-        .pLongTermRefPicsSps = ltr,
-        .pSequenceParameterSetVui = vui_sps,
-        .pPredictorPaletteEntries = NULL,
-    };
-
-    /* PPS */
-    *vkpps = (StdVideoH265PictureParameterSet) {
-        .flags = (StdVideoH265PpsFlags) {
-            .dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag,
-            .output_flag_present_flag = pps->output_flag_present_flag,
-            .sign_data_hiding_enabled_flag = pps->sign_data_hiding_enabled_flag,
-            .cabac_init_present_flag = pps->cabac_init_present_flag,
-            .constrained_intra_pred_flag = pps->constrained_intra_pred_flag,
-            .transform_skip_enabled_flag = pps->transform_skip_enabled_flag,
-            .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag,
-            .pps_slice_chroma_qp_offsets_present_flag = pps->pps_slice_chroma_qp_offsets_present_flag,
-            .weighted_pred_flag = pps->weighted_pred_flag,
-            .weighted_bipred_flag = pps->weighted_bipred_flag,
-            .transquant_bypass_enabled_flag = pps->transquant_bypass_enabled_flag,
-            .tiles_enabled_flag = pps->tiles_enabled_flag,
-            .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag,
-            .uniform_spacing_flag = pps->uniform_spacing_flag,
-            .loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag,
-            .pps_loop_filter_across_slices_enabled_flag = pps->pps_loop_filter_across_slices_enabled_flag,
-            .deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag,
-            .deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag,
-            .pps_deblocking_filter_disabled_flag = pps->pps_deblocking_filter_disabled_flag,
-            .pps_scaling_list_data_present_flag = pps->pps_scaling_list_data_present_flag,
-            .lists_modification_present_flag = pps->lists_modification_present_flag,
-            .slice_segment_header_extension_present_flag = pps->slice_segment_header_extension_present_flag,
-            .pps_extension_present_flag = pps->pps_extension_present_flag,
-            .cross_component_prediction_enabled_flag = pps->cross_component_prediction_enabled_flag,
-            .chroma_qp_offset_list_enabled_flag = pps->chroma_qp_offset_list_enabled_flag,
-            .pps_curr_pic_ref_enabled_flag = pps->pps_curr_pic_ref_enabled_flag,
-            .residual_adaptive_colour_transform_enabled_flag = pps->residual_adaptive_colour_transform_enabled_flag,
-            .pps_slice_act_qp_offsets_present_flag = pps->pps_slice_act_qp_offsets_present_flag,
-            .pps_palette_predictor_initializers_present_flag = pps->pps_palette_predictor_initializer_present_flag,
-            .monochrome_palette_flag = pps->monochrome_palette_flag,
-            .pps_range_extension_flag = pps->pps_range_extension_flag,
-        },
-        .pps_pic_parameter_set_id = pps->pps_pic_parameter_set_id,
-        .pps_seq_parameter_set_id = pps->pps_seq_parameter_set_id,
-        .sps_video_parameter_set_id = sps->sps_video_parameter_set_id,
-        .num_extra_slice_header_bits = pps->num_extra_slice_header_bits,
-        .num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active_minus1,
-        .num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active_minus1,
-        .init_qp_minus26 = pps->init_qp_minus26,
-        .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth,
-        .pps_cb_qp_offset = pps->pps_cb_qp_offset,
-        .pps_cr_qp_offset = pps->pps_cr_qp_offset,
-        .pps_beta_offset_div2 = pps->pps_beta_offset_div2,
-        .pps_tc_offset_div2 = pps->pps_tc_offset_div2,
-        .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level_minus2,
-        .log2_max_transform_skip_block_size_minus2 = pps->log2_max_transform_skip_block_size_minus2,
-        .diff_cu_chroma_qp_offset_depth = pps->diff_cu_chroma_qp_offset_depth,
-        .chroma_qp_offset_list_len_minus1 = pps->chroma_qp_offset_list_len_minus1,
-        .log2_sao_offset_scale_luma = pps->log2_sao_offset_scale_luma,
-        .log2_sao_offset_scale_chroma = pps->log2_sao_offset_scale_chroma,
-        .pps_act_y_qp_offset_plus5 = pps->pps_act_y_qp_offset_plus5,
-        .pps_act_cb_qp_offset_plus5 = pps->pps_act_cb_qp_offset_plus5,
-        .pps_act_cr_qp_offset_plus3 = pps->pps_act_cr_qp_offset_plus3,
-        .pps_num_palette_predictor_initializers = pps->pps_num_palette_predictor_initializer,
-        .luma_bit_depth_entry_minus8 = pps->luma_bit_depth_entry_minus8,
-        .chroma_bit_depth_entry_minus8 = pps->chroma_bit_depth_entry_minus8,
-        .num_tile_columns_minus1 = pps->num_tile_columns_minus1,
-        .num_tile_rows_minus1 = pps->num_tile_rows_minus1,
-        .pScalingLists = NULL,
-        .pPredictorPaletteEntries = NULL,
-    };
-
-    for (int i = 0; i < pps->num_tile_columns_minus1; i++)
-        vkpps->column_width_minus1[i] = pps->column_width_minus1[i];
-
-    for (int i = 0; i < pps->num_tile_rows_minus1; i++)
-        vkpps->row_height_minus1[i] = pps->row_height_minus1[i];
-
-    for (int i = 0; i <= pps->chroma_qp_offset_list_len_minus1; i++) {
-        vkpps->cb_qp_offset_list[i] = pps->cb_qp_offset_list[i];
-        vkpps->cr_qp_offset_list[i] = pps->cr_qp_offset_list[i];
-    }
-
-    /* VPS */
-    for (int i = 0; i < STD_VIDEO_H265_SUBLAYERS_LIST_SIZE; i++) {
-        dpbm_vps->max_latency_increase_plus1[i] = vps->vps_max_latency_increase_plus1[i];
-        dpbm_vps->max_dec_pic_buffering_minus1[i] = vps->vps_max_dec_pic_buffering_minus1[i];
-        dpbm_vps->max_num_reorder_pics[i] = vps->vps_max_num_reorder_pics[i];
-    }
-
-    *ptl_vps = (StdVideoH265ProfileTierLevel) {
-        .flags = (StdVideoH265ProfileTierLevelFlags) {
-            .general_tier_flag = vps->profile_tier_level.general_tier_flag,
-            .general_progressive_source_flag = vps->profile_tier_level.general_progressive_source_flag,
-            .general_interlaced_source_flag = vps->profile_tier_level.general_interlaced_source_flag,
-            .general_non_packed_constraint_flag = vps->profile_tier_level.general_non_packed_constraint_flag,
-            .general_frame_only_constraint_flag = vps->profile_tier_level.general_frame_only_constraint_flag,
-        },
-        .general_profile_idc = ff_vk_h265_profile_to_vk(vps->profile_tier_level.general_profile_idc),
-        .general_level_idc = ff_vk_h265_level_to_vk(vps->profile_tier_level.general_level_idc),
-    };
-
-    *vkvps = (StdVideoH265VideoParameterSet) {
-        .flags = (StdVideoH265VpsFlags) {
-            .vps_temporal_id_nesting_flag = vps->vps_temporal_id_nesting_flag,
-            .vps_sub_layer_ordering_info_present_flag = vps->vps_sub_layer_ordering_info_present_flag,
-            .vps_timing_info_present_flag = vps->vps_timing_info_present_flag,
-            .vps_poc_proportional_to_timing_flag = vps->vps_poc_proportional_to_timing_flag,
-        },
-        .vps_video_parameter_set_id = vps->vps_video_parameter_set_id,
-        .vps_max_sub_layers_minus1 = vps->vps_max_sub_layers_minus1,
-        /* Reserved */
-        /* Reserved */
-        .vps_num_units_in_tick = vps->vps_num_units_in_tick,
-        .vps_time_scale = vps->vps_time_scale,
-        .vps_num_ticks_poc_diff_one_minus1 = vps->vps_num_ticks_poc_diff_one_minus1,
-        /* Reserved */
-        .pDecPicBufMgr = dpbm_vps,
-        .pHrdParameters = vui_header_vps,
-        .pProfileTierLevel = ptl_vps,
-    };
-
-    return 0;
-}
-
-static int create_session_params(AVCodecContext *avctx)
-{
-    int err;
-    VulkanEncodeH265Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext *ctx = &enc->common;
-    FFVulkanContext *s = &ctx->s;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-
-    VulkanH265Units vk_units = { 0 };
-
-    VkVideoEncodeH265SessionParametersAddInfoKHR h265_params_info;
-    VkVideoEncodeH265SessionParametersCreateInfoKHR h265_params;
-
-    /* Convert it to Vulkan */
-    err = base_unit_to_vk(avctx, &vk_units);
-    if (err < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to convert SPS/PPS units to Vulkan: %s\n",
-               av_err2str(err));
-        return err;
-    }
-
-    /* Destroy the session params */
-    if (ctx->session_params)
-        vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
-                                             ctx->session_params,
-                                             s->hwctx->alloc);
-
-    h265_params_info = (VkVideoEncodeH265SessionParametersAddInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR,
-        .pStdSPSs = &vk_units.sps,
-        .stdSPSCount = 1,
-        .pStdPPSs = &vk_units.pps,
-        .stdPPSCount = 1,
-        .pStdVPSs = &vk_units.vps,
-        .stdVPSCount = 1,
-    };
-    h265_params = (VkVideoEncodeH265SessionParametersCreateInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR,
-        .maxStdSPSCount = 1,
-        .maxStdPPSCount = 1,
-        .maxStdVPSCount = 1,
-        .pParametersAddInfo = &h265_params_info,
-    };
-
-    return ff_vulkan_encode_create_session_params(avctx, ctx, &h265_params);
-}
-
-static int parse_feedback_units(AVCodecContext *avctx,
-                                const uint8_t *data, size_t size,
-                                int sps_override, int pps_override)
-{
-    int err;
-    VulkanEncodeH265Context *enc = avctx->priv_data;
-
-    CodedBitstreamContext *cbs;
-    CodedBitstreamFragment au = { 0 };
-
-    err = ff_cbs_init(&cbs, AV_CODEC_ID_HEVC, avctx);
-    if (err < 0)
-        return err;
-
-    err = ff_cbs_read(cbs, &au, NULL, data, size);
-    if (err < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to parse feedback units, bad drivers: %s\n",
-               av_err2str(err));
-        goto fail;
-    }
-
-    if (sps_override) {
-        for (int i = 0; i < au.nb_units; i++) {
-            if (au.units[i].type == HEVC_NAL_SPS) {
-                H265RawSPS *sps = au.units[i].content;
-                enc->units.raw_sps.pic_width_in_luma_samples = sps->pic_width_in_luma_samples;
-                enc->units.raw_sps.pic_height_in_luma_samples = sps->pic_height_in_luma_samples;
-                enc->units.raw_sps.log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_luma_coding_block_size;
-                enc->units.raw_sps.max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter;
-                enc->units.raw_sps.max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra;
-            }
-        }
-    }
-
-    /* If PPS has an override, just copy it entirely. */
-    if (pps_override) {
-        for (int i = 0; i < au.nb_units; i++) {
-            if (au.units[i].type == HEVC_NAL_PPS) {
-                H265RawPPS *pps = au.units[i].content;
-                memcpy(&enc->units.raw_pps, pps, sizeof(*pps));
-                enc->fixed_qp_idr = pps->init_qp_minus26 + 26;
-                break;
-            }
-        }
-    }
-
-    err = 0;
-fail:
-    ff_cbs_fragment_free(&au);
-    ff_cbs_close(&cbs);
-
-    return err;
-}
-
-static int init_base_units(AVCodecContext *avctx)
-{
-    int err;
-    VkResult ret;
-    VulkanEncodeH265Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext *ctx = &enc->common;
-    FFVulkanContext *s = &ctx->s;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-
-    VkVideoEncodeH265SessionParametersGetInfoKHR h265_params_info;
-    VkVideoEncodeSessionParametersGetInfoKHR params_info;
-    VkVideoEncodeH265SessionParametersFeedbackInfoKHR h265_params_feedback;
-    VkVideoEncodeSessionParametersFeedbackInfoKHR params_feedback;
-
-    void *data = NULL;
-    size_t data_size = 0;
-
-    /* Generate SPS/PPS unit info */
-    err = init_sequence_headers(avctx);
-    if (err < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to initialize SPS/PPS units: %s\n",
-               av_err2str(err));
-        return err;
-    }
-
-    /* Create session parameters from them */
-    err = create_session_params(avctx);
-    if (err < 0)
-        return err;
-
-    h265_params_info = (VkVideoEncodeH265SessionParametersGetInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_GET_INFO_KHR,
-        .writeStdSPS = 1,
-        .writeStdPPS = 1,
-        .writeStdVPS = 1,
-        .stdSPSId = enc->units.raw_sps.sps_seq_parameter_set_id,
-        .stdPPSId = enc->units.raw_pps.pps_pic_parameter_set_id,
-        .stdVPSId = enc->units.raw_vps.vps_video_parameter_set_id,
-    };
-    params_info = (VkVideoEncodeSessionParametersGetInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_GET_INFO_KHR,
-        .pNext = &h265_params_info,
-        .videoSessionParameters = ctx->session_params,
-    };
-
-    h265_params_feedback = (VkVideoEncodeH265SessionParametersFeedbackInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_FEEDBACK_INFO_KHR,
-    };
-    params_feedback = (VkVideoEncodeSessionParametersFeedbackInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_FEEDBACK_INFO_KHR,
-        .pNext = &h265_params_feedback,
-    };
-
-    ret = vk->GetEncodedVideoSessionParametersKHR(s->hwctx->act_dev, &params_info,
-                                                  &params_feedback,
-                                                  &data_size, data);
-    if (ret == VK_INCOMPLETE ||
-        (ret == VK_SUCCESS) && (data_size > 0)) {
-        data = av_mallocz(data_size);
-        if (!data)
-            return AVERROR(ENOMEM);
-    } else {
-        av_log(avctx, AV_LOG_ERROR, "Unable to get feedback for H.265 units = %"SIZE_SPECIFIER"\n", data_size);
-        return err;
-    }
-
-    ret = vk->GetEncodedVideoSessionParametersKHR(s->hwctx->act_dev, &params_info,
-                                                  &params_feedback,
-                                                  &data_size, data);
-    if (ret != VK_SUCCESS) {
-        av_log(avctx, AV_LOG_ERROR, "Error writing feedback units\n");
-        return err;
-    }
-
-    av_log(avctx, AV_LOG_VERBOSE, "Feedback units written, overrides: %i (SPS: %i PPS: %i VPS: %i)\n",
-           params_feedback.hasOverrides,
-           h265_params_feedback.hasStdSPSOverrides,
-           h265_params_feedback.hasStdPPSOverrides,
-           h265_params_feedback.hasStdVPSOverrides);
-
-    params_feedback.hasOverrides = 1;
-    h265_params_feedback.hasStdSPSOverrides = 1;
-    h265_params_feedback.hasStdPPSOverrides = 1;
-
-    /* No need to sync any overrides */
-    if (!params_feedback.hasOverrides)
-        return 0;
-
-    /* Parse back tne units and override */
-    err = parse_feedback_units(avctx, data, data_size,
-                               h265_params_feedback.hasStdSPSOverrides,
-                               h265_params_feedback.hasStdPPSOverrides);
-    if (err < 0)
-        return err;
-
-    /* Create final session parameters */
-    err = create_session_params(avctx);
-    if (err < 0)
-        return err;
-
-    return 0;
-}
-
-static int vulkan_encode_h265_add_nal(AVCodecContext *avctx,
-                                      CodedBitstreamFragment *au,
-                                      void *nal_unit)
-{
-    H265RawNALUnitHeader *header = nal_unit;
-
-    int err = ff_cbs_insert_unit_content(au, -1,
-                                         header->nal_unit_type, nal_unit, NULL);
-    if (err < 0)
-        av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: "
-               "type = %d.\n", header->nal_unit_type);
-
-    return err;
-}
-
-static int write_access_unit(AVCodecContext *avctx,
-                             uint8_t *data, size_t *data_len,
-                             CodedBitstreamFragment *au)
-{
-    VulkanEncodeH265Context *enc = avctx->priv_data;
-
-    int err = ff_cbs_write_fragment_data(enc->cbs, au);
-    if (err < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n");
-        return err;
-    }
-
-    if (*data_len < au->data_size) {
-        av_log(avctx, AV_LOG_ERROR, "Access unit too large: %zu < %zu.\n",
-               *data_len, au->data_size);
-        return AVERROR(ENOSPC);
-    }
-
-    memcpy(data, au->data, au->data_size);
-    *data_len = au->data_size;
-
-    return 0;
-}
-
-static int write_sequence_headers(AVCodecContext *avctx,
-                                  FFHWBaseEncodePicture *base_pic,
-                                  uint8_t *data, size_t *data_len)
-{
-    int err;
-    VulkanEncodeH265Context *enc = avctx->priv_data;
-    VulkanEncodeH265Picture  *hp = base_pic ? base_pic->codec_priv : NULL;
-    CodedBitstreamFragment   *au = &enc->current_access_unit;
-
-    if (hp && hp->units_needed & UNIT_AUD) {
-        err = vulkan_encode_h265_add_nal(avctx, au, &enc->raw_aud);
-        if (err < 0)
-            goto fail;
-        hp->units_needed &= ~UNIT_AUD;
-    }
-
-    err = vulkan_encode_h265_add_nal(avctx, au, &enc->units.raw_vps);
-    if (err < 0)
-        goto fail;
-
-    err = vulkan_encode_h265_add_nal(avctx, au, &enc->units.raw_sps);
-    if (err < 0)
-        goto fail;
-
-    err = vulkan_encode_h265_add_nal(avctx, au, &enc->units.raw_pps);
-    if (err < 0)
-        goto fail;
-
-    err = write_access_unit(avctx, data, data_len, au);
-fail:
-    ff_cbs_fragment_reset(au);
-    return err;
-}
-
-static int write_extra_headers(AVCodecContext *avctx,
-                               FFHWBaseEncodePicture *base_pic,
-                               uint8_t *data, size_t *data_len)
-{
-    int err;
-    VulkanEncodeH265Context *enc = avctx->priv_data;
-    VulkanEncodeH265Picture  *hp = base_pic->codec_priv;
-    CodedBitstreamFragment   *au = &enc->current_access_unit;
-
-    if (hp->units_needed & UNIT_AUD) {
-        err = vulkan_encode_h265_add_nal(avctx, au, &enc->raw_aud);
-        if (err < 0)
-            goto fail;
-    }
-
-    if (hp->units_needed & UNIT_SEI_MASTERING_DISPLAY) {
-        err = ff_cbs_sei_add_message(enc->cbs, au, 1,
-                                     SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME,
-                                     &enc->sei_mastering_display, NULL);
-        if (err < 0)
-            goto fail;
-    }
-
-    if (hp->units_needed & UNIT_SEI_CONTENT_LIGHT_LEVEL) {
-        err = ff_cbs_sei_add_message(enc->cbs, au, 1,
-                                     SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO,
-                                     &enc->sei_content_light_level, NULL);
-        if (err < 0)
-            goto fail;
-    }
-    if (hp->units_needed & UNIT_SEI_A53_CC) {
-        err = ff_cbs_sei_add_message(enc->cbs, au, 1,
-                                     SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35,
-                                     &enc->sei_a53cc, NULL);
-        if (err < 0)
-            goto fail;
-    }
-
-    if (hp->units_needed) {
-        err = write_access_unit(avctx, data, data_len, au);
-        if (err < 0)
-            goto fail;
-    } else {
-        err = 0;
-        *data_len = 0;
-    }
-
-fail:
-    ff_cbs_fragment_reset(au);
-    return err;
-}
-
-static int write_filler(AVCodecContext *avctx, uint32_t filler,
-                        uint8_t *data, size_t *data_len)
-{
-    int err;
-    VulkanEncodeH265Context *enc = avctx->priv_data;
-    CodedBitstreamFragment   *au = &enc->current_access_unit;
-
-    H265RawFiller raw_filler = {
-        .nal_unit_header =
-        {
-            .nal_unit_type = HEVC_NAL_FD_NUT,
-            .nuh_temporal_id_plus1 = 1,
-        },
-        .filler_size = filler,
-    };
-
-    err = vulkan_encode_h265_add_nal(avctx, au, &raw_filler);
-    if (err < 0)
-        goto fail;
-
-    err = write_access_unit(avctx, data, data_len, au);
-fail:
-    ff_cbs_fragment_reset(au);
-    return err;
-}
-
-static const FFVulkanCodec enc_cb = {
-    .flags = FF_HW_FLAG_B_PICTURES |
-             FF_HW_FLAG_B_PICTURE_REFERENCES |
-             FF_HW_FLAG_NON_IDR_KEY_PICTURES,
-    .picture_priv_data_size = sizeof(VulkanEncodeH265Picture),
-    .filler_header_size = 7,
-    .init_profile = init_profile,
-    .init_pic_rc = init_pic_rc,
-    .init_pic_params = init_pic_params,
-    .write_sequence_headers = write_sequence_headers,
-    .write_extra_headers = write_extra_headers,
-    .write_filler = write_filler,
-};
-
-static av_cold int vulkan_encode_h265_init(AVCodecContext *avctx)
-{
-    int err, ref_l0, ref_l1;
-    VulkanEncodeH265Context *enc = avctx->priv_data;
-    FFVulkanEncodeContext *ctx = &enc->common;
-    FFHWBaseEncodeContext *base_ctx = &ctx->base;
-    int flags;
-
-    if (avctx->profile == AV_PROFILE_UNKNOWN)
-        avctx->profile = enc->common.opts.profile;
-
-    enc->caps = (VkVideoEncodeH265CapabilitiesKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_KHR,
-    };
-
-    enc->quality_props = (VkVideoEncodeH265QualityLevelPropertiesKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_QUALITY_LEVEL_PROPERTIES_KHR,
-    };
-
-    err = ff_vulkan_encode_init(avctx, &enc->common,
-                                &ff_vk_enc_h265_desc, &enc_cb,
-                                &enc->caps, &enc->quality_props);
-    if (err < 0)
-        return err;
-
-    av_log(avctx, AV_LOG_VERBOSE, "H265 encoder capabilities:\n");
-    av_log(avctx, AV_LOG_VERBOSE, "    Standard capability flags:\n");
-    av_log(avctx, AV_LOG_VERBOSE, "        separate_color_plane: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SEPARATE_COLOR_PLANE_FLAG_SET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        sample_adaptive_offset: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG_SET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        scaling_lists: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SCALING_LIST_DATA_PRESENT_FLAG_SET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        pcm: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_PCM_ENABLED_FLAG_SET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        temporal_mvp: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SPS_TEMPORAL_MVP_ENABLED_FLAG_SET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        init_qp: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_INIT_QP_MINUS26_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        weighted:%s%s\n",
-           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_WEIGHTED_PRED_FLAG_SET_BIT_KHR ?
-               " pred" : "",
-           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_WEIGHTED_BIPRED_FLAG_SET_BIT_KHR ?
-               " bipred" : "");
-    av_log(avctx, AV_LOG_VERBOSE, "        parallel_merge_level: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_LOG2_PARALLEL_MERGE_LEVEL_MINUS2_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        sign_data_hiding: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SIGN_DATA_HIDING_ENABLED_FLAG_SET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        transform_skip:%s%s\n",
-           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_TRANSFORM_SKIP_ENABLED_FLAG_SET_BIT_KHR ?
-           " set" : "",
-           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_TRANSFORM_SKIP_ENABLED_FLAG_UNSET_BIT_KHR ?
-           " unset" : "");
-    av_log(avctx, AV_LOG_VERBOSE, "        slice_chroma_qp_offsets: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_FLAG_SET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        transquant_bypass: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_TRANSQUANT_BYPASS_ENABLED_FLAG_SET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        constrained_intra_pred: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_CONSTRAINED_INTRA_PRED_FLAG_SET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        entrypy_coding_sync: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_ENTROPY_CODING_SYNC_ENABLED_FLAG_SET_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        dependent_slice_segment:%s%s\n",
-           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENTS_ENABLED_FLAG_SET_BIT_KHR ?
-               " enabled" : "",
-           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENT_FLAG_SET_BIT_KHR ?
-               " set" : "");
-    av_log(avctx, AV_LOG_VERBOSE, "        slice_qp_delta: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SLICE_QP_DELTA_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        different_slice_qp_delta: %i\n",
-           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_DIFFERENT_SLICE_QP_DELTA_BIT_KHR));
-
-    av_log(avctx, AV_LOG_VERBOSE, "    Capability flags:\n");
-    av_log(avctx, AV_LOG_VERBOSE, "        hdr_compliance: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        pred_weight_table_generated: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        row_unaligned_slice: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        different_slice_type: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        b_frame_in_l0_list: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        b_frame_in_l1_list: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        per_pict_type_min_max_qp: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        per_slice_constant_qp: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PER_SLICE_CONSTANT_QP_BIT_KHR));
-    av_log(avctx, AV_LOG_VERBOSE, "        generate_prefix_nalu: %i\n",
-           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_KHR));
-
-    av_log(avctx, AV_LOG_VERBOSE, "    Capabilities:\n");
-    av_log(avctx, AV_LOG_VERBOSE, "        maxLevelIdc: %i\n",
-           enc->caps.maxLevelIdc);
-    av_log(avctx, AV_LOG_VERBOSE, "        maxSliceCount: %i\n",
-           enc->caps.maxSliceSegmentCount);
-    av_log(avctx, AV_LOG_VERBOSE, "        maxTiles: %ix%i\n",
-           enc->caps.maxTiles.width, enc->caps.maxTiles.height);
-    av_log(avctx, AV_LOG_VERBOSE, "        cbtSizes: 0x%x\n",
-           enc->caps.ctbSizes);
-    av_log(avctx, AV_LOG_VERBOSE, "        transformBlockSizes: 0x%x\n",
-           enc->caps.transformBlockSizes);
-    av_log(avctx, AV_LOG_VERBOSE, "        max(P/B)PictureL0ReferenceCount: %i P's; %i B's\n",
-           enc->caps.maxPPictureL0ReferenceCount,
-           enc->caps.maxBPictureL0ReferenceCount);
-    av_log(avctx, AV_LOG_VERBOSE, "        maxL1ReferenceCount: %i\n",
-           enc->caps.maxL1ReferenceCount);
-    av_log(avctx, AV_LOG_VERBOSE, "        maxSubLayerCount: %i\n",
-           enc->caps.maxSubLayerCount);
-    av_log(avctx, AV_LOG_VERBOSE, "        expectDyadicTemporalLayerPattern: %i\n",
-           enc->caps.expectDyadicTemporalSubLayerPattern);
-    av_log(avctx, AV_LOG_VERBOSE, "        min/max Qp: [%i, %i]\n",
-           enc->caps.minQp, enc->caps.maxQp);
-    av_log(avctx, AV_LOG_VERBOSE, "        prefersGopRemainingFrames: %i\n",
-           enc->caps.prefersGopRemainingFrames);
-    av_log(avctx, AV_LOG_VERBOSE, "        requiresGopRemainingFrames: %i\n",
-           enc->caps.requiresGopRemainingFrames);
-
-    err = init_enc_options(avctx);
-    if (err < 0)
-        return err;
-
-    flags = ctx->codec->flags;
-    if (!enc->caps.maxPPictureL0ReferenceCount &&
-        !enc->caps.maxBPictureL0ReferenceCount &&
-        !enc->caps.maxL1ReferenceCount) {
-        /* Intra-only */
-        flags |= FF_HW_FLAG_INTRA_ONLY;
-        ref_l0 = ref_l1 = 0;
-    } else if (!enc->caps.maxPPictureL0ReferenceCount) {
-        /* No P-frames? How. */
-        base_ctx->p_to_gpb = 1;
-        ref_l0 = enc->caps.maxBPictureL0ReferenceCount;
-        ref_l1 = enc->caps.maxL1ReferenceCount;
-    } else if (!enc->caps.maxBPictureL0ReferenceCount &&
-               !enc->caps.maxL1ReferenceCount) {
-        /* No B-frames */
-        flags &= ~(FF_HW_FLAG_B_PICTURES | FF_HW_FLAG_B_PICTURE_REFERENCES);
-        ref_l0 = enc->caps.maxPPictureL0ReferenceCount;
-        ref_l1 = 0;
-    } else {
-        /* P and B frames */
-        ref_l0 = FFMIN(enc->caps.maxPPictureL0ReferenceCount,
-                       enc->caps.maxBPictureL0ReferenceCount);
-        ref_l1 = enc->caps.maxL1ReferenceCount;
-    }
-
-    err = ff_hw_base_init_gop_structure(base_ctx, avctx, ref_l0, ref_l1,
-                                        flags, 0);
-    if (err < 0)
-        return err;
-
-    base_ctx->output_delay = base_ctx->b_per_p;
-    base_ctx->decode_delay = base_ctx->max_b_depth;
-
-    /* Init CBS */
-    err = ff_cbs_init(&enc->cbs, AV_CODEC_ID_HEVC, avctx);
-    if (err < 0)
-        return err;
-
-    /* Create units and session parameters */
-    err = init_base_units(avctx);
-    if (err < 0)
-        return err;
-
-    /* Write out extradata */
-    err = ff_vulkan_write_global_header(avctx, &enc->common);
-    if (err < 0)
-        return err;
-
-    return 0;
-}
-
-static av_cold int vulkan_encode_h265_close(AVCodecContext *avctx)
-{
-    VulkanEncodeH265Context *enc = avctx->priv_data;
-    ff_vulkan_encode_uninit(&enc->common);
-    return 0;
-}
-
-#define OFFSET(x) offsetof(VulkanEncodeH265Context, x)
-#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
-static const AVOption vulkan_encode_h265_options[] = {
-    HW_BASE_ENCODE_COMMON_OPTIONS,
-    VULKAN_ENCODE_COMMON_OPTIONS,
-
-    { "profile", "Set profile (profile_idc and constraint_set*_flag)",
-      OFFSET(common.opts.profile), AV_OPT_TYPE_INT,
-      { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, 0xffff, FLAGS, .unit = "profile" },
-
-#define PROFILE(name, value)  name, NULL, 0, AV_OPT_TYPE_CONST, \
-      { .i64 = value }, 0, 0, FLAGS, .unit = "profile"
-    { PROFILE("main",               AV_PROFILE_HEVC_MAIN) },
-    { PROFILE("main10",             AV_PROFILE_HEVC_MAIN_10) },
-    { PROFILE("rext",               AV_PROFILE_HEVC_REXT) },
-#undef PROFILE
-
-    { "tier", "Set tier (general_tier_flag)", OFFSET(common.opts.tier), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, .unit = "tier" },
-        { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, .unit = "tier" },
-        { "high", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, .unit = "tier" },
-
-    { "level", "Set level (general_level_idc)",
-      OFFSET(common.opts.level), AV_OPT_TYPE_INT,
-      { .i64 = AV_LEVEL_UNKNOWN }, AV_LEVEL_UNKNOWN, 0xff, FLAGS, .unit = "level" },
-
-#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
-      { .i64 = value }, 0, 0, FLAGS, .unit = "level"
-    { LEVEL("1",    30) },
-    { LEVEL("2",    60) },
-    { LEVEL("2.1",  63) },
-    { LEVEL("3",    90) },
-    { LEVEL("3.1",  93) },
-    { LEVEL("4",   120) },
-    { LEVEL("4.1", 123) },
-    { LEVEL("5",   150) },
-    { LEVEL("5.1", 153) },
-    { LEVEL("5.2", 156) },
-    { LEVEL("6",   180) },
-    { LEVEL("6.1", 183) },
-    { LEVEL("6.2", 186) },
-#undef LEVEL
-
-    { "units", "Set units to include", OFFSET(unit_elems), AV_OPT_TYPE_FLAGS, { .i64 = UNIT_SEI_MASTERING_DISPLAY | UNIT_SEI_CONTENT_LIGHT_LEVEL | UNIT_SEI_A53_CC }, 0, INT_MAX, FLAGS, "units" },
-        { "hdr",        "Include HDR metadata for mastering display colour volume and content light level information", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_SEI_MASTERING_DISPLAY | UNIT_SEI_CONTENT_LIGHT_LEVEL }, INT_MIN, INT_MAX, FLAGS, "units" },
-        { "a53_cc",     "Include A/53 caption data", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_SEI_A53_CC }, INT_MIN, INT_MAX, FLAGS, "units" },
-
-    { NULL },
-};
-
-static const FFCodecDefault vulkan_encode_h265_defaults[] = {
-    { "b",              "0"   },
-    { "bf",             "2"   },
-    { "g",              "300" },
-    { "i_qfactor",      "1"   },
-    { "i_qoffset",      "0"   },
-    { "b_qfactor",      "6/5" },
-    { "b_qoffset",      "0"   },
-    { "qmin",           "-1"  },
-    { "qmax",           "-1"  },
-    { "refs",           "0"   },
-    { NULL },
-};
-
-static const AVClass vulkan_encode_h265_class = {
-    .class_name = "hevc_vulkan",
-    .item_name  = av_default_item_name,
-    .option     = vulkan_encode_h265_options,
-    .version    = LIBAVUTIL_VERSION_INT,
-};
-
-const FFCodec ff_hevc_vulkan_encoder = {
-    .p.name         = "hevc_vulkan",
-    CODEC_LONG_NAME("H.265/HEVC (Vulkan)"),
-    .p.type         = AVMEDIA_TYPE_VIDEO,
-    .p.id           = AV_CODEC_ID_HEVC,
-    .priv_data_size = sizeof(VulkanEncodeH265Context),
-    .init           = &vulkan_encode_h265_init,
-    FF_CODEC_RECEIVE_PACKET_CB(&ff_vulkan_encode_receive_packet),
-    .close          = &vulkan_encode_h265_close,
-    .p.priv_class   = &vulkan_encode_h265_class,
-    .p.capabilities = AV_CODEC_CAP_DELAY |
-                      AV_CODEC_CAP_HARDWARE |
-                      AV_CODEC_CAP_DR1 |
-                      AV_CODEC_CAP_ENCODER_FLUSH |
-                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
-    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
-    .defaults       = vulkan_encode_h265_defaults,
-    CODEC_PIXFMTS(AV_PIX_FMT_VULKAN),
-    .hw_configs     = ff_vulkan_encode_hw_configs,
-    .p.wrapper_name = "vulkan",
-};
-- 
2.49.1


From 11b0e7cd6abc536087b2e4c63bddce5949beeb38 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:35:51 +0000
Subject: [PATCH 078/118] Changing vulkan file directory

---
 libavcodec/vulkan/vulkan_encode_h265.c | 1795 ++++++++++++++++++++++++
 1 file changed, 1795 insertions(+)
 create mode 100644 libavcodec/vulkan/vulkan_encode_h265.c

diff --git a/libavcodec/vulkan/vulkan_encode_h265.c b/libavcodec/vulkan/vulkan_encode_h265.c
new file mode 100644
index 0000000000..d1b6af25fb
--- /dev/null
+++ b/libavcodec/vulkan/vulkan_encode_h265.c
@@ -0,0 +1,1795 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/internal.h"
+#include "libavutil/opt.h"
+#include "libavutil/mem.h"
+
+#include "libavcodec/cbs.h"
+#include "libavcodec/cbs_h265.h"
+#include "libavcodec/atsc_a53.h"
+#include "libavutil/mastering_display_metadata.h"
+
+#include "libavcodec/codec_internal.h"
+#include "libavcodec/version.h"
+#include "libavcodec/hw_base_encode_h265.h"
+
+#include "vulkan_encode.h"
+
+enum UnitElems {
+    UNIT_AUD                     = 1 << 0,
+    UNIT_SEI_MASTERING_DISPLAY   = 1 << 1,
+    UNIT_SEI_CONTENT_LIGHT_LEVEL = 1 << 2,
+    UNIT_SEI_A53_CC              = 1 << 3,
+};
+
+const FFVulkanEncodeDescriptor ff_vk_enc_h265_desc = {
+    .codec_id         = AV_CODEC_ID_H265,
+    .encode_extension = FF_VK_EXT_VIDEO_ENCODE_H265,
+    .encode_op        = VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR,
+    .ext_props = {
+        .extensionName = VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_EXTENSION_NAME,
+        .specVersion   = VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION,
+    },
+};
+
+typedef struct VulkanEncodeH265Picture {
+    int frame_num;
+    int64_t last_idr_frame;
+    uint16_t idr_pic_id;
+    int primary_pic_type;
+    int slice_type;
+    int pic_order_cnt;
+    int pic_type;
+
+    enum UnitElems units_needed;
+
+    VkVideoEncodeH265RateControlInfoKHR vkrc_info;
+    VkVideoEncodeH265RateControlLayerInfoKHR vkrc_layer_info;
+
+    StdVideoEncodeH265PictureInfo   h265pic_info;
+    VkVideoEncodeH265PictureInfoKHR vkh265pic_info;
+
+    StdVideoEncodeH265WeightTable slice_wt;
+    StdVideoEncodeH265SliceSegmentHeader slice_hdr;
+    VkVideoEncodeH265NaluSliceSegmentInfoKHR vkslice;
+
+    StdVideoEncodeH265ReferenceInfo h265dpb_info;
+    VkVideoEncodeH265DpbSlotInfoKHR vkh265dpb_info;
+
+    StdVideoEncodeH265ReferenceListsInfo ref_list_info;
+    StdVideoEncodeH265LongTermRefPics l_rps;
+    StdVideoH265ShortTermRefPicSet s_rps;
+} VulkanEncodeH265Picture;
+
+typedef struct VulkanEncodeH265Context {
+    FFVulkanEncodeContext common;
+
+    FFHWBaseEncodeH265 units;
+    FFHWBaseEncodeH265Opts unit_opts;
+
+    enum UnitElems unit_elems;
+
+    uint8_t fixed_qp_idr;
+    uint8_t fixed_qp_p;
+    uint8_t fixed_qp_b;
+
+    uint64_t hrd_buffer_size;
+    uint64_t initial_buffer_fullness;
+
+    VkVideoEncodeH265ProfileInfoKHR profile;
+
+    VkVideoEncodeH265CapabilitiesKHR caps;
+    VkVideoEncodeH265QualityLevelPropertiesKHR quality_props;
+
+    CodedBitstreamContext *cbs;
+    CodedBitstreamFragment current_access_unit;
+
+    H265RawAUD                         raw_aud;
+
+    SEIRawMasteringDisplayColourVolume sei_mastering_display;
+    SEIRawContentLightLevelInfo        sei_content_light_level;
+    SEIRawUserDataRegistered           sei_a53cc;
+    void                              *sei_a53cc_data;
+} VulkanEncodeH265Context;
+
+static int init_pic_rc(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
+                       VkVideoEncodeRateControlInfoKHR *rc_info,
+                       VkVideoEncodeRateControlLayerInfoKHR *rc_layer)
+{
+    VulkanEncodeH265Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext   *ctx = &enc->common;
+    VulkanEncodeH265Picture  *hp = pic->codec_priv;
+
+    hp->vkrc_info = (VkVideoEncodeH265RateControlInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_KHR,
+        .flags = VK_VIDEO_ENCODE_H265_RATE_CONTROL_REFERENCE_PATTERN_FLAT_BIT_KHR |
+                 VK_VIDEO_ENCODE_H265_RATE_CONTROL_REGULAR_GOP_BIT_KHR,
+        .idrPeriod = ctx->base.gop_size,
+        .gopFrameCount = ctx->base.gop_size,
+        .consecutiveBFrameCount = FFMAX(ctx->base.b_per_p - 1, 0),
+        .subLayerCount = 0,
+    };
+    rc_info->pNext = &hp->vkrc_info;
+
+    if (rc_info->rateControlMode > VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
+        rc_info->virtualBufferSizeInMs = (enc->hrd_buffer_size * 1000LL) / avctx->bit_rate;
+        rc_info->initialVirtualBufferSizeInMs = (enc->initial_buffer_fullness * 1000LL) / avctx->bit_rate;
+
+        hp->vkrc_layer_info = (VkVideoEncodeH265RateControlLayerInfoKHR) {
+            .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_KHR,
+
+            .useMinQp  = avctx->qmin > 0,
+            .minQp.qpI = avctx->qmin > 0 ? avctx->qmin : 0,
+            .minQp.qpP = avctx->qmin > 0 ? avctx->qmin : 0,
+            .minQp.qpB = avctx->qmin > 0 ? avctx->qmin : 0,
+
+            .useMaxQp  = avctx->qmax > 0,
+            .maxQp.qpI = avctx->qmax > 0 ? avctx->qmax : 0,
+            .maxQp.qpP = avctx->qmax > 0 ? avctx->qmax : 0,
+            .maxQp.qpB = avctx->qmax > 0 ? avctx->qmax : 0,
+
+            .useMaxFrameSize = 0,
+        };
+        rc_layer->pNext = &hp->vkrc_layer_info;
+        hp->vkrc_info.subLayerCount = 1;
+    }
+
+    return 0;
+}
+
+static int vk_enc_h265_update_pic_info(AVCodecContext *avctx,
+                                       FFHWBaseEncodePicture *pic)
+{
+    VulkanEncodeH265Context   *enc = avctx->priv_data;
+    VulkanEncodeH265Picture    *hp = pic->codec_priv;
+    FFHWBaseEncodePicture    *prev = pic->prev;
+    VulkanEncodeH265Picture *hprev = prev ? prev->codec_priv : NULL;
+
+    if (pic->type == FF_HW_PICTURE_TYPE_IDR) {
+        av_assert0(pic->display_order == pic->encode_order);
+
+        hp->last_idr_frame = pic->display_order;
+
+        hp->slice_type     = STD_VIDEO_H265_SLICE_TYPE_I;
+        hp->pic_type       = STD_VIDEO_H265_PICTURE_TYPE_IDR;
+    } else {
+        av_assert0(prev);
+        hp->last_idr_frame = hprev->last_idr_frame;
+
+        if (pic->type == FF_HW_PICTURE_TYPE_I) {
+            hp->slice_type     = STD_VIDEO_H265_SLICE_TYPE_I;
+            hp->pic_type       = STD_VIDEO_H265_PICTURE_TYPE_I;
+        } else if (pic->type == FF_HW_PICTURE_TYPE_P) {
+            av_assert0(pic->refs[0]);
+            hp->slice_type     = STD_VIDEO_H265_SLICE_TYPE_P;
+            hp->pic_type       = STD_VIDEO_H265_PICTURE_TYPE_P;
+        } else {
+            FFHWBaseEncodePicture *irap_ref;
+            av_assert0(pic->refs[0][0] && pic->refs[1][0]);
+            for (irap_ref = pic; irap_ref; irap_ref = irap_ref->refs[1][0]) {
+                if (irap_ref->type == FF_HW_PICTURE_TYPE_I)
+                    break;
+            }
+            hp->slice_type = STD_VIDEO_H265_SLICE_TYPE_B;
+            hp->pic_type   = STD_VIDEO_H265_PICTURE_TYPE_B;
+        }
+    }
+    hp->pic_order_cnt = pic->display_order - hp->last_idr_frame;
+
+    hp->units_needed = 0;
+
+    if (enc->unit_elems & UNIT_AUD) {
+        hp->units_needed |= UNIT_AUD;
+        enc->raw_aud = (H265RawAUD) {
+            .nal_unit_header = {
+                .nal_unit_type         = HEVC_NAL_AUD,
+                .nuh_layer_id          = 0,
+                .nuh_temporal_id_plus1 = 1,
+            },
+            .pic_type = hp->pic_type,
+        };
+    }
+
+    // Only look for the metadata on I/IDR frame on the output. We
+    // may force an IDR frame on the output where the metadata gets
+    // changed on the input frame.
+    if ((enc->unit_elems & UNIT_SEI_MASTERING_DISPLAY) &&
+        (pic->type == FF_HW_PICTURE_TYPE_I || pic->type == FF_HW_PICTURE_TYPE_IDR)) {
+        AVFrameSideData *sd =
+            av_frame_get_side_data(pic->input_image,
+                                   AV_FRAME_DATA_MASTERING_DISPLAY_METADATA);
+
+        if (sd) {
+            AVMasteringDisplayMetadata *mdm = (AVMasteringDisplayMetadata *)sd->data;
+
+            // SEI is needed when both the primaries and luminance are set
+            if (mdm->has_primaries && mdm->has_luminance) {
+                SEIRawMasteringDisplayColourVolume *mdcv =
+                    &enc->sei_mastering_display;
+                const int mapping[3] = {1, 2, 0};
+                const int chroma_den = 50000;
+                const int luma_den   = 10000;
+
+                for (int i = 0; i < 3; i++) {
+                    const int j = mapping[i];
+                    mdcv->display_primaries_x[i] =
+                        FFMIN(lrint(chroma_den *
+                                    av_q2d(mdm->display_primaries[j][0])),
+                              chroma_den);
+                    mdcv->display_primaries_y[i] =
+                        FFMIN(lrint(chroma_den *
+                                    av_q2d(mdm->display_primaries[j][1])),
+                              chroma_den);
+                }
+
+                mdcv->white_point_x =
+                    FFMIN(lrint(chroma_den * av_q2d(mdm->white_point[0])),
+                          chroma_den);
+                mdcv->white_point_y =
+                    FFMIN(lrint(chroma_den * av_q2d(mdm->white_point[1])),
+                          chroma_den);
+
+                mdcv->max_display_mastering_luminance =
+                    lrint(luma_den * av_q2d(mdm->max_luminance));
+                mdcv->min_display_mastering_luminance =
+                    FFMIN(lrint(luma_den * av_q2d(mdm->min_luminance)),
+                          mdcv->max_display_mastering_luminance);
+
+                hp->units_needed |= UNIT_SEI_MASTERING_DISPLAY;
+            }
+        }
+    }
+
+    if ((enc->unit_elems & UNIT_SEI_CONTENT_LIGHT_LEVEL) &&
+        (pic->type == FF_HW_PICTURE_TYPE_I || pic->type == FF_HW_PICTURE_TYPE_IDR)) {
+        AVFrameSideData *sd = av_frame_get_side_data(pic->input_image,
+                                                     AV_FRAME_DATA_CONTENT_LIGHT_LEVEL);
+
+        if (sd) {
+            AVContentLightMetadata *clm = (AVContentLightMetadata *)sd->data;
+            SEIRawContentLightLevelInfo *clli = &enc->sei_content_light_level;
+
+            clli->max_content_light_level     = FFMIN(clm->MaxCLL,  65535);
+            clli->max_pic_average_light_level = FFMIN(clm->MaxFALL, 65535);
+
+            hp->units_needed |= UNIT_SEI_CONTENT_LIGHT_LEVEL;
+        }
+    }
+
+    if (enc->unit_elems & UNIT_SEI_A53_CC) {
+        int err;
+        size_t sei_a53cc_len;
+        av_freep(&enc->sei_a53cc_data);
+        err = ff_alloc_a53_sei(pic->input_image, 0, &enc->sei_a53cc_data, &sei_a53cc_len);
+        if (err < 0)
+            return err;
+        if (enc->sei_a53cc_data != NULL) {
+            enc->sei_a53cc.itu_t_t35_country_code = 181;
+            enc->sei_a53cc.data = (uint8_t *)enc->sei_a53cc_data + 1;
+            enc->sei_a53cc.data_length = sei_a53cc_len - 1;
+
+            hp->units_needed |= UNIT_SEI_A53_CC;
+        }
+    }
+
+    return 0;
+}
+
+static void setup_slices(AVCodecContext *avctx,
+                         FFHWBaseEncodePicture *pic)
+{
+    VulkanEncodeH265Context *enc = avctx->priv_data;
+    VulkanEncodeH265Picture *hp = pic->codec_priv;
+
+    hp->slice_wt = (StdVideoEncodeH265WeightTable) {
+        .flags = (StdVideoEncodeH265WeightTableFlags) {
+            .luma_weight_l0_flag = 0,
+            .chroma_weight_l0_flag = 0,
+            .luma_weight_l1_flag = 0,
+            .chroma_weight_l1_flag = 0,
+        },
+        .luma_log2_weight_denom = 0,
+        .delta_chroma_log2_weight_denom = 0,
+        .delta_luma_weight_l0 = { 0 },
+        .luma_offset_l0 = { 0 },
+        .delta_chroma_weight_l0 = { { 0 } },
+        .delta_chroma_offset_l0 = { { 0 } },
+        .delta_luma_weight_l1 = { 0 },
+        .luma_offset_l1 = { 0 },
+        .delta_chroma_weight_l1 = { { 0 } },
+        .delta_chroma_offset_l1 = { { 0 } },
+    };
+
+    hp->slice_hdr = (StdVideoEncodeH265SliceSegmentHeader) {
+        .flags = (StdVideoEncodeH265SliceSegmentHeaderFlags) {
+            .first_slice_segment_in_pic_flag = 1,
+            .dependent_slice_segment_flag = 0,
+            .slice_sao_luma_flag = enc->units.raw_sps.sample_adaptive_offset_enabled_flag,
+            .slice_sao_chroma_flag = enc->units.raw_sps.sample_adaptive_offset_enabled_flag,
+            .num_ref_idx_active_override_flag = 0,
+            .mvd_l1_zero_flag = 0,
+            .cabac_init_flag = 0,
+            .cu_chroma_qp_offset_enabled_flag = 0,
+            .deblocking_filter_override_flag = 0,
+            .slice_deblocking_filter_disabled_flag = 0,
+            .collocated_from_l0_flag = 1,
+            .slice_loop_filter_across_slices_enabled_flag = 0,
+            /* Reserved */
+        },
+        .slice_type = hp->slice_type,
+        .slice_segment_address = 0,
+        .collocated_ref_idx = 0,
+        .MaxNumMergeCand = 5,
+        .slice_cb_qp_offset = 0,
+        .slice_cr_qp_offset = 0,
+        .slice_beta_offset_div2 = 0,
+        .slice_tc_offset_div2 = 0,
+        .slice_act_y_qp_offset = 0,
+        .slice_act_cb_qp_offset = 0,
+        .slice_act_cr_qp_offset = 0,
+        .slice_qp_delta = 0, /* Filled in below */
+        /* Reserved */
+        .pWeightTable = NULL, // &hp->slice_wt,
+    };
+
+    hp->vkslice = (VkVideoEncodeH265NaluSliceSegmentInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_KHR,
+        .pNext = NULL,
+        .constantQp = pic->type == FF_HW_PICTURE_TYPE_B ? enc->fixed_qp_b :
+                      pic->type == FF_HW_PICTURE_TYPE_P ? enc->fixed_qp_p :
+                                                          enc->fixed_qp_idr,
+        .pStdSliceSegmentHeader = &hp->slice_hdr,
+    };
+
+    if (enc->common.opts.rc_mode != VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR)
+        hp->vkslice.constantQp = 0;
+
+    hp->slice_hdr.slice_qp_delta = hp->vkslice.constantQp -
+                                   (enc->units.raw_pps.init_qp_minus26 + 26);
+
+    hp->vkh265pic_info.pNaluSliceSegmentEntries = &hp->vkslice;
+    hp->vkh265pic_info.naluSliceSegmentEntryCount = 1;
+}
+
+static void setup_refs(AVCodecContext *avctx,
+                       FFHWBaseEncodePicture *pic,
+                       VkVideoEncodeInfoKHR *encode_info)
+{
+    int i, j;
+    VulkanEncodeH265Context *enc = avctx->priv_data;
+    VulkanEncodeH265Picture *hp = pic->codec_priv;
+
+    hp->ref_list_info = (StdVideoEncodeH265ReferenceListsInfo) {
+        .flags = (StdVideoEncodeH265ReferenceListsInfoFlags) {
+            .ref_pic_list_modification_flag_l0 = 0,
+            .ref_pic_list_modification_flag_l1 = 0,
+            /* Reserved */
+        },
+        /* May be overridden during setup_slices() */
+        .num_ref_idx_l0_active_minus1 = pic->nb_refs[0] - 1,
+        .num_ref_idx_l1_active_minus1 = pic->nb_refs[1] - 1,
+        /* Reserved */
+        .list_entry_l0 = { 0 },
+        .list_entry_l1 = { 0 },
+    };
+
+    for (i = 0; i < STD_VIDEO_H265_MAX_NUM_LIST_REF; i++)
+        hp->ref_list_info.RefPicList0[i] = hp->ref_list_info.RefPicList1[i] = -1;
+
+    /* Note: really not sure */
+    for (i = 0; i < pic->nb_refs[0]; i++) {
+        VkVideoReferenceSlotInfoKHR *slot_info;
+        slot_info = (VkVideoReferenceSlotInfoKHR *)&encode_info->pReferenceSlots[i];
+        hp->ref_list_info.RefPicList0[i] = slot_info->slotIndex;
+    }
+
+    /* Note: really not sure */
+    for (i = 0; i < pic->nb_refs[1]; i++) {
+        VkVideoReferenceSlotInfoKHR *slot_info;
+        slot_info = (VkVideoReferenceSlotInfoKHR *)&encode_info->pReferenceSlots[pic->nb_refs[0] + i];
+        hp->ref_list_info.RefPicList1[i] = slot_info->slotIndex;
+    }
+
+    hp->h265pic_info.pRefLists = &hp->ref_list_info;
+
+    if (pic->type != FF_HW_PICTURE_TYPE_IDR) {
+        StdVideoH265ShortTermRefPicSet *rps;
+        VulkanEncodeH265Picture *strp;
+        int rps_poc[MAX_DPB_SIZE];
+        int rps_used[MAX_DPB_SIZE];
+        int poc, rps_pics;
+
+        hp->h265pic_info.flags.short_term_ref_pic_set_sps_flag = 0;
+
+        rps = &hp->s_rps;
+        memset(rps, 0, sizeof(*rps));
+
+        rps_pics = 0;
+        for (i = 0; i < MAX_REFERENCE_LIST_NUM; i++) {
+            for (j = 0; j < pic->nb_refs[i]; j++) {
+                strp = pic->refs[i][j]->codec_priv;
+                rps_poc[rps_pics]  = strp->pic_order_cnt;
+                rps_used[rps_pics] = 1;
+                ++rps_pics;
+            }
+        }
+
+        for (i = 0; i < pic->nb_dpb_pics; i++) {
+            if (pic->dpb[i] == pic)
+                continue;
+
+            for (j = 0; j < pic->nb_refs[0]; j++) {
+                if (pic->dpb[i] == pic->refs[0][j])
+                    break;
+            }
+            if (j < pic->nb_refs[0])
+                continue;
+
+            for (j = 0; j < pic->nb_refs[1]; j++) {
+                if (pic->dpb[i] == pic->refs[1][j])
+                    break;
+            }
+            if (j < pic->nb_refs[1])
+                continue;
+
+            strp = pic->dpb[i]->codec_priv;
+            rps_poc[rps_pics]  = strp->pic_order_cnt;
+            rps_used[rps_pics] = 0;
+            ++rps_pics;
+        }
+
+        for (i = 1; i < rps_pics; i++) {
+            for (j = i; j > 0; j--) {
+                if (rps_poc[j] > rps_poc[j - 1])
+                    break;
+                av_assert0(rps_poc[j] != rps_poc[j - 1]);
+                FFSWAP(int, rps_poc[j],  rps_poc[j - 1]);
+                FFSWAP(int, rps_used[j], rps_used[j - 1]);
+            }
+        }
+
+        av_log(avctx, AV_LOG_DEBUG, "RPS for POC %d:", hp->pic_order_cnt);
+        for (i = 0; i < rps_pics; i++)
+            av_log(avctx, AV_LOG_DEBUG, " (%d,%d)", rps_poc[i], rps_used[i]);
+
+        av_log(avctx, AV_LOG_DEBUG, "\n");
+
+        for (i = 0; i < rps_pics; i++) {
+            av_assert0(rps_poc[i] != hp->pic_order_cnt);
+            if (rps_poc[i] > hp->pic_order_cnt)
+                break;
+        }
+
+        rps->num_negative_pics = i;
+        rps->used_by_curr_pic_s0_flag = 0x0;
+        poc = hp->pic_order_cnt;
+        for (j = i - 1; j >= 0; j--) {
+            rps->delta_poc_s0_minus1[i - 1 - j] = poc - rps_poc[j] - 1;
+            rps->used_by_curr_pic_s0_flag |= rps_used[j] << (i - 1 - j);
+            poc = rps_poc[j];
+        }
+
+        rps->num_positive_pics = rps_pics - i;
+        rps->used_by_curr_pic_s1_flag = 0x0;
+        poc = hp->pic_order_cnt;
+        for (j = i; j < rps_pics; j++) {
+            rps->delta_poc_s1_minus1[j - i] = rps_poc[j] - poc - 1;
+            rps->used_by_curr_pic_s1_flag |= rps_used[j] << (j - i);
+            poc = rps_poc[j];
+        }
+
+        hp->l_rps.num_long_term_sps  = 0;
+        hp->l_rps.num_long_term_pics = 0;
+
+        // when this flag is not present, it is inerred to 1.
+        hp->slice_hdr.flags.collocated_from_l0_flag = 1;
+        hp->h265pic_info.flags.slice_temporal_mvp_enabled_flag =
+            enc->units.raw_sps.sps_temporal_mvp_enabled_flag;
+        if (hp->h265pic_info.flags.slice_temporal_mvp_enabled_flag) {
+            if (hp->slice_hdr.slice_type == STD_VIDEO_H265_SLICE_TYPE_B)
+                hp->slice_hdr.flags.collocated_from_l0_flag = 1;
+            hp->slice_hdr.collocated_ref_idx = 0;
+        }
+
+        hp->slice_hdr.flags.num_ref_idx_active_override_flag = 0;
+        hp->ref_list_info.num_ref_idx_l0_active_minus1 = enc->units.raw_pps.num_ref_idx_l0_default_active_minus1;
+        hp->ref_list_info.num_ref_idx_l1_active_minus1 = enc->units.raw_pps.num_ref_idx_l1_default_active_minus1;
+    }
+
+    hp->h265pic_info.pShortTermRefPicSet = &hp->s_rps;
+    hp->h265pic_info.pLongTermRefPics = &hp->l_rps;
+}
+
+static int init_pic_params(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
+                           VkVideoEncodeInfoKHR *encode_info)
+{
+    int err;
+    VulkanEncodeH265Context *enc = avctx->priv_data;
+    FFVulkanEncodePicture *vp = pic->priv;
+    VulkanEncodeH265Picture *hp = pic->codec_priv;
+    VkVideoReferenceSlotInfoKHR *ref_slot;
+
+    err = vk_enc_h265_update_pic_info(avctx, pic);
+    if (err < 0)
+        return err;
+
+    hp->vkh265pic_info = (VkVideoEncodeH265PictureInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PICTURE_INFO_KHR,
+        .pNext = NULL,
+        .pNaluSliceSegmentEntries = NULL, // Filled in during setup_slices()
+        .naluSliceSegmentEntryCount = 0, // Filled in during setup_slices()
+        .pStdPictureInfo = &hp->h265pic_info,
+    };
+
+    hp->h265pic_info = (StdVideoEncodeH265PictureInfo) {
+        .flags = (StdVideoEncodeH265PictureInfoFlags) {
+            .is_reference = pic->is_reference,
+            .IrapPicFlag = pic->type == FF_HW_PICTURE_TYPE_IDR,
+            .used_for_long_term_reference = 0,
+            .discardable_flag = 0,
+            .cross_layer_bla_flag = 0,
+            .pic_output_flag = 1,
+            .no_output_of_prior_pics_flag = 0,
+            .short_term_ref_pic_set_sps_flag = 0,
+            .slice_temporal_mvp_enabled_flag = enc->units.raw_sps.sps_temporal_mvp_enabled_flag,
+            /* Reserved */
+        },
+        .pic_type = hp->pic_type,
+        .sps_video_parameter_set_id = 0,
+        .pps_seq_parameter_set_id = 0,
+        .pps_pic_parameter_set_id = 0,
+        .short_term_ref_pic_set_idx = 0,
+        .PicOrderCntVal = hp->pic_order_cnt,
+        .TemporalId = 0,
+        /* Reserved */
+        .pRefLists = NULL, // Filled in during setup_refs
+        .pShortTermRefPicSet = NULL,
+        .pLongTermRefPics = NULL,
+    };
+    encode_info->pNext = &hp->vkh265pic_info;
+
+    hp->h265dpb_info = (StdVideoEncodeH265ReferenceInfo) {
+        .flags = (StdVideoEncodeH265ReferenceInfoFlags) {
+            .used_for_long_term_reference = 0,
+            .unused_for_reference = 0,
+            /* Reserved */
+        },
+        .pic_type = hp->h265pic_info.pic_type,
+        .PicOrderCntVal = hp->h265pic_info.PicOrderCntVal,
+        .TemporalId = hp->h265pic_info.TemporalId,
+    };
+    hp->vkh265dpb_info = (VkVideoEncodeH265DpbSlotInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_KHR,
+        .pStdReferenceInfo = &hp->h265dpb_info,
+    };
+
+    vp->dpb_slot.pNext = &hp->vkh265dpb_info;
+
+    ref_slot = (VkVideoReferenceSlotInfoKHR *)encode_info->pSetupReferenceSlot;
+    ref_slot->pNext = &hp->vkh265dpb_info;
+
+    setup_refs(avctx, pic, encode_info);
+
+    setup_slices(avctx, pic);
+
+    return 0;
+}
+
+static int init_profile(AVCodecContext *avctx,
+                        VkVideoProfileInfoKHR *profile, void *pnext)
+{
+    VkResult ret;
+    VulkanEncodeH265Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext *ctx = &enc->common;
+    FFVulkanContext *s = &ctx->s;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+    VkVideoEncodeH265CapabilitiesKHR h265_caps = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_KHR,
+    };
+    VkVideoEncodeCapabilitiesKHR enc_caps = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR,
+        .pNext = &h265_caps,
+    };
+    VkVideoCapabilitiesKHR caps = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR,
+        .pNext = &enc_caps,
+    };
+
+    /* In order of preference */
+    int last_supported = AV_PROFILE_UNKNOWN;
+    static const int known_profiles[] = {
+        AV_PROFILE_HEVC_MAIN,
+        AV_PROFILE_HEVC_MAIN_10,
+        AV_PROFILE_HEVC_REXT,
+    };
+    int nb_profiles = FF_ARRAY_ELEMS(known_profiles);
+
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->frames->sw_format);
+    if (!desc)
+        return AVERROR(EINVAL);
+
+    if (s->frames->sw_format == AV_PIX_FMT_NV12)
+        nb_profiles = 1;
+    else if (s->frames->sw_format == AV_PIX_FMT_P010)
+        nb_profiles = 2;
+
+    enc->profile = (VkVideoEncodeH265ProfileInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_KHR,
+        .pNext = pnext,
+        .stdProfileIdc = ff_vk_h265_profile_to_vk(avctx->profile),
+    };
+    profile->pNext = &enc->profile;
+
+    /* Set level */
+    if (avctx->level == AV_LEVEL_UNKNOWN)
+        avctx->level = enc->common.opts.level;
+
+    /* User has explicitly specified a profile. */
+    if (avctx->profile != AV_PROFILE_UNKNOWN)
+        return 0;
+
+    av_log(avctx, AV_LOG_DEBUG, "Supported profiles:\n");
+    for (int i = 0; i < nb_profiles; i++) {
+        enc->profile.stdProfileIdc = ff_vk_h265_profile_to_vk(known_profiles[i]);
+        ret = vk->GetPhysicalDeviceVideoCapabilitiesKHR(s->hwctx->phys_dev,
+                                                        profile,
+                                                        &caps);
+        if (ret == VK_SUCCESS) {
+            av_log(avctx, AV_LOG_DEBUG, "    %s\n",
+                   avcodec_profile_name(avctx->codec_id, known_profiles[i]));
+            last_supported = known_profiles[i];
+        }
+    }
+
+    if (last_supported == AV_PROFILE_UNKNOWN) {
+        av_log(avctx, AV_LOG_ERROR, "No supported profiles for given format\n");
+        return AVERROR(ENOTSUP);
+    }
+
+    enc->profile.stdProfileIdc = ff_vk_h265_profile_to_vk(last_supported);
+    av_log(avctx, AV_LOG_VERBOSE, "Using profile %s\n",
+           avcodec_profile_name(avctx->codec_id, last_supported));
+    avctx->profile = last_supported;
+
+    return 0;
+}
+
+static int init_enc_options(AVCodecContext *avctx)
+{
+    VulkanEncodeH265Context *enc = avctx->priv_data;
+
+    if (avctx->rc_buffer_size)
+        enc->hrd_buffer_size = avctx->rc_buffer_size;
+    else if (avctx->rc_max_rate > 0)
+        enc->hrd_buffer_size = avctx->rc_max_rate;
+    else
+        enc->hrd_buffer_size = avctx->bit_rate;
+
+    if (avctx->rc_initial_buffer_occupancy) {
+        if (avctx->rc_initial_buffer_occupancy > enc->hrd_buffer_size) {
+            av_log(avctx, AV_LOG_ERROR, "Invalid RC buffer settings: "
+                                        "must have initial buffer size (%d) <= "
+                                        "buffer size (%"PRId64").\n",
+                   avctx->rc_initial_buffer_occupancy, enc->hrd_buffer_size);
+            return AVERROR(EINVAL);
+        }
+        enc->initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
+    } else {
+        enc->initial_buffer_fullness = enc->hrd_buffer_size * 3 / 4;
+    }
+
+    if (enc->common.opts.rc_mode == VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
+        enc->fixed_qp_p = av_clip(enc->common.opts.qp,
+                                  enc->caps.minQp, enc->caps.maxQp);
+
+        if (avctx->i_quant_factor > 0.0)
+            enc->fixed_qp_idr = av_clip((avctx->i_quant_factor * enc->fixed_qp_p +
+                                         avctx->i_quant_offset) + 0.5,
+                                        enc->caps.minQp, enc->caps.maxQp);
+        else
+            enc->fixed_qp_idr = enc->fixed_qp_p;
+
+        if (avctx->b_quant_factor > 0.0)
+            enc->fixed_qp_b = av_clip((avctx->b_quant_factor * enc->fixed_qp_p +
+                                       avctx->b_quant_offset) + 0.5,
+                                      enc->caps.minQp, enc->caps.maxQp);
+        else
+            enc->fixed_qp_b = enc->fixed_qp_p;
+
+        av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
+               "%d / %d / %d for IDR- / P- / B-frames.\n",
+               enc->fixed_qp_idr, enc->fixed_qp_p, enc->fixed_qp_b);
+    } else {
+        enc->fixed_qp_idr = 26;
+        enc->fixed_qp_p = 26;
+        enc->fixed_qp_b = 26;
+    }
+
+    return 0;
+}
+
+static av_cold int init_sequence_headers(AVCodecContext *avctx)
+{
+    int err;
+    VulkanEncodeH265Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext *ctx = &enc->common;
+    FFHWBaseEncodeContext *base_ctx = &ctx->base;
+
+    FFHWBaseEncodeH265 *units = &enc->units;
+    FFHWBaseEncodeH265Opts *unit_opts = &enc->unit_opts;
+
+    int max_ctb_size;
+    unsigned min_tb_size;
+    unsigned max_tb_size;
+    unsigned max_transform_hierarchy;
+
+    unit_opts->tier = enc->common.opts.tier;
+    unit_opts->fixed_qp_idr = enc->fixed_qp_idr;
+    unit_opts->cu_qp_delta_enabled_flag = enc->common.opts.rc_mode != VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
+
+    unit_opts->nb_slices = 1;
+
+    unit_opts->slice_block_rows = (avctx->height + base_ctx->slice_block_height - 1) /
+                                  base_ctx->slice_block_height;
+    unit_opts->slice_block_cols = (avctx->width  + base_ctx->slice_block_width  - 1) /
+                                  base_ctx->slice_block_width;
+
+    /* cabac already set via an option */
+    /* fixed_qp_idr initialized in init_enc_options() */
+    /* hrd_buffer_size initialized in init_enc_options() */
+    /* initial_buffer_fullness initialized in init_enc_options() */
+
+    err = ff_hw_base_encode_init_params_h265(&enc->common.base, avctx,
+                                             units, unit_opts);
+    if (err < 0)
+        return err;
+
+    units->raw_sps.sample_adaptive_offset_enabled_flag =
+      !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG_SET_BIT_KHR);
+    units->raw_pps.transform_skip_enabled_flag =
+      !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_TRANSFORM_SKIP_ENABLED_FLAG_SET_BIT_KHR);
+
+    max_ctb_size = 16;
+
+    /* coding blocks from 8x8 to max CTB size. */
+    if (enc->caps.ctbSizes & VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_KHR)
+        max_ctb_size = 64;
+    else if (enc->caps.ctbSizes & VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_KHR)
+        max_ctb_size = 32;
+
+    min_tb_size = 0;
+    max_tb_size = 0;
+    if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_KHR)
+        min_tb_size = 4;
+    else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_KHR)
+        min_tb_size = 8;
+    else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_KHR)
+        min_tb_size = 16;
+    else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR)
+        min_tb_size = 32;
+
+    if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR)
+        max_tb_size = 32;
+    else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_KHR)
+        max_tb_size = 16;
+    else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_KHR)
+        max_tb_size = 8;
+    else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_KHR)
+        max_tb_size = 4;
+
+    units->raw_sps.log2_min_luma_coding_block_size_minus3 = 0;
+    units->raw_sps.log2_diff_max_min_luma_coding_block_size = av_log2(max_ctb_size) - 3;
+    units->raw_sps.log2_min_luma_transform_block_size_minus2 = av_log2(min_tb_size) - 2;
+    units->raw_sps.log2_diff_max_min_luma_transform_block_size = av_log2(max_tb_size) - av_log2(min_tb_size);
+
+    max_transform_hierarchy = av_log2(max_ctb_size) - av_log2(min_tb_size);
+    units->raw_sps.max_transform_hierarchy_depth_intra = max_transform_hierarchy;
+    units->raw_sps.max_transform_hierarchy_depth_intra = max_transform_hierarchy;
+
+    units->raw_sps.vui.bitstream_restriction_flag = 0;
+    units->raw_sps.vui.max_bytes_per_pic_denom = 2;
+    units->raw_sps.vui.max_bits_per_min_cu_denom = 1;
+
+    units->raw_sps.sps_temporal_mvp_enabled_flag = 0;
+
+    if (base_ctx->gop_size & base_ctx->gop_size - 1 == 0)
+        units->raw_sps.log2_max_pic_order_cnt_lsb_minus4 = FFMAX(av_log2(base_ctx->gop_size) - 4, 0);
+    else
+        units->raw_sps.log2_max_pic_order_cnt_lsb_minus4 = FFMAX(av_log2(base_ctx->gop_size) - 3, 0);
+
+    return 0;
+}
+
+typedef struct VulkanH265Units {
+    StdVideoH265SequenceParameterSet    sps;
+    StdVideoH265ShortTermRefPicSet      str[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE];
+    StdVideoH265LongTermRefPicsSps      ltr;
+    StdVideoH265ProfileTierLevel        ptl_sps;
+    StdVideoH265DecPicBufMgr            dpbm_sps;
+
+    StdVideoH265HrdParameters           vui_header_sps;
+    StdVideoH265SequenceParameterSetVui vui_sps;
+
+    StdVideoH265SubLayerHrdParameters   slhdrnal[HEVC_MAX_SUB_LAYERS];
+    StdVideoH265SubLayerHrdParameters   slhdrvcl[HEVC_MAX_SUB_LAYERS];
+
+    StdVideoH265PictureParameterSet     pps;
+    StdVideoH265ScalingLists            pps_scaling;
+
+    StdVideoH265VideoParameterSet       vps;
+    StdVideoH265ProfileTierLevel        ptl_vps;
+    StdVideoH265DecPicBufMgr            dpbm_vps;
+    StdVideoH265HrdParameters           vui_header_vps;
+} VulkanH265Units;
+
+static av_cold int base_unit_to_vk(AVCodecContext *avctx,
+                                   VulkanH265Units *vk_units)
+{
+    VulkanEncodeH265Context *enc = avctx->priv_data;
+
+    H265RawSPS                           *sps = &enc->units.raw_sps;
+    StdVideoH265SequenceParameterSet   *vksps = &vk_units->sps;
+    StdVideoH265ShortTermRefPicSet       *str =  vk_units->str;
+    StdVideoH265LongTermRefPicsSps       *ltr = &vk_units->ltr;
+    StdVideoH265ProfileTierLevel         *ptl_sps = &vk_units->ptl_sps;
+    StdVideoH265DecPicBufMgr            *dpbm_sps = &vk_units->dpbm_sps;
+
+    StdVideoH265HrdParameters           *vui_header_sps = &vk_units->vui_header_sps;
+    StdVideoH265SequenceParameterSetVui *vui_sps = &vk_units->vui_sps;
+
+    StdVideoH265SubLayerHrdParameters *slhdrnal = vk_units->slhdrnal;
+    StdVideoH265SubLayerHrdParameters *slhdrvcl = vk_units->slhdrvcl;
+
+    H265RawPPS                          *pps = &enc->units.raw_pps;
+    StdVideoH265PictureParameterSet   *vkpps = &vk_units->pps;
+
+    H265RawVPS                           *vps = &enc->units.raw_vps;
+    StdVideoH265VideoParameterSet      *vkvps = &vk_units->vps;
+    StdVideoH265ProfileTierLevel     *ptl_vps = &vk_units->ptl_vps;
+    StdVideoH265DecPicBufMgr        *dpbm_vps = &vk_units->dpbm_vps;
+    StdVideoH265HrdParameters *vui_header_vps = &vk_units->vui_header_vps;
+
+    /* SPS */
+    for (int i = 0; i < HEVC_MAX_SUB_LAYERS; i++) {
+        memcpy(&slhdrnal[i], &sps->vui.hrd_parameters.nal_sub_layer_hrd_parameters[i], sizeof(*slhdrnal));
+        memcpy(&slhdrvcl[i], &sps->vui.hrd_parameters.vcl_sub_layer_hrd_parameters[i], sizeof(*slhdrvcl));
+        slhdrnal[i].cbr_flag = 0x0;
+        slhdrvcl[i].cbr_flag = 0x0;
+        for (int j = 0; j < HEVC_MAX_CPB_CNT; j++) {
+            slhdrnal[i].cbr_flag |= sps->vui.hrd_parameters.nal_sub_layer_hrd_parameters[i].cbr_flag[j] << i;
+            slhdrvcl[i].cbr_flag |= sps->vui.hrd_parameters.vcl_sub_layer_hrd_parameters[i].cbr_flag[j] << i;
+        }
+    }
+
+    *vui_header_sps = (StdVideoH265HrdParameters) {
+        .flags = (StdVideoH265HrdFlags) {
+            .nal_hrd_parameters_present_flag = sps->vui.hrd_parameters.nal_hrd_parameters_present_flag,
+            .vcl_hrd_parameters_present_flag = sps->vui.hrd_parameters.vcl_hrd_parameters_present_flag,
+            .sub_pic_hrd_params_present_flag = sps->vui.hrd_parameters.sub_pic_hrd_params_present_flag,
+            .sub_pic_cpb_params_in_pic_timing_sei_flag = sps->vui.hrd_parameters.sub_pic_cpb_params_in_pic_timing_sei_flag,
+            .fixed_pic_rate_general_flag = 0x0,
+            .fixed_pic_rate_within_cvs_flag = 0x0,
+            .low_delay_hrd_flag = 0x0,
+        },
+        .tick_divisor_minus2 = sps->vui.hrd_parameters.tick_divisor_minus2,
+        .du_cpb_removal_delay_increment_length_minus1 = sps->vui.hrd_parameters.du_cpb_removal_delay_increment_length_minus1,
+        .dpb_output_delay_du_length_minus1 = sps->vui.hrd_parameters.dpb_output_delay_du_length_minus1,
+        .bit_rate_scale = sps->vui.hrd_parameters.bit_rate_scale,
+        .cpb_size_scale = sps->vui.hrd_parameters.cpb_size_scale,
+        .cpb_size_du_scale = sps->vui.hrd_parameters.cpb_size_du_scale,
+        .initial_cpb_removal_delay_length_minus1 = sps->vui.hrd_parameters.initial_cpb_removal_delay_length_minus1,
+        .au_cpb_removal_delay_length_minus1 = sps->vui.hrd_parameters.au_cpb_removal_delay_length_minus1,
+        .dpb_output_delay_length_minus1 = sps->vui.hrd_parameters.dpb_output_delay_length_minus1,
+        /* Reserved - 3*16 bits */
+        .pSubLayerHrdParametersNal = slhdrnal,
+        .pSubLayerHrdParametersVcl = slhdrvcl,
+    };
+
+    for (int i = 0; i < HEVC_MAX_SUB_LAYERS; i++) {
+        vui_header_sps->flags.fixed_pic_rate_general_flag |= sps->vui.hrd_parameters.fixed_pic_rate_general_flag[i] << i;
+        vui_header_sps->flags.fixed_pic_rate_within_cvs_flag |= sps->vui.hrd_parameters.fixed_pic_rate_within_cvs_flag[i] << i;
+        vui_header_sps->flags.low_delay_hrd_flag |= sps->vui.hrd_parameters.low_delay_hrd_flag[i] << i;
+    }
+
+    for (int i = 0; i < STD_VIDEO_H265_SUBLAYERS_LIST_SIZE; i++) {
+        dpbm_sps->max_latency_increase_plus1[i] = sps->sps_max_latency_increase_plus1[i];
+        dpbm_sps->max_dec_pic_buffering_minus1[i] = sps->sps_max_dec_pic_buffering_minus1[i];
+        dpbm_sps->max_num_reorder_pics[i] = sps->sps_max_num_reorder_pics[i];
+    }
+
+    *ptl_sps = (StdVideoH265ProfileTierLevel) {
+        .flags = (StdVideoH265ProfileTierLevelFlags) {
+            .general_tier_flag = sps->profile_tier_level.general_tier_flag,
+            .general_progressive_source_flag = sps->profile_tier_level.general_progressive_source_flag,
+            .general_interlaced_source_flag = sps->profile_tier_level.general_interlaced_source_flag,
+            .general_non_packed_constraint_flag = sps->profile_tier_level.general_non_packed_constraint_flag,
+            .general_frame_only_constraint_flag = sps->profile_tier_level.general_frame_only_constraint_flag,
+        },
+        .general_profile_idc = ff_vk_h265_profile_to_vk(sps->profile_tier_level.general_profile_idc),
+        .general_level_idc = ff_vk_h265_level_to_vk(sps->profile_tier_level.general_level_idc),
+    };
+
+    for (int i = 0; i < STD_VIDEO_H265_MAX_SHORT_TERM_REF_PIC_SETS; i++) {
+        const H265RawSTRefPicSet *st_rps = &sps->st_ref_pic_set[i];
+
+        str[i] = (StdVideoH265ShortTermRefPicSet) {
+            .flags = (StdVideoH265ShortTermRefPicSetFlags) {
+                .inter_ref_pic_set_prediction_flag = st_rps->inter_ref_pic_set_prediction_flag,
+                .delta_rps_sign = st_rps->delta_rps_sign,
+            },
+            .delta_idx_minus1 = st_rps->delta_idx_minus1,
+            .use_delta_flag = 0x0,
+            .abs_delta_rps_minus1 = st_rps->abs_delta_rps_minus1,
+            .used_by_curr_pic_flag    = 0x0,
+            .used_by_curr_pic_s0_flag = 0x0,
+            .used_by_curr_pic_s1_flag = 0x0,
+            /* Reserved */
+            /* Reserved */
+            /* Reserved */
+            .num_negative_pics = st_rps->num_negative_pics,
+            .num_positive_pics = st_rps->num_positive_pics,
+        };
+
+        for (int j = 0; j < HEVC_MAX_REFS; j++) {
+            str[i].use_delta_flag |= st_rps->use_delta_flag[j] << i;
+            str[i].used_by_curr_pic_flag |= st_rps->used_by_curr_pic_flag[j] << i;
+            str[i].used_by_curr_pic_s0_flag |= st_rps->used_by_curr_pic_s0_flag[j] << i;
+            str[i].used_by_curr_pic_s1_flag |= st_rps->used_by_curr_pic_s1_flag[j] << i;
+            str[i].delta_poc_s0_minus1[j] = st_rps->delta_poc_s0_minus1[j];
+            str[i].delta_poc_s1_minus1[j] = st_rps->delta_poc_s1_minus1[j];
+        }
+    }
+
+    ltr->used_by_curr_pic_lt_sps_flag = 0;
+    for (int i = 0; i < STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS; i++) {
+        ltr->used_by_curr_pic_lt_sps_flag |= sps->lt_ref_pic_poc_lsb_sps[i] << i;
+        ltr->lt_ref_pic_poc_lsb_sps[i] = sps->lt_ref_pic_poc_lsb_sps[i];
+    }
+
+    *vksps = (StdVideoH265SequenceParameterSet) {
+        .flags = (StdVideoH265SpsFlags) {
+            .sps_temporal_id_nesting_flag = sps->sps_temporal_id_nesting_flag,
+            .separate_colour_plane_flag = sps->separate_colour_plane_flag,
+            .conformance_window_flag = sps->conformance_window_flag,
+            .sps_sub_layer_ordering_info_present_flag = sps->sps_sub_layer_ordering_info_present_flag,
+            .scaling_list_enabled_flag = sps->scaling_list_enabled_flag,
+            .sps_scaling_list_data_present_flag = sps->sps_scaling_list_data_present_flag,
+            .amp_enabled_flag = sps->amp_enabled_flag,
+            .sample_adaptive_offset_enabled_flag = sps->sample_adaptive_offset_enabled_flag,
+            .pcm_enabled_flag = sps->pcm_enabled_flag,
+            .pcm_loop_filter_disabled_flag = sps->pcm_loop_filter_disabled_flag,
+            .long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag,
+            .sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag,
+            .strong_intra_smoothing_enabled_flag = sps->strong_intra_smoothing_enabled_flag,
+            .vui_parameters_present_flag = sps->vui_parameters_present_flag,
+            .sps_extension_present_flag = sps->sps_extension_present_flag,
+            .sps_range_extension_flag = sps->sps_range_extension_flag,
+            .transform_skip_rotation_enabled_flag = sps->transform_skip_rotation_enabled_flag,
+            .transform_skip_context_enabled_flag = sps->transform_skip_context_enabled_flag,
+            .implicit_rdpcm_enabled_flag = sps->implicit_rdpcm_enabled_flag,
+            .explicit_rdpcm_enabled_flag = sps->explicit_rdpcm_enabled_flag,
+            .extended_precision_processing_flag = sps->extended_precision_processing_flag,
+            .intra_smoothing_disabled_flag = sps->intra_smoothing_disabled_flag,
+            .high_precision_offsets_enabled_flag = sps->high_precision_offsets_enabled_flag,
+            .persistent_rice_adaptation_enabled_flag = sps->persistent_rice_adaptation_enabled_flag,
+            .cabac_bypass_alignment_enabled_flag = sps->cabac_bypass_alignment_enabled_flag,
+            .sps_scc_extension_flag = sps->sps_scc_extension_flag,
+            .sps_curr_pic_ref_enabled_flag = sps->sps_curr_pic_ref_enabled_flag,
+            .palette_mode_enabled_flag = sps->palette_mode_enabled_flag,
+            .sps_palette_predictor_initializers_present_flag = sps->sps_palette_predictor_initializer_present_flag,
+            .intra_boundary_filtering_disabled_flag = sps->intra_boundary_filtering_disable_flag,
+        },
+        .chroma_format_idc = sps->chroma_format_idc,
+        .pic_width_in_luma_samples = sps->pic_width_in_luma_samples,
+        .pic_height_in_luma_samples = sps->pic_height_in_luma_samples,
+        .sps_video_parameter_set_id = sps->sps_video_parameter_set_id,
+        .sps_max_sub_layers_minus1 = sps->sps_max_sub_layers_minus1,
+        .sps_seq_parameter_set_id = sps->sps_seq_parameter_set_id,
+        .bit_depth_luma_minus8 = sps->bit_depth_luma_minus8,
+        .bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8,
+        .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4,
+        .log2_min_luma_coding_block_size_minus3 = sps->log2_min_luma_coding_block_size_minus3,
+        .log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_luma_coding_block_size,
+        .log2_min_luma_transform_block_size_minus2 = sps->log2_min_luma_transform_block_size_minus2,
+        .log2_diff_max_min_luma_transform_block_size = sps->log2_diff_max_min_luma_transform_block_size,
+        .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter,
+        .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra,
+        .num_short_term_ref_pic_sets = sps->num_short_term_ref_pic_sets,
+        .num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps,
+        .pcm_sample_bit_depth_luma_minus1 = sps->pcm_sample_bit_depth_luma_minus1,
+        .pcm_sample_bit_depth_chroma_minus1 = sps->pcm_sample_bit_depth_chroma_minus1,
+        .log2_min_pcm_luma_coding_block_size_minus3 = sps->log2_min_pcm_luma_coding_block_size_minus3,
+        .log2_diff_max_min_pcm_luma_coding_block_size = sps->log2_diff_max_min_pcm_luma_coding_block_size,
+        /* Reserved */
+        /* Reserved */
+        .palette_max_size = sps->palette_max_size,
+        .delta_palette_max_predictor_size = sps->delta_palette_max_predictor_size,
+        .motion_vector_resolution_control_idc = sps->motion_vector_resolution_control_idc,
+        .sps_num_palette_predictor_initializers_minus1 = sps->sps_num_palette_predictor_initializer_minus1,
+        .conf_win_left_offset = sps->conf_win_left_offset,
+        .conf_win_right_offset = sps->conf_win_right_offset,
+        .conf_win_top_offset = sps->conf_win_top_offset,
+        .conf_win_bottom_offset = sps->conf_win_bottom_offset,
+        .pProfileTierLevel = ptl_sps,
+        .pDecPicBufMgr = dpbm_sps,
+        .pScalingLists = NULL,
+        .pShortTermRefPicSet = str,
+        .pLongTermRefPicsSps = ltr,
+        .pSequenceParameterSetVui = vui_sps,
+        .pPredictorPaletteEntries = NULL,
+    };
+
+    /* PPS */
+    *vkpps = (StdVideoH265PictureParameterSet) {
+        .flags = (StdVideoH265PpsFlags) {
+            .dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag,
+            .output_flag_present_flag = pps->output_flag_present_flag,
+            .sign_data_hiding_enabled_flag = pps->sign_data_hiding_enabled_flag,
+            .cabac_init_present_flag = pps->cabac_init_present_flag,
+            .constrained_intra_pred_flag = pps->constrained_intra_pred_flag,
+            .transform_skip_enabled_flag = pps->transform_skip_enabled_flag,
+            .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag,
+            .pps_slice_chroma_qp_offsets_present_flag = pps->pps_slice_chroma_qp_offsets_present_flag,
+            .weighted_pred_flag = pps->weighted_pred_flag,
+            .weighted_bipred_flag = pps->weighted_bipred_flag,
+            .transquant_bypass_enabled_flag = pps->transquant_bypass_enabled_flag,
+            .tiles_enabled_flag = pps->tiles_enabled_flag,
+            .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag,
+            .uniform_spacing_flag = pps->uniform_spacing_flag,
+            .loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag,
+            .pps_loop_filter_across_slices_enabled_flag = pps->pps_loop_filter_across_slices_enabled_flag,
+            .deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag,
+            .deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag,
+            .pps_deblocking_filter_disabled_flag = pps->pps_deblocking_filter_disabled_flag,
+            .pps_scaling_list_data_present_flag = pps->pps_scaling_list_data_present_flag,
+            .lists_modification_present_flag = pps->lists_modification_present_flag,
+            .slice_segment_header_extension_present_flag = pps->slice_segment_header_extension_present_flag,
+            .pps_extension_present_flag = pps->pps_extension_present_flag,
+            .cross_component_prediction_enabled_flag = pps->cross_component_prediction_enabled_flag,
+            .chroma_qp_offset_list_enabled_flag = pps->chroma_qp_offset_list_enabled_flag,
+            .pps_curr_pic_ref_enabled_flag = pps->pps_curr_pic_ref_enabled_flag,
+            .residual_adaptive_colour_transform_enabled_flag = pps->residual_adaptive_colour_transform_enabled_flag,
+            .pps_slice_act_qp_offsets_present_flag = pps->pps_slice_act_qp_offsets_present_flag,
+            .pps_palette_predictor_initializers_present_flag = pps->pps_palette_predictor_initializer_present_flag,
+            .monochrome_palette_flag = pps->monochrome_palette_flag,
+            .pps_range_extension_flag = pps->pps_range_extension_flag,
+        },
+        .pps_pic_parameter_set_id = pps->pps_pic_parameter_set_id,
+        .pps_seq_parameter_set_id = pps->pps_seq_parameter_set_id,
+        .sps_video_parameter_set_id = sps->sps_video_parameter_set_id,
+        .num_extra_slice_header_bits = pps->num_extra_slice_header_bits,
+        .num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active_minus1,
+        .num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active_minus1,
+        .init_qp_minus26 = pps->init_qp_minus26,
+        .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth,
+        .pps_cb_qp_offset = pps->pps_cb_qp_offset,
+        .pps_cr_qp_offset = pps->pps_cr_qp_offset,
+        .pps_beta_offset_div2 = pps->pps_beta_offset_div2,
+        .pps_tc_offset_div2 = pps->pps_tc_offset_div2,
+        .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level_minus2,
+        .log2_max_transform_skip_block_size_minus2 = pps->log2_max_transform_skip_block_size_minus2,
+        .diff_cu_chroma_qp_offset_depth = pps->diff_cu_chroma_qp_offset_depth,
+        .chroma_qp_offset_list_len_minus1 = pps->chroma_qp_offset_list_len_minus1,
+        .log2_sao_offset_scale_luma = pps->log2_sao_offset_scale_luma,
+        .log2_sao_offset_scale_chroma = pps->log2_sao_offset_scale_chroma,
+        .pps_act_y_qp_offset_plus5 = pps->pps_act_y_qp_offset_plus5,
+        .pps_act_cb_qp_offset_plus5 = pps->pps_act_cb_qp_offset_plus5,
+        .pps_act_cr_qp_offset_plus3 = pps->pps_act_cr_qp_offset_plus3,
+        .pps_num_palette_predictor_initializers = pps->pps_num_palette_predictor_initializer,
+        .luma_bit_depth_entry_minus8 = pps->luma_bit_depth_entry_minus8,
+        .chroma_bit_depth_entry_minus8 = pps->chroma_bit_depth_entry_minus8,
+        .num_tile_columns_minus1 = pps->num_tile_columns_minus1,
+        .num_tile_rows_minus1 = pps->num_tile_rows_minus1,
+        .pScalingLists = NULL,
+        .pPredictorPaletteEntries = NULL,
+    };
+
+    for (int i = 0; i < pps->num_tile_columns_minus1; i++)
+        vkpps->column_width_minus1[i] = pps->column_width_minus1[i];
+
+    for (int i = 0; i < pps->num_tile_rows_minus1; i++)
+        vkpps->row_height_minus1[i] = pps->row_height_minus1[i];
+
+    for (int i = 0; i <= pps->chroma_qp_offset_list_len_minus1; i++) {
+        vkpps->cb_qp_offset_list[i] = pps->cb_qp_offset_list[i];
+        vkpps->cr_qp_offset_list[i] = pps->cr_qp_offset_list[i];
+    }
+
+    /* VPS */
+    for (int i = 0; i < STD_VIDEO_H265_SUBLAYERS_LIST_SIZE; i++) {
+        dpbm_vps->max_latency_increase_plus1[i] = vps->vps_max_latency_increase_plus1[i];
+        dpbm_vps->max_dec_pic_buffering_minus1[i] = vps->vps_max_dec_pic_buffering_minus1[i];
+        dpbm_vps->max_num_reorder_pics[i] = vps->vps_max_num_reorder_pics[i];
+    }
+
+    *ptl_vps = (StdVideoH265ProfileTierLevel) {
+        .flags = (StdVideoH265ProfileTierLevelFlags) {
+            .general_tier_flag = vps->profile_tier_level.general_tier_flag,
+            .general_progressive_source_flag = vps->profile_tier_level.general_progressive_source_flag,
+            .general_interlaced_source_flag = vps->profile_tier_level.general_interlaced_source_flag,
+            .general_non_packed_constraint_flag = vps->profile_tier_level.general_non_packed_constraint_flag,
+            .general_frame_only_constraint_flag = vps->profile_tier_level.general_frame_only_constraint_flag,
+        },
+        .general_profile_idc = ff_vk_h265_profile_to_vk(vps->profile_tier_level.general_profile_idc),
+        .general_level_idc = ff_vk_h265_level_to_vk(vps->profile_tier_level.general_level_idc),
+    };
+
+    *vkvps = (StdVideoH265VideoParameterSet) {
+        .flags = (StdVideoH265VpsFlags) {
+            .vps_temporal_id_nesting_flag = vps->vps_temporal_id_nesting_flag,
+            .vps_sub_layer_ordering_info_present_flag = vps->vps_sub_layer_ordering_info_present_flag,
+            .vps_timing_info_present_flag = vps->vps_timing_info_present_flag,
+            .vps_poc_proportional_to_timing_flag = vps->vps_poc_proportional_to_timing_flag,
+        },
+        .vps_video_parameter_set_id = vps->vps_video_parameter_set_id,
+        .vps_max_sub_layers_minus1 = vps->vps_max_sub_layers_minus1,
+        /* Reserved */
+        /* Reserved */
+        .vps_num_units_in_tick = vps->vps_num_units_in_tick,
+        .vps_time_scale = vps->vps_time_scale,
+        .vps_num_ticks_poc_diff_one_minus1 = vps->vps_num_ticks_poc_diff_one_minus1,
+        /* Reserved */
+        .pDecPicBufMgr = dpbm_vps,
+        .pHrdParameters = vui_header_vps,
+        .pProfileTierLevel = ptl_vps,
+    };
+
+    return 0;
+}
+
+static int create_session_params(AVCodecContext *avctx)
+{
+    int err;
+    VulkanEncodeH265Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext *ctx = &enc->common;
+    FFVulkanContext *s = &ctx->s;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+
+    VulkanH265Units vk_units = { 0 };
+
+    VkVideoEncodeH265SessionParametersAddInfoKHR h265_params_info;
+    VkVideoEncodeH265SessionParametersCreateInfoKHR h265_params;
+
+    /* Convert it to Vulkan */
+    err = base_unit_to_vk(avctx, &vk_units);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to convert SPS/PPS units to Vulkan: %s\n",
+               av_err2str(err));
+        return err;
+    }
+
+    /* Destroy the session params */
+    if (ctx->session_params)
+        vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
+                                             ctx->session_params,
+                                             s->hwctx->alloc);
+
+    h265_params_info = (VkVideoEncodeH265SessionParametersAddInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR,
+        .pStdSPSs = &vk_units.sps,
+        .stdSPSCount = 1,
+        .pStdPPSs = &vk_units.pps,
+        .stdPPSCount = 1,
+        .pStdVPSs = &vk_units.vps,
+        .stdVPSCount = 1,
+    };
+    h265_params = (VkVideoEncodeH265SessionParametersCreateInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR,
+        .maxStdSPSCount = 1,
+        .maxStdPPSCount = 1,
+        .maxStdVPSCount = 1,
+        .pParametersAddInfo = &h265_params_info,
+    };
+
+    return ff_vulkan_encode_create_session_params(avctx, ctx, &h265_params);
+}
+
+static int parse_feedback_units(AVCodecContext *avctx,
+                                const uint8_t *data, size_t size,
+                                int sps_override, int pps_override)
+{
+    int err;
+    VulkanEncodeH265Context *enc = avctx->priv_data;
+
+    CodedBitstreamContext *cbs;
+    CodedBitstreamFragment au = { 0 };
+
+    err = ff_cbs_init(&cbs, AV_CODEC_ID_HEVC, avctx);
+    if (err < 0)
+        return err;
+
+    err = ff_cbs_read(cbs, &au, NULL, data, size);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to parse feedback units, bad drivers: %s\n",
+               av_err2str(err));
+        goto fail;
+    }
+
+    if (sps_override) {
+        for (int i = 0; i < au.nb_units; i++) {
+            if (au.units[i].type == HEVC_NAL_SPS) {
+                H265RawSPS *sps = au.units[i].content;
+                enc->units.raw_sps.pic_width_in_luma_samples = sps->pic_width_in_luma_samples;
+                enc->units.raw_sps.pic_height_in_luma_samples = sps->pic_height_in_luma_samples;
+                enc->units.raw_sps.log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_luma_coding_block_size;
+                enc->units.raw_sps.max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter;
+                enc->units.raw_sps.max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra;
+            }
+        }
+    }
+
+    /* If PPS has an override, just copy it entirely. */
+    if (pps_override) {
+        for (int i = 0; i < au.nb_units; i++) {
+            if (au.units[i].type == HEVC_NAL_PPS) {
+                H265RawPPS *pps = au.units[i].content;
+                memcpy(&enc->units.raw_pps, pps, sizeof(*pps));
+                enc->fixed_qp_idr = pps->init_qp_minus26 + 26;
+                break;
+            }
+        }
+    }
+
+    err = 0;
+fail:
+    ff_cbs_fragment_free(&au);
+    ff_cbs_close(&cbs);
+
+    return err;
+}
+
+static int init_base_units(AVCodecContext *avctx)
+{
+    int err;
+    VkResult ret;
+    VulkanEncodeH265Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext *ctx = &enc->common;
+    FFVulkanContext *s = &ctx->s;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+
+    VkVideoEncodeH265SessionParametersGetInfoKHR h265_params_info;
+    VkVideoEncodeSessionParametersGetInfoKHR params_info;
+    VkVideoEncodeH265SessionParametersFeedbackInfoKHR h265_params_feedback;
+    VkVideoEncodeSessionParametersFeedbackInfoKHR params_feedback;
+
+    void *data = NULL;
+    size_t data_size = 0;
+
+    /* Generate SPS/PPS unit info */
+    err = init_sequence_headers(avctx);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to initialize SPS/PPS units: %s\n",
+               av_err2str(err));
+        return err;
+    }
+
+    /* Create session parameters from them */
+    err = create_session_params(avctx);
+    if (err < 0)
+        return err;
+
+    h265_params_info = (VkVideoEncodeH265SessionParametersGetInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_GET_INFO_KHR,
+        .writeStdSPS = 1,
+        .writeStdPPS = 1,
+        .writeStdVPS = 1,
+        .stdSPSId = enc->units.raw_sps.sps_seq_parameter_set_id,
+        .stdPPSId = enc->units.raw_pps.pps_pic_parameter_set_id,
+        .stdVPSId = enc->units.raw_vps.vps_video_parameter_set_id,
+    };
+    params_info = (VkVideoEncodeSessionParametersGetInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_GET_INFO_KHR,
+        .pNext = &h265_params_info,
+        .videoSessionParameters = ctx->session_params,
+    };
+
+    h265_params_feedback = (VkVideoEncodeH265SessionParametersFeedbackInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_FEEDBACK_INFO_KHR,
+    };
+    params_feedback = (VkVideoEncodeSessionParametersFeedbackInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_FEEDBACK_INFO_KHR,
+        .pNext = &h265_params_feedback,
+    };
+
+    ret = vk->GetEncodedVideoSessionParametersKHR(s->hwctx->act_dev, &params_info,
+                                                  &params_feedback,
+                                                  &data_size, data);
+    if (ret == VK_INCOMPLETE ||
+        (ret == VK_SUCCESS) && (data_size > 0)) {
+        data = av_mallocz(data_size);
+        if (!data)
+            return AVERROR(ENOMEM);
+    } else {
+        av_log(avctx, AV_LOG_ERROR, "Unable to get feedback for H.265 units = %"SIZE_SPECIFIER"\n", data_size);
+        return err;
+    }
+
+    ret = vk->GetEncodedVideoSessionParametersKHR(s->hwctx->act_dev, &params_info,
+                                                  &params_feedback,
+                                                  &data_size, data);
+    if (ret != VK_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Error writing feedback units\n");
+        return err;
+    }
+
+    av_log(avctx, AV_LOG_VERBOSE, "Feedback units written, overrides: %i (SPS: %i PPS: %i VPS: %i)\n",
+           params_feedback.hasOverrides,
+           h265_params_feedback.hasStdSPSOverrides,
+           h265_params_feedback.hasStdPPSOverrides,
+           h265_params_feedback.hasStdVPSOverrides);
+
+    params_feedback.hasOverrides = 1;
+    h265_params_feedback.hasStdSPSOverrides = 1;
+    h265_params_feedback.hasStdPPSOverrides = 1;
+
+    /* No need to sync any overrides */
+    if (!params_feedback.hasOverrides)
+        return 0;
+
+    /* Parse back tne units and override */
+    err = parse_feedback_units(avctx, data, data_size,
+                               h265_params_feedback.hasStdSPSOverrides,
+                               h265_params_feedback.hasStdPPSOverrides);
+    if (err < 0)
+        return err;
+
+    /* Create final session parameters */
+    err = create_session_params(avctx);
+    if (err < 0)
+        return err;
+
+    return 0;
+}
+
+static int vulkan_encode_h265_add_nal(AVCodecContext *avctx,
+                                      CodedBitstreamFragment *au,
+                                      void *nal_unit)
+{
+    H265RawNALUnitHeader *header = nal_unit;
+
+    int err = ff_cbs_insert_unit_content(au, -1,
+                                         header->nal_unit_type, nal_unit, NULL);
+    if (err < 0)
+        av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: "
+               "type = %d.\n", header->nal_unit_type);
+
+    return err;
+}
+
+static int write_access_unit(AVCodecContext *avctx,
+                             uint8_t *data, size_t *data_len,
+                             CodedBitstreamFragment *au)
+{
+    VulkanEncodeH265Context *enc = avctx->priv_data;
+
+    int err = ff_cbs_write_fragment_data(enc->cbs, au);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n");
+        return err;
+    }
+
+    if (*data_len < au->data_size) {
+        av_log(avctx, AV_LOG_ERROR, "Access unit too large: %"SIZE_SPECIFIER" < %"SIZE_SPECIFIER".\n",
+               *data_len, au->data_size);
+        return AVERROR(ENOSPC);
+    }
+
+    memcpy(data, au->data, au->data_size);
+    *data_len = au->data_size;
+
+    return 0;
+}
+
+static int write_sequence_headers(AVCodecContext *avctx,
+                                  FFHWBaseEncodePicture *base_pic,
+                                  uint8_t *data, size_t *data_len)
+{
+    int err;
+    VulkanEncodeH265Context *enc = avctx->priv_data;
+    VulkanEncodeH265Picture  *hp = base_pic ? base_pic->codec_priv : NULL;
+    CodedBitstreamFragment   *au = &enc->current_access_unit;
+
+    if (hp && hp->units_needed & UNIT_AUD) {
+        err = vulkan_encode_h265_add_nal(avctx, au, &enc->raw_aud);
+        if (err < 0)
+            goto fail;
+        hp->units_needed &= ~UNIT_AUD;
+    }
+
+    err = vulkan_encode_h265_add_nal(avctx, au, &enc->units.raw_vps);
+    if (err < 0)
+        goto fail;
+
+    err = vulkan_encode_h265_add_nal(avctx, au, &enc->units.raw_sps);
+    if (err < 0)
+        goto fail;
+
+    err = vulkan_encode_h265_add_nal(avctx, au, &enc->units.raw_pps);
+    if (err < 0)
+        goto fail;
+
+    err = write_access_unit(avctx, data, data_len, au);
+fail:
+    ff_cbs_fragment_reset(au);
+    return err;
+}
+
+static int write_extra_headers(AVCodecContext *avctx,
+                               FFHWBaseEncodePicture *base_pic,
+                               uint8_t *data, size_t *data_len)
+{
+    int err;
+    VulkanEncodeH265Context *enc = avctx->priv_data;
+    VulkanEncodeH265Picture  *hp = base_pic->codec_priv;
+    CodedBitstreamFragment   *au = &enc->current_access_unit;
+
+    if (hp->units_needed & UNIT_AUD) {
+        err = vulkan_encode_h265_add_nal(avctx, au, &enc->raw_aud);
+        if (err < 0)
+            goto fail;
+    }
+
+    if (hp->units_needed & UNIT_SEI_MASTERING_DISPLAY) {
+        err = ff_cbs_sei_add_message(enc->cbs, au, 1,
+                                     SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME,
+                                     &enc->sei_mastering_display, NULL);
+        if (err < 0)
+            goto fail;
+    }
+
+    if (hp->units_needed & UNIT_SEI_CONTENT_LIGHT_LEVEL) {
+        err = ff_cbs_sei_add_message(enc->cbs, au, 1,
+                                     SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO,
+                                     &enc->sei_content_light_level, NULL);
+        if (err < 0)
+            goto fail;
+    }
+    if (hp->units_needed & UNIT_SEI_A53_CC) {
+        err = ff_cbs_sei_add_message(enc->cbs, au, 1,
+                                     SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35,
+                                     &enc->sei_a53cc, NULL);
+        if (err < 0)
+            goto fail;
+    }
+
+    if (hp->units_needed) {
+        err = write_access_unit(avctx, data, data_len, au);
+        if (err < 0)
+            goto fail;
+    } else {
+        err = 0;
+        *data_len = 0;
+    }
+
+fail:
+    ff_cbs_fragment_reset(au);
+    return err;
+}
+
+static int write_filler(AVCodecContext *avctx, uint32_t filler,
+                        uint8_t *data, size_t *data_len)
+{
+    int err;
+    VulkanEncodeH265Context *enc = avctx->priv_data;
+    CodedBitstreamFragment   *au = &enc->current_access_unit;
+
+    H265RawFiller raw_filler = {
+        .nal_unit_header =
+        {
+            .nal_unit_type = HEVC_NAL_FD_NUT,
+            .nuh_temporal_id_plus1 = 1,
+        },
+        .filler_size = filler,
+    };
+
+    err = vulkan_encode_h265_add_nal(avctx, au, &raw_filler);
+    if (err < 0)
+        goto fail;
+
+    err = write_access_unit(avctx, data, data_len, au);
+fail:
+    ff_cbs_fragment_reset(au);
+    return err;
+}
+
+static const FFVulkanCodec enc_cb = {
+    .flags = FF_HW_FLAG_B_PICTURES |
+             FF_HW_FLAG_B_PICTURE_REFERENCES |
+             FF_HW_FLAG_NON_IDR_KEY_PICTURES,
+    .picture_priv_data_size = sizeof(VulkanEncodeH265Picture),
+    .filler_header_size = 7,
+    .init_profile = init_profile,
+    .init_pic_rc = init_pic_rc,
+    .init_pic_params = init_pic_params,
+    .write_sequence_headers = write_sequence_headers,
+    .write_extra_headers = write_extra_headers,
+    .write_filler = write_filler,
+};
+
+static av_cold int vulkan_encode_h265_init(AVCodecContext *avctx)
+{
+    int err, ref_l0, ref_l1;
+    VulkanEncodeH265Context *enc = avctx->priv_data;
+    FFVulkanEncodeContext *ctx = &enc->common;
+    FFHWBaseEncodeContext *base_ctx = &ctx->base;
+    int flags;
+
+    if (avctx->profile == AV_PROFILE_UNKNOWN)
+        avctx->profile = enc->common.opts.profile;
+
+    enc->caps = (VkVideoEncodeH265CapabilitiesKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_KHR,
+    };
+
+    enc->quality_props = (VkVideoEncodeH265QualityLevelPropertiesKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_QUALITY_LEVEL_PROPERTIES_KHR,
+    };
+
+    err = ff_vulkan_encode_init(avctx, &enc->common,
+                                &ff_vk_enc_h265_desc, &enc_cb,
+                                &enc->caps, &enc->quality_props);
+    if (err < 0)
+        return err;
+
+    av_log(avctx, AV_LOG_VERBOSE, "H265 encoder capabilities:\n");
+    av_log(avctx, AV_LOG_VERBOSE, "    Standard capability flags:\n");
+    av_log(avctx, AV_LOG_VERBOSE, "        separate_color_plane: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SEPARATE_COLOR_PLANE_FLAG_SET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        sample_adaptive_offset: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG_SET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        scaling_lists: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SCALING_LIST_DATA_PRESENT_FLAG_SET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        pcm: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_PCM_ENABLED_FLAG_SET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        temporal_mvp: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SPS_TEMPORAL_MVP_ENABLED_FLAG_SET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        init_qp: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_INIT_QP_MINUS26_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        weighted:%s%s\n",
+           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_WEIGHTED_PRED_FLAG_SET_BIT_KHR ?
+               " pred" : "",
+           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_WEIGHTED_BIPRED_FLAG_SET_BIT_KHR ?
+               " bipred" : "");
+    av_log(avctx, AV_LOG_VERBOSE, "        parallel_merge_level: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_LOG2_PARALLEL_MERGE_LEVEL_MINUS2_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        sign_data_hiding: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SIGN_DATA_HIDING_ENABLED_FLAG_SET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        transform_skip:%s%s\n",
+           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_TRANSFORM_SKIP_ENABLED_FLAG_SET_BIT_KHR ?
+           " set" : "",
+           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_TRANSFORM_SKIP_ENABLED_FLAG_UNSET_BIT_KHR ?
+           " unset" : "");
+    av_log(avctx, AV_LOG_VERBOSE, "        slice_chroma_qp_offsets: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_FLAG_SET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        transquant_bypass: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_TRANSQUANT_BYPASS_ENABLED_FLAG_SET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        constrained_intra_pred: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_CONSTRAINED_INTRA_PRED_FLAG_SET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        entrypy_coding_sync: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_ENTROPY_CODING_SYNC_ENABLED_FLAG_SET_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        dependent_slice_segment:%s%s\n",
+           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENTS_ENABLED_FLAG_SET_BIT_KHR ?
+               " enabled" : "",
+           enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENT_FLAG_SET_BIT_KHR ?
+               " set" : "");
+    av_log(avctx, AV_LOG_VERBOSE, "        slice_qp_delta: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SLICE_QP_DELTA_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        different_slice_qp_delta: %i\n",
+           !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_DIFFERENT_SLICE_QP_DELTA_BIT_KHR));
+
+    av_log(avctx, AV_LOG_VERBOSE, "    Capability flags:\n");
+    av_log(avctx, AV_LOG_VERBOSE, "        hdr_compliance: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        pred_weight_table_generated: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        row_unaligned_slice: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        different_slice_type: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        b_frame_in_l0_list: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        b_frame_in_l1_list: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        per_pict_type_min_max_qp: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        per_slice_constant_qp: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PER_SLICE_CONSTANT_QP_BIT_KHR));
+    av_log(avctx, AV_LOG_VERBOSE, "        generate_prefix_nalu: %i\n",
+           !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_KHR));
+
+    av_log(avctx, AV_LOG_VERBOSE, "    Capabilities:\n");
+    av_log(avctx, AV_LOG_VERBOSE, "        maxLevelIdc: %i\n",
+           enc->caps.maxLevelIdc);
+    av_log(avctx, AV_LOG_VERBOSE, "        maxSliceCount: %i\n",
+           enc->caps.maxSliceSegmentCount);
+    av_log(avctx, AV_LOG_VERBOSE, "        maxTiles: %ix%i\n",
+           enc->caps.maxTiles.width, enc->caps.maxTiles.height);
+    av_log(avctx, AV_LOG_VERBOSE, "        cbtSizes: 0x%x\n",
+           enc->caps.ctbSizes);
+    av_log(avctx, AV_LOG_VERBOSE, "        transformBlockSizes: 0x%x\n",
+           enc->caps.transformBlockSizes);
+    av_log(avctx, AV_LOG_VERBOSE, "        max(P/B)PictureL0ReferenceCount: %i P's; %i B's\n",
+           enc->caps.maxPPictureL0ReferenceCount,
+           enc->caps.maxBPictureL0ReferenceCount);
+    av_log(avctx, AV_LOG_VERBOSE, "        maxL1ReferenceCount: %i\n",
+           enc->caps.maxL1ReferenceCount);
+    av_log(avctx, AV_LOG_VERBOSE, "        maxSubLayerCount: %i\n",
+           enc->caps.maxSubLayerCount);
+    av_log(avctx, AV_LOG_VERBOSE, "        expectDyadicTemporalLayerPattern: %i\n",
+           enc->caps.expectDyadicTemporalSubLayerPattern);
+    av_log(avctx, AV_LOG_VERBOSE, "        min/max Qp: [%i, %i]\n",
+           enc->caps.minQp, enc->caps.maxQp);
+    av_log(avctx, AV_LOG_VERBOSE, "        prefersGopRemainingFrames: %i\n",
+           enc->caps.prefersGopRemainingFrames);
+    av_log(avctx, AV_LOG_VERBOSE, "        requiresGopRemainingFrames: %i\n",
+           enc->caps.requiresGopRemainingFrames);
+
+    err = init_enc_options(avctx);
+    if (err < 0)
+        return err;
+
+    flags = ctx->codec->flags;
+    if (!enc->caps.maxPPictureL0ReferenceCount &&
+        !enc->caps.maxBPictureL0ReferenceCount &&
+        !enc->caps.maxL1ReferenceCount) {
+        /* Intra-only */
+        flags |= FF_HW_FLAG_INTRA_ONLY;
+        ref_l0 = ref_l1 = 0;
+    } else if (!enc->caps.maxPPictureL0ReferenceCount) {
+        /* No P-frames? How. */
+        base_ctx->p_to_gpb = 1;
+        ref_l0 = enc->caps.maxBPictureL0ReferenceCount;
+        ref_l1 = enc->caps.maxL1ReferenceCount;
+    } else if (!enc->caps.maxBPictureL0ReferenceCount &&
+               !enc->caps.maxL1ReferenceCount) {
+        /* No B-frames */
+        flags &= ~(FF_HW_FLAG_B_PICTURES | FF_HW_FLAG_B_PICTURE_REFERENCES);
+        ref_l0 = enc->caps.maxPPictureL0ReferenceCount;
+        ref_l1 = 0;
+    } else {
+        /* P and B frames */
+        ref_l0 = FFMIN(enc->caps.maxPPictureL0ReferenceCount,
+                       enc->caps.maxBPictureL0ReferenceCount);
+        ref_l1 = enc->caps.maxL1ReferenceCount;
+    }
+
+    err = ff_hw_base_init_gop_structure(base_ctx, avctx, ref_l0, ref_l1,
+                                        flags, 0);
+    if (err < 0)
+        return err;
+
+    base_ctx->output_delay = base_ctx->b_per_p;
+    base_ctx->decode_delay = base_ctx->max_b_depth;
+
+    /* Init CBS */
+    err = ff_cbs_init(&enc->cbs, AV_CODEC_ID_HEVC, avctx);
+    if (err < 0)
+        return err;
+
+    /* Create units and session parameters */
+    err = init_base_units(avctx);
+    if (err < 0)
+        return err;
+
+    /* Write out extradata */
+    err = ff_vulkan_write_global_header(avctx, &enc->common);
+    if (err < 0)
+        return err;
+
+    return 0;
+}
+
+static av_cold int vulkan_encode_h265_close(AVCodecContext *avctx)
+{
+    VulkanEncodeH265Context *enc = avctx->priv_data;
+    ff_vulkan_encode_uninit(&enc->common);
+    return 0;
+}
+
+#define OFFSET(x) offsetof(VulkanEncodeH265Context, x)
+#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
+static const AVOption vulkan_encode_h265_options[] = {
+    HW_BASE_ENCODE_COMMON_OPTIONS,
+    VULKAN_ENCODE_COMMON_OPTIONS,
+
+    { "profile", "Set profile (profile_idc and constraint_set*_flag)",
+      OFFSET(common.opts.profile), AV_OPT_TYPE_INT,
+      { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, 0xffff, FLAGS, .unit = "profile" },
+
+#define PROFILE(name, value)  name, NULL, 0, AV_OPT_TYPE_CONST, \
+      { .i64 = value }, 0, 0, FLAGS, .unit = "profile"
+    { PROFILE("main",               AV_PROFILE_HEVC_MAIN) },
+    { PROFILE("main10",             AV_PROFILE_HEVC_MAIN_10) },
+    { PROFILE("rext",               AV_PROFILE_HEVC_REXT) },
+#undef PROFILE
+
+    { "tier", "Set tier (general_tier_flag)", OFFSET(common.opts.tier), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, .unit = "tier" },
+        { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, .unit = "tier" },
+        { "high", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, .unit = "tier" },
+
+    { "level", "Set level (general_level_idc)",
+      OFFSET(common.opts.level), AV_OPT_TYPE_INT,
+      { .i64 = AV_LEVEL_UNKNOWN }, AV_LEVEL_UNKNOWN, 0xff, FLAGS, .unit = "level" },
+
+#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
+      { .i64 = value }, 0, 0, FLAGS, .unit = "level"
+    { LEVEL("1",    30) },
+    { LEVEL("2",    60) },
+    { LEVEL("2.1",  63) },
+    { LEVEL("3",    90) },
+    { LEVEL("3.1",  93) },
+    { LEVEL("4",   120) },
+    { LEVEL("4.1", 123) },
+    { LEVEL("5",   150) },
+    { LEVEL("5.1", 153) },
+    { LEVEL("5.2", 156) },
+    { LEVEL("6",   180) },
+    { LEVEL("6.1", 183) },
+    { LEVEL("6.2", 186) },
+#undef LEVEL
+
+    { "units", "Set units to include", OFFSET(unit_elems), AV_OPT_TYPE_FLAGS, { .i64 = UNIT_SEI_MASTERING_DISPLAY | UNIT_SEI_CONTENT_LIGHT_LEVEL | UNIT_SEI_A53_CC }, 0, INT_MAX, FLAGS, "units" },
+        { "hdr",        "Include HDR metadata for mastering display colour volume and content light level information", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_SEI_MASTERING_DISPLAY | UNIT_SEI_CONTENT_LIGHT_LEVEL }, INT_MIN, INT_MAX, FLAGS, "units" },
+        { "a53_cc",     "Include A/53 caption data", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_SEI_A53_CC }, INT_MIN, INT_MAX, FLAGS, "units" },
+
+    { NULL },
+};
+
+static const FFCodecDefault vulkan_encode_h265_defaults[] = {
+    { "b",              "0"   },
+    { "bf",             "2"   },
+    { "g",              "300" },
+    { "i_qfactor",      "1"   },
+    { "i_qoffset",      "0"   },
+    { "b_qfactor",      "6/5" },
+    { "b_qoffset",      "0"   },
+    { "qmin",           "-1"  },
+    { "qmax",           "-1"  },
+    { "refs",           "0"   },
+    { NULL },
+};
+
+static const AVClass vulkan_encode_h265_class = {
+    .class_name = "hevc_vulkan",
+    .item_name  = av_default_item_name,
+    .option     = vulkan_encode_h265_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+const FFCodec ff_hevc_vulkan_encoder = {
+    .p.name         = "hevc_vulkan",
+    CODEC_LONG_NAME("H.265/HEVC (Vulkan)"),
+    .p.type         = AVMEDIA_TYPE_VIDEO,
+    .p.id           = AV_CODEC_ID_HEVC,
+    .priv_data_size = sizeof(VulkanEncodeH265Context),
+    .init           = &vulkan_encode_h265_init,
+    FF_CODEC_RECEIVE_PACKET_CB(&ff_vulkan_encode_receive_packet),
+    .close          = &vulkan_encode_h265_close,
+    .p.priv_class   = &vulkan_encode_h265_class,
+    .p.capabilities = AV_CODEC_CAP_DELAY |
+                      AV_CODEC_CAP_HARDWARE |
+                      AV_CODEC_CAP_DR1 |
+                      AV_CODEC_CAP_ENCODER_FLUSH |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
+    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
+    .defaults       = vulkan_encode_h265_defaults,
+    CODEC_PIXFMTS(AV_PIX_FMT_VULKAN),
+    .hw_configs     = ff_vulkan_encode_hw_configs,
+    .p.wrapper_name = "vulkan",
+};
-- 
2.49.1


From eeafc4f977be2d52e6b7015073d143e64fbb5c84 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:36:15 +0000
Subject: [PATCH 079/118] Changing vulkan file directory

---
 libavcodec/vulkan_ffv1.c | 1175 --------------------------------------
 1 file changed, 1175 deletions(-)
 delete mode 100644 libavcodec/vulkan_ffv1.c

diff --git a/libavcodec/vulkan_ffv1.c b/libavcodec/vulkan_ffv1.c
deleted file mode 100644
index b02bc71683..0000000000
--- a/libavcodec/vulkan_ffv1.c
+++ /dev/null
@@ -1,1175 +0,0 @@
-/*
- * Copyright (c) 2024 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "vulkan_decode.h"
-#include "hwaccel_internal.h"
-
-#include "ffv1.h"
-#include "ffv1_vulkan.h"
-#include "libavutil/vulkan_spirv.h"
-#include "libavutil/mem.h"
-
-#define RGB_LINECACHE 2
-
-extern const char *ff_source_common_comp;
-extern const char *ff_source_rangecoder_comp;
-extern const char *ff_source_ffv1_vlc_comp;
-extern const char *ff_source_ffv1_common_comp;
-extern const char *ff_source_ffv1_dec_setup_comp;
-extern const char *ff_source_ffv1_reset_comp;
-extern const char *ff_source_ffv1_dec_comp;
-
-const FFVulkanDecodeDescriptor ff_vk_dec_ffv1_desc = {
-    .codec_id         = AV_CODEC_ID_FFV1,
-    .decode_extension = FF_VK_EXT_PUSH_DESCRIPTOR,
-    .queue_flags      = VK_QUEUE_COMPUTE_BIT,
-};
-
-typedef struct FFv1VulkanDecodePicture {
-    FFVulkanDecodePicture vp;
-
-    AVBufferRef *slice_state;
-    uint32_t plane_state_size;
-    uint32_t slice_state_size;
-    uint32_t slice_data_size;
-
-    AVBufferRef *slice_offset_buf;
-    uint32_t    *slice_offset;
-    int          slice_num;
-
-    AVBufferRef *slice_status_buf;
-    int crc_checked;
-} FFv1VulkanDecodePicture;
-
-typedef struct FFv1VulkanDecodeContext {
-    AVBufferRef *intermediate_frames_ref[2]; /* 16/32 bit */
-
-    FFVulkanShader setup;
-    FFVulkanShader reset[2]; /* AC/Golomb */
-    FFVulkanShader decode[2][2][2]; /* 16/32 bit, AC/Golomb, Normal/RGB */
-
-    FFVkBuffer rangecoder_static_buf;
-    FFVkBuffer quant_buf;
-    FFVkBuffer crc_tab_buf;
-
-    AVBufferPool *slice_state_pool;
-    AVBufferPool *slice_offset_pool;
-    AVBufferPool *slice_status_pool;
-} FFv1VulkanDecodeContext;
-
-typedef struct FFv1VkParameters {
-    VkDeviceAddress slice_data;
-    VkDeviceAddress slice_state;
-
-    int fmt_lut[4];
-    uint32_t img_size[2];
-    uint32_t chroma_shift[2];
-
-    uint32_t plane_state_size;
-    uint32_t crcref;
-    int rct_offset;
-
-    uint8_t extend_lookup[8];
-    uint8_t bits_per_raw_sample;
-    uint8_t quant_table_count;
-    uint8_t version;
-    uint8_t micro_version;
-    uint8_t key_frame;
-    uint8_t planes;
-    uint8_t codec_planes;
-    uint8_t color_planes;
-    uint8_t transparency;
-    uint8_t planar_rgb;
-    uint8_t colorspace;
-    uint8_t ec;
-    uint8_t golomb;
-    uint8_t check_crc;
-    uint8_t padding[3];
-} FFv1VkParameters;
-
-static void add_push_data(FFVulkanShader *shd)
-{
-    GLSLC(0, layout(push_constant, scalar) uniform pushConstants {  );
-    GLSLC(1,    u8buf slice_data;                                   );
-    GLSLC(1,    u8buf slice_state;                                  );
-    GLSLC(0,                                                        );
-    GLSLC(1,    ivec4 fmt_lut;                                      );
-    GLSLC(1,    uvec2 img_size;                                     );
-    GLSLC(1,    uvec2 chroma_shift;                                 );
-    GLSLC(0,                                                        );
-    GLSLC(1,    uint plane_state_size;                              );
-    GLSLC(1,    uint32_t crcref;                                    );
-    GLSLC(1,    int rct_offset;                                     );
-    GLSLC(0,                                                        );
-    GLSLC(1,    uint8_t extend_lookup[8];                           );
-    GLSLC(1,    uint8_t bits_per_raw_sample;                        );
-    GLSLC(1,    uint8_t quant_table_count;                          );
-    GLSLC(1,    uint8_t version;                                    );
-    GLSLC(1,    uint8_t micro_version;                              );
-    GLSLC(1,    uint8_t key_frame;                                  );
-    GLSLC(1,    uint8_t planes;                                     );
-    GLSLC(1,    uint8_t codec_planes;                               );
-    GLSLC(1,    uint8_t color_planes;                               );
-    GLSLC(1,    uint8_t transparency;                               );
-    GLSLC(1,    uint8_t planar_rgb;                                 );
-    GLSLC(1,    uint8_t colorspace;                                 );
-    GLSLC(1,    uint8_t ec;                                         );
-    GLSLC(1,    uint8_t golomb;                                     );
-    GLSLC(1,    uint8_t check_crc;                                  );
-    GLSLC(1,    uint8_t padding[3];                                 );
-    GLSLC(0, };                                                     );
-    ff_vk_shader_add_push_const(shd, 0, sizeof(FFv1VkParameters),
-                                VK_SHADER_STAGE_COMPUTE_BIT);
-}
-
-static int vk_ffv1_start_frame(AVCodecContext          *avctx,
-                               const AVBufferRef       *buffer_ref,
-                               av_unused const uint8_t *buffer,
-                               av_unused uint32_t       size)
-{
-    int err;
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-    FFv1VulkanDecodeContext *fv = ctx->sd_ctx;
-    FFV1Context *f = avctx->priv_data;
-
-    FFv1VulkanDecodePicture *fp = f->hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &fp->vp;
-
-    AVHWFramesContext *hwfc = (AVHWFramesContext *)avctx->hw_frames_ctx->data;
-    enum AVPixelFormat sw_format = hwfc->sw_format;
-
-    int max_contexts;
-    int is_rgb = !(f->colorspace == 0 && sw_format != AV_PIX_FMT_YA8) &&
-                 !(sw_format == AV_PIX_FMT_YA8);
-
-    fp->slice_num = 0;
-
-    max_contexts = 0;
-    for (int i = 0; i < f->quant_table_count; i++)
-        max_contexts = FFMAX(f->context_count[i], max_contexts);
-
-    /* Allocate slice buffer data */
-    if (f->ac == AC_GOLOMB_RICE)
-        fp->plane_state_size = 8;
-    else
-        fp->plane_state_size = CONTEXT_SIZE;
-
-    fp->plane_state_size *= max_contexts;
-    fp->slice_state_size = fp->plane_state_size*f->plane_count;
-
-    fp->slice_data_size = 256; /* Overestimation for the SliceContext struct */
-    fp->slice_state_size += fp->slice_data_size;
-    fp->slice_state_size = FFALIGN(fp->slice_state_size, 8);
-
-    fp->crc_checked = f->ec && (avctx->err_recognition & AV_EF_CRCCHECK);
-
-    /* Host map the input slices data if supported */
-    if (ctx->s.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY)
-        ff_vk_host_map_buffer(&ctx->s, &vp->slices_buf, buffer_ref->data,
-                              buffer_ref,
-                              VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
-                              VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
-
-    /* Allocate slice state data */
-    if (f->picture.f->flags & AV_FRAME_FLAG_KEY) {
-        err = ff_vk_get_pooled_buffer(&ctx->s, &fv->slice_state_pool,
-                                      &fp->slice_state,
-                                      VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
-                                      VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
-                                      NULL, f->slice_count*fp->slice_state_size,
-                                      VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
-        if (err < 0)
-            return err;
-    } else {
-        FFv1VulkanDecodePicture *fpl = f->hwaccel_last_picture_private;
-        fp->slice_state = av_buffer_ref(fpl->slice_state);
-        if (!fp->slice_state)
-            return AVERROR(ENOMEM);
-    }
-
-    /* Allocate slice offsets buffer */
-    err = ff_vk_get_pooled_buffer(&ctx->s, &fv->slice_offset_pool,
-                                  &fp->slice_offset_buf,
-                                  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
-                                  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
-                                  NULL, 2*f->slice_count*sizeof(uint32_t),
-                                  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
-                                  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
-    if (err < 0)
-        return err;
-
-    /* Allocate slice status buffer */
-    err = ff_vk_get_pooled_buffer(&ctx->s, &fv->slice_status_pool,
-                                  &fp->slice_status_buf,
-                                  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
-                                  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
-                                  NULL, 2*f->slice_count*sizeof(uint32_t),
-                                  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
-                                  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
-    if (err < 0)
-        return err;
-
-    /* Prepare frame to be used */
-    err = ff_vk_decode_prepare_frame_sdr(dec, f->picture.f, vp, 1,
-                                         FF_VK_REP_NATIVE, 0);
-    if (err < 0)
-        return err;
-
-    /* Create a temporaty frame for RGB */
-    if (is_rgb) {
-        vp->dpb_frame = av_frame_alloc();
-        if (!vp->dpb_frame)
-            return AVERROR(ENOMEM);
-
-        err = av_hwframe_get_buffer(fv->intermediate_frames_ref[f->use32bit],
-                                    vp->dpb_frame, 0);
-        if (err < 0)
-            return err;
-    }
-
-    return 0;
-}
-
-static int vk_ffv1_decode_slice(AVCodecContext *avctx,
-                                const uint8_t  *data,
-                                uint32_t        size)
-{
-    FFV1Context *f = avctx->priv_data;
-
-    FFv1VulkanDecodePicture *fp = f->hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &fp->vp;
-
-    FFVkBuffer *slice_offset = (FFVkBuffer *)fp->slice_offset_buf->data;
-    FFVkBuffer *slices_buf = vp->slices_buf ? (FFVkBuffer *)vp->slices_buf->data : NULL;
-
-    if (slices_buf && slices_buf->host_ref) {
-        AV_WN32(slice_offset->mapped_mem + (2*fp->slice_num + 0)*sizeof(uint32_t),
-                data - slices_buf->mapped_mem);
-        AV_WN32(slice_offset->mapped_mem + (2*fp->slice_num + 1)*sizeof(uint32_t),
-                size);
-
-        fp->slice_num++;
-    } else {
-        int err = ff_vk_decode_add_slice(avctx, vp, data, size, 0,
-                                         &fp->slice_num,
-                                         (const uint32_t **)&fp->slice_offset);
-        if (err < 0)
-            return err;
-
-        AV_WN32(slice_offset->mapped_mem + (2*(fp->slice_num - 1) + 0)*sizeof(uint32_t),
-                fp->slice_offset[fp->slice_num - 1]);
-        AV_WN32(slice_offset->mapped_mem + (2*(fp->slice_num - 1) + 1)*sizeof(uint32_t),
-                size);
-    }
-
-    return 0;
-}
-
-static int vk_ffv1_end_frame(AVCodecContext *avctx)
-{
-    int err;
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-
-    FFV1Context *f = avctx->priv_data;
-    FFv1VulkanDecodeContext *fv = ctx->sd_ctx;
-    FFv1VkParameters pd;
-    FFv1VkResetParameters pd_reset;
-
-    AVHWFramesContext *hwfc = (AVHWFramesContext *)avctx->hw_frames_ctx->data;
-    enum AVPixelFormat sw_format = hwfc->sw_format;
-
-    int bits = f->avctx->bits_per_raw_sample > 0 ? f->avctx->bits_per_raw_sample : 8;
-    int is_rgb = !(f->colorspace == 0 && sw_format != AV_PIX_FMT_YA8) &&
-                 !(sw_format == AV_PIX_FMT_YA8);
-    int color_planes = av_pix_fmt_desc_get(avctx->sw_pix_fmt)->nb_components;
-
-    FFVulkanShader *reset_shader;
-    FFVulkanShader *decode_shader;
-
-    FFv1VulkanDecodePicture *fp = f->hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &fp->vp;
-
-    FFVkBuffer *slices_buf = (FFVkBuffer *)vp->slices_buf->data;
-    FFVkBuffer *slice_state = (FFVkBuffer *)fp->slice_state->data;
-    FFVkBuffer *slice_offset = (FFVkBuffer *)fp->slice_offset_buf->data;
-    FFVkBuffer *slice_status = (FFVkBuffer *)fp->slice_status_buf->data;
-
-    VkImageView rct_image_views[AV_NUM_DATA_POINTERS];
-
-    AVFrame *decode_dst = is_rgb ? vp->dpb_frame : f->picture.f;
-    VkImageView *decode_dst_view = is_rgb ? rct_image_views : vp->view.out;
-
-    VkImageMemoryBarrier2 img_bar[37];
-    int nb_img_bar = 0;
-    VkBufferMemoryBarrier2 buf_bar[8];
-    int nb_buf_bar = 0;
-
-    FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
-    ff_vk_exec_start(&ctx->s, exec);
-
-    /* Prepare deps */
-    RET(ff_vk_exec_add_dep_frame(&ctx->s, exec, f->picture.f,
-                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
-
-    err = ff_vk_exec_mirror_sem_value(&ctx->s, exec, &vp->sem, &vp->sem_value,
-                                      f->picture.f);
-    if (err < 0)
-        return err;
-
-    if (is_rgb) {
-        RET(ff_vk_create_imageviews(&ctx->s, exec, rct_image_views,
-                                    vp->dpb_frame, FF_VK_REP_NATIVE));
-        RET(ff_vk_exec_add_dep_frame(&ctx->s, exec, vp->dpb_frame,
-                                     VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                     VK_PIPELINE_STAGE_2_CLEAR_BIT));
-        ff_vk_frame_barrier(&ctx->s, exec, decode_dst, img_bar, &nb_img_bar,
-                            VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                            VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                            VK_ACCESS_2_TRANSFER_WRITE_BIT,
-                            VK_IMAGE_LAYOUT_GENERAL,
-                            VK_QUEUE_FAMILY_IGNORED);
-    }
-
-    if (!(f->picture.f->flags & AV_FRAME_FLAG_KEY)) {
-        FFv1VulkanDecodePicture *fpl = f->hwaccel_last_picture_private;
-        FFVulkanDecodePicture *vpl = &fpl->vp;
-
-        /* Wait on the previous frame */
-        RET(ff_vk_exec_add_dep_wait_sem(&ctx->s, exec, vpl->sem, vpl->sem_value,
-                                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT));
-    }
-
-    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &fp->slice_state, 1, 1));
-    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &fp->slice_status_buf, 1, 1));
-    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0));
-    vp->slices_buf = NULL;
-    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &fp->slice_offset_buf, 1, 0));
-    fp->slice_offset_buf = NULL;
-
-    /* Entry barrier for the slice state */
-    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
-        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-        .srcStageMask = slice_state->stage,
-        .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-        .srcAccessMask = slice_state->access,
-        .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
-                         VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
-        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .buffer = slice_state->buf,
-        .offset = 0,
-        .size = fp->slice_data_size*f->slice_count,
-    };
-
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-        .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-        .pImageMemoryBarriers = img_bar,
-        .imageMemoryBarrierCount = nb_img_bar,
-        .pBufferMemoryBarriers = buf_bar,
-        .bufferMemoryBarrierCount = nb_buf_bar,
-    });
-    slice_state->stage = buf_bar[0].dstStageMask;
-    slice_state->access = buf_bar[0].dstAccessMask;
-    nb_buf_bar = 0;
-    nb_img_bar = 0;
-
-    /* Setup shader */
-    ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->setup,
-                                    1, 0, 0,
-                                    slice_state,
-                                    0, fp->slice_data_size*f->slice_count,
-                                    VK_FORMAT_UNDEFINED);
-    ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->setup,
-                                    1, 1, 0,
-                                    slice_offset,
-                                    0, 2*f->slice_count*sizeof(uint32_t),
-                                    VK_FORMAT_UNDEFINED);
-    ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->setup,
-                                    1, 2, 0,
-                                    slice_status,
-                                    0, 2*f->slice_count*sizeof(uint32_t),
-                                    VK_FORMAT_UNDEFINED);
-
-    ff_vk_exec_bind_shader(&ctx->s, exec, &fv->setup);
-    pd = (FFv1VkParameters) {
-        .slice_data = slices_buf->address,
-        .slice_state  = slice_state->address + f->slice_count*fp->slice_data_size,
-
-        .img_size[0] = f->picture.f->width,
-        .img_size[1] = f->picture.f->height,
-        .chroma_shift[0] = f->chroma_h_shift,
-        .chroma_shift[1] = f->chroma_v_shift,
-
-        .plane_state_size = fp->plane_state_size,
-        .crcref = f->crcref,
-        .rct_offset = 1 << bits,
-
-        .bits_per_raw_sample = bits,
-        .quant_table_count = f->quant_table_count,
-        .version = f->version,
-        .micro_version = f->micro_version,
-        .key_frame = f->picture.f->flags & AV_FRAME_FLAG_KEY,
-        .planes = av_pix_fmt_count_planes(sw_format),
-        .codec_planes = f->plane_count,
-        .color_planes = color_planes,
-        .transparency = f->transparency,
-        .planar_rgb = ff_vk_mt_is_np_rgb(sw_format) &&
-                      (ff_vk_count_images((AVVkFrame *)f->picture.f->data[0]) > 1),
-        .colorspace = f->colorspace,
-        .ec = f->ec,
-        .golomb = f->ac == AC_GOLOMB_RICE,
-        .check_crc = !!(avctx->err_recognition & AV_EF_CRCCHECK),
-    };
-    for (int i = 0; i < f->quant_table_count; i++)
-        pd.extend_lookup[i] = (f->quant_tables[i][3][127] != 0) ||
-                              (f->quant_tables[i][4][127] != 0);
-
-
-    /* For some reason the C FFv1 encoder/decoder treats these differently */
-    if (sw_format == AV_PIX_FMT_GBRP10 || sw_format == AV_PIX_FMT_GBRP12 ||
-        sw_format == AV_PIX_FMT_GBRP14)
-        memcpy(pd.fmt_lut, (int [4]) { 2, 1, 0, 3 }, 4*sizeof(int));
-    else if (sw_format == AV_PIX_FMT_X2BGR10)
-        memcpy(pd.fmt_lut, (int [4]) { 0, 2, 1, 3 }, 4*sizeof(int));
-    else
-        ff_vk_set_perm(sw_format, pd.fmt_lut, 0);
-
-    ff_vk_shader_update_push_const(&ctx->s, exec, &fv->setup,
-                                   VK_SHADER_STAGE_COMPUTE_BIT,
-                                   0, sizeof(pd), &pd);
-
-    vk->CmdDispatch(exec->buf, f->num_h_slices, f->num_v_slices, 1);
-
-    if (is_rgb) {
-        AVVkFrame *vkf = (AVVkFrame *)vp->dpb_frame->data[0];
-        for (int i = 0; i < color_planes; i++)
-            vk->CmdClearColorImage(exec->buf, vkf->img[i], VK_IMAGE_LAYOUT_GENERAL,
-                                   &((VkClearColorValue) { 0 }),
-                                   1, &((VkImageSubresourceRange) {
-                                       .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
-                                       .levelCount = 1,
-                                       .layerCount = 1,
-                                   }));
-    }
-
-    /* Reset shader */
-    reset_shader = &fv->reset[f->ac == AC_GOLOMB_RICE];
-    ff_vk_shader_update_desc_buffer(&ctx->s, exec, reset_shader,
-                                    1, 0, 0,
-                                    slice_state,
-                                    0, fp->slice_data_size*f->slice_count,
-                                    VK_FORMAT_UNDEFINED);
-
-    ff_vk_exec_bind_shader(&ctx->s, exec, reset_shader);
-
-    pd_reset = (FFv1VkResetParameters) {
-        .slice_state = slice_state->address + f->slice_count*fp->slice_data_size,
-        .plane_state_size = fp->plane_state_size,
-        .codec_planes = f->plane_count,
-        .key_frame = f->picture.f->flags & AV_FRAME_FLAG_KEY,
-        .version = f->version,
-        .micro_version = f->micro_version,
-    };
-    for (int i = 0; i < f->quant_table_count; i++)
-        pd_reset.context_count[i] = f->context_count[i];
-
-    ff_vk_shader_update_push_const(&ctx->s, exec, reset_shader,
-                                   VK_SHADER_STAGE_COMPUTE_BIT,
-                                   0, sizeof(pd_reset), &pd_reset);
-
-    /* Sync between setup and reset shaders */
-    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
-        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-        .srcStageMask = slice_state->stage,
-        .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-        .srcAccessMask = slice_state->access,
-        .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT,
-        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .buffer = slice_state->buf,
-        .offset = 0,
-        .size = fp->slice_data_size*f->slice_count,
-    };
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-        .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-        .pImageMemoryBarriers = img_bar,
-        .imageMemoryBarrierCount = nb_img_bar,
-        .pBufferMemoryBarriers = buf_bar,
-        .bufferMemoryBarrierCount = nb_buf_bar,
-    });
-    slice_state->stage = buf_bar[0].dstStageMask;
-    slice_state->access = buf_bar[0].dstAccessMask;
-    nb_buf_bar = 0;
-    nb_img_bar = 0;
-
-    vk->CmdDispatch(exec->buf, f->num_h_slices, f->num_v_slices,
-                    f->plane_count);
-
-    /* Decode */
-    decode_shader = &fv->decode[f->use32bit][f->ac == AC_GOLOMB_RICE][is_rgb];
-    ff_vk_shader_update_desc_buffer(&ctx->s, exec, decode_shader,
-                                    1, 0, 0,
-                                    slice_state,
-                                    0, fp->slice_data_size*f->slice_count,
-                                    VK_FORMAT_UNDEFINED);
-    ff_vk_shader_update_img_array(&ctx->s, exec, decode_shader,
-                                  decode_dst, decode_dst_view,
-                                  1, 1,
-                                  VK_IMAGE_LAYOUT_GENERAL,
-                                  VK_NULL_HANDLE);
-    ff_vk_shader_update_desc_buffer(&ctx->s, exec, decode_shader,
-                                    1, 2, 0,
-                                    slice_status,
-                                    0, 2*f->slice_count*sizeof(uint32_t),
-                                    VK_FORMAT_UNDEFINED);
-    if (is_rgb)
-        ff_vk_shader_update_img_array(&ctx->s, exec, decode_shader,
-                                      f->picture.f, vp->view.out,
-                                      1, 3,
-                                      VK_IMAGE_LAYOUT_GENERAL,
-                                      VK_NULL_HANDLE);
-
-    ff_vk_exec_bind_shader(&ctx->s, exec, decode_shader);
-    ff_vk_shader_update_push_const(&ctx->s, exec, decode_shader,
-                                   VK_SHADER_STAGE_COMPUTE_BIT,
-                                   0, sizeof(pd), &pd);
-
-    /* Sync between reset and decode shaders */
-    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
-        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
-        .srcStageMask = slice_state->stage,
-        .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-        .srcAccessMask = slice_state->access,
-        .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
-                         VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
-        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
-        .buffer = slice_state->buf,
-        .offset = fp->slice_data_size*f->slice_count,
-        .size = f->slice_count*(fp->slice_state_size - fp->slice_data_size),
-    };
-
-    /* Input frame barrier */
-    ff_vk_frame_barrier(&ctx->s, exec, f->picture.f, img_bar, &nb_img_bar,
-                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                        VK_ACCESS_SHADER_WRITE_BIT |
-                        (!is_rgb ? VK_ACCESS_SHADER_READ_BIT : 0),
-                        VK_IMAGE_LAYOUT_GENERAL,
-                        VK_QUEUE_FAMILY_IGNORED);
-    if (is_rgb)
-        ff_vk_frame_barrier(&ctx->s, exec, vp->dpb_frame, img_bar, &nb_img_bar,
-                            VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                            VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
-                            VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
-                            VK_IMAGE_LAYOUT_GENERAL,
-                            VK_QUEUE_FAMILY_IGNORED);
-
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-        .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-        .pImageMemoryBarriers = img_bar,
-        .imageMemoryBarrierCount = nb_img_bar,
-        .pBufferMemoryBarriers = buf_bar,
-        .bufferMemoryBarrierCount = nb_buf_bar,
-    });
-    slice_state->stage = buf_bar[0].dstStageMask;
-    slice_state->access = buf_bar[0].dstAccessMask;
-    nb_img_bar = 0;
-    nb_buf_bar = 0;
-
-    vk->CmdDispatch(exec->buf, f->num_h_slices, f->num_v_slices, 1);
-
-    err = ff_vk_exec_submit(&ctx->s, exec);
-    if (err < 0)
-        return err;
-
-    /* We don't need the temporary frame after decoding */
-    av_frame_free(&vp->dpb_frame);
-
-fail:
-    return 0;
-}
-
-static void define_shared_code(FFVulkanShader *shd, int use32bit)
-{
-    int smp_bits = use32bit ? 32 : 16;
-
-    GLSLC(0, #define DECODE                                              );
-
-    av_bprintf(&shd->src, "#define RGB_LINECACHE %i\n"                   ,RGB_LINECACHE);
-    av_bprintf(&shd->src, "#define CONTEXT_SIZE %i\n"                    ,CONTEXT_SIZE);
-    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_MASK 0x%x\n"          ,MAX_QUANT_TABLE_MASK);
-
-    GLSLF(0, #define TYPE int%i_t                                        ,smp_bits);
-    GLSLF(0, #define VTYPE2 i%ivec2                                      ,smp_bits);
-    GLSLF(0, #define VTYPE3 i%ivec3                                      ,smp_bits);
-    GLSLD(ff_source_rangecoder_comp);
-    GLSLD(ff_source_ffv1_common_comp);
-}
-
-static int init_setup_shader(FFV1Context *f, FFVulkanContext *s,
-                             FFVkExecPool *pool, FFVkSPIRVCompiler *spv,
-                             FFVulkanShader *shd)
-{
-    int err;
-    FFVulkanDescriptorSetBinding *desc_set;
-
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-
-    RET(ff_vk_shader_init(s, shd, "ffv1_dec_setup",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          (const char *[]) { "GL_EXT_buffer_reference",
-                                             "GL_EXT_buffer_reference2" }, 2,
-                          1, 1, 1,
-                          0));
-
-    /* Common codec header */
-    GLSLD(ff_source_common_comp);
-
-    add_push_data(shd);
-
-    av_bprintf(&shd->src, "#define MAX_QUANT_TABLES %i\n", MAX_QUANT_TABLES);
-    av_bprintf(&shd->src, "#define MAX_CONTEXT_INPUTS %i\n", MAX_CONTEXT_INPUTS);
-    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_SIZE %i\n", MAX_QUANT_TABLE_SIZE);
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "rangecoder_static_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "uint8_t zero_one_state[512];",
-        },
-        {
-            .name        = "crc_ieee_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "uint32_t crc_ieee[256];",
-        },
-        {
-            .name        = "quant_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "int16_t quant_table[MAX_QUANT_TABLES]"
-                           "[MAX_CONTEXT_INPUTS][MAX_QUANT_TABLE_SIZE];",
-        },
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(s, shd, desc_set, 3, 1, 0));
-
-    define_shared_code(shd, 0 /* Irrelevant */);
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "slice_data_buf",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "SliceContext slice_ctx",
-            .buf_elems   = f->max_slice_count,
-        },
-        {
-            .name        = "slice_offsets_buf",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_quali   = "readonly",
-            .buf_content = "uint32_t slice_offsets",
-            .buf_elems   = 2*f->max_slice_count,
-        },
-        {
-            .name        = "slice_status_buf",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_quali   = "writeonly",
-            .buf_content = "uint32_t slice_status",
-            .buf_elems   = 2*f->max_slice_count,
-        },
-    };
-    RET(ff_vk_shader_add_descriptor_set(s, shd, desc_set, 3, 0, 0));
-
-    GLSLD(ff_source_ffv1_dec_setup_comp);
-
-    RET(spv->compile_shader(s, spv, shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(s, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(s, pool, shd));
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-
-    return err;
-}
-
-static int init_reset_shader(FFV1Context *f, FFVulkanContext *s,
-                             FFVkExecPool *pool, FFVkSPIRVCompiler *spv,
-                             FFVulkanShader *shd, int ac)
-{
-    int err;
-    FFVulkanDescriptorSetBinding *desc_set;
-
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    int wg_dim = FFMIN(s->props.properties.limits.maxComputeWorkGroupSize[0], 1024);
-
-    RET(ff_vk_shader_init(s, shd, "ffv1_dec_reset",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          (const char *[]) { "GL_EXT_buffer_reference",
-                                             "GL_EXT_buffer_reference2" }, 2,
-                          wg_dim, 1, 1,
-                          0));
-
-    if (ac == AC_GOLOMB_RICE)
-        av_bprintf(&shd->src, "#define GOLOMB\n");
-
-    /* Common codec header */
-    GLSLD(ff_source_common_comp);
-
-    GLSLC(0, layout(push_constant, scalar) uniform pushConstants {             );
-    GLSLF(1,    uint context_count[%i];                                        ,MAX_QUANT_TABLES);
-    GLSLC(1,    u8buf slice_state;                                             );
-    GLSLC(1,    uint plane_state_size;                                         );
-    GLSLC(1,    uint8_t codec_planes;                                          );
-    GLSLC(1,    uint8_t key_frame;                                             );
-    GLSLC(1,    uint8_t version;                                               );
-    GLSLC(1,    uint8_t micro_version;                                         );
-    GLSLC(1,    uint8_t padding[1];                                            );
-    GLSLC(0, };                                                                );
-    ff_vk_shader_add_push_const(shd, 0, sizeof(FFv1VkResetParameters),
-                                VK_SHADER_STAGE_COMPUTE_BIT);
-
-    av_bprintf(&shd->src, "#define MAX_QUANT_TABLES %i\n", MAX_QUANT_TABLES);
-    av_bprintf(&shd->src, "#define MAX_CONTEXT_INPUTS %i\n", MAX_CONTEXT_INPUTS);
-    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_SIZE %i\n", MAX_QUANT_TABLE_SIZE);
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "rangecoder_static_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "uint8_t zero_one_state[512];",
-        },
-        {
-            .name        = "quant_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "int16_t quant_table[MAX_QUANT_TABLES]"
-                           "[MAX_CONTEXT_INPUTS][MAX_QUANT_TABLE_SIZE];",
-        },
-    };
-    RET(ff_vk_shader_add_descriptor_set(s, shd, desc_set, 2, 1, 0));
-
-    define_shared_code(shd, 0 /* Bit depth irrelevant for the reset shader */);
-    if (ac == AC_GOLOMB_RICE)
-        GLSLD(ff_source_ffv1_vlc_comp);
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "slice_data_buf",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .mem_quali   = "readonly",
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "SliceContext slice_ctx",
-            .buf_elems   = f->max_slice_count,
-        },
-    };
-    RET(ff_vk_shader_add_descriptor_set(s, shd, desc_set, 1, 0, 0));
-
-    GLSLD(ff_source_ffv1_reset_comp);
-
-    RET(spv->compile_shader(s, spv, shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(s, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(s, pool, shd));
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-
-    return err;
-}
-
-static int init_decode_shader(FFV1Context *f, FFVulkanContext *s,
-                              FFVkExecPool *pool, FFVkSPIRVCompiler *spv,
-                              FFVulkanShader *shd,
-                              AVHWFramesContext *dec_frames_ctx,
-                              AVHWFramesContext *out_frames_ctx,
-                              int use32bit, int ac, int rgb)
-{
-    int err;
-    FFVulkanDescriptorSetBinding *desc_set;
-
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-    int use_cached_reader = ac != AC_GOLOMB_RICE &&
-                            s->driver_props.driverID == VK_DRIVER_ID_MESA_RADV;
-
-    RET(ff_vk_shader_init(s, shd, "ffv1_dec",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          (const char *[]) { "GL_EXT_buffer_reference",
-                                             "GL_EXT_buffer_reference2" }, 2,
-                          use_cached_reader ? CONTEXT_SIZE : 1, 1, 1,
-                          0));
-
-    if (ac == AC_GOLOMB_RICE)
-        av_bprintf(&shd->src, "#define GOLOMB\n");
-
-    if (rgb)
-        av_bprintf(&shd->src, "#define RGB\n");
-
-    if (use_cached_reader)
-        av_bprintf(&shd->src, "#define CACHED_SYMBOL_READER 1\n");
-
-    /* Common codec header */
-    GLSLD(ff_source_common_comp);
-
-    add_push_data(shd);
-
-    av_bprintf(&shd->src, "#define MAX_QUANT_TABLES %i\n", MAX_QUANT_TABLES);
-    av_bprintf(&shd->src, "#define MAX_CONTEXT_INPUTS %i\n", MAX_CONTEXT_INPUTS);
-    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_SIZE %i\n", MAX_QUANT_TABLE_SIZE);
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "rangecoder_static_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "uint8_t zero_one_state[512];",
-        },
-        {
-            .name        = "quant_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "int16_t quant_table[MAX_QUANT_TABLES]"
-                           "[MAX_CONTEXT_INPUTS][MAX_QUANT_TABLE_SIZE];",
-        },
-    };
-
-    RET(ff_vk_shader_add_descriptor_set(s, shd, desc_set, 2, 1, 0));
-
-    define_shared_code(shd, use32bit);
-    if (ac == AC_GOLOMB_RICE)
-        GLSLD(ff_source_ffv1_vlc_comp);
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "slice_data_buf",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .buf_content = "SliceContext slice_ctx",
-            .buf_elems   = f->max_slice_count,
-        },
-        {
-            .name       = "dec",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .dimensions = 2,
-            .mem_layout = ff_vk_shader_rep_fmt(dec_frames_ctx->sw_format,
-                                               FF_VK_REP_NATIVE),
-            .elems      = av_pix_fmt_count_planes(dec_frames_ctx->sw_format),
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-        {
-            .name        = "slice_status_buf",
-            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_quali   = "writeonly",
-            .buf_content = "uint32_t slice_status",
-            .buf_elems   = 2*f->max_slice_count,
-        },
-        {
-            .name       = "dst",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .dimensions = 2,
-            .mem_layout = ff_vk_shader_rep_fmt(out_frames_ctx->sw_format,
-                                               FF_VK_REP_NATIVE),
-            .mem_quali  = "writeonly",
-            .elems      = av_pix_fmt_count_planes(out_frames_ctx->sw_format),
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-    };
-    RET(ff_vk_shader_add_descriptor_set(s, shd, desc_set, 3 + rgb, 0, 0));
-
-    GLSLD(ff_source_ffv1_dec_comp);
-
-    RET(spv->compile_shader(s, spv, shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(s, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(s, pool, shd));
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-
-    return err;
-}
-
-static int init_indirect(AVCodecContext *avctx, FFVulkanContext *s,
-                         AVBufferRef **dst, enum AVPixelFormat sw_format)
-{
-    int err;
-    AVHWFramesContext *frames_ctx;
-    AVVulkanFramesContext *vk_frames;
-    FFV1Context *f = avctx->priv_data;
-
-    *dst = av_hwframe_ctx_alloc(s->device_ref);
-    if (!(*dst))
-        return AVERROR(ENOMEM);
-
-    frames_ctx = (AVHWFramesContext *)((*dst)->data);
-    frames_ctx->format    = AV_PIX_FMT_VULKAN;
-    frames_ctx->sw_format = sw_format;
-    frames_ctx->width     = s->frames->width;
-    frames_ctx->height    = f->num_v_slices*RGB_LINECACHE;
-
-    vk_frames = frames_ctx->hwctx;
-    vk_frames->tiling    = VK_IMAGE_TILING_OPTIMAL;
-    vk_frames->img_flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
-    vk_frames->usage     = VK_IMAGE_USAGE_STORAGE_BIT |
-                           VK_IMAGE_USAGE_TRANSFER_DST_BIT;
-
-    err = av_hwframe_ctx_init(*dst);
-    if (err < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to initialize frame pool with format %s: %s\n",
-               av_get_pix_fmt_name(sw_format), av_err2str(err));
-        av_buffer_unref(dst);
-        return err;
-    }
-
-    return 0;
-}
-
-static void vk_decode_ffv1_uninit(FFVulkanDecodeShared *ctx)
-{
-    FFv1VulkanDecodeContext *fv = ctx->sd_ctx;
-
-    ff_vk_shader_free(&ctx->s, &fv->setup);
-
-    for (int i = 0; i < 2; i++) /* 16/32 bit */
-        av_buffer_unref(&fv->intermediate_frames_ref[i]);
-
-    for (int i = 0; i < 2; i++) /* AC/Golomb */
-        ff_vk_shader_free(&ctx->s, &fv->reset[i]);
-
-    for (int i = 0; i < 2; i++) /* 16/32 bit */
-        for (int j = 0; j < 2; j++) /* AC/Golomb */
-            for (int k = 0; k < 2; k++) /* Normal/RGB */
-                ff_vk_shader_free(&ctx->s, &fv->decode[i][j][k]);
-
-    ff_vk_free_buf(&ctx->s, &fv->quant_buf);
-    ff_vk_free_buf(&ctx->s, &fv->rangecoder_static_buf);
-    ff_vk_free_buf(&ctx->s, &fv->crc_tab_buf);
-
-    av_buffer_pool_uninit(&fv->slice_state_pool);
-    av_buffer_pool_uninit(&fv->slice_offset_pool);
-    av_buffer_pool_uninit(&fv->slice_status_pool);
-
-    av_freep(&fv);
-}
-
-static int vk_decode_ffv1_init(AVCodecContext *avctx)
-{
-    int err;
-    FFV1Context *f = avctx->priv_data;
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = NULL;
-    FFv1VulkanDecodeContext *fv;
-    FFVkSPIRVCompiler *spv;
-
-    if (f->version < 3 ||
-        (f->version == 4 && f->micro_version > 3))
-        return AVERROR(ENOTSUP);
-
-    spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    err = ff_vk_decode_init(avctx);
-    if (err < 0)
-        return err;
-    ctx = dec->shared_ctx;
-
-    fv = ctx->sd_ctx = av_mallocz(sizeof(*fv));
-    if (!fv) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    ctx->sd_ctx_free = &vk_decode_ffv1_uninit;
-
-    /* Intermediate frame pool for RCT */
-    for (int i = 0; i < 2; i++) { /* 16/32 bit */
-        RET(init_indirect(avctx, &ctx->s, &fv->intermediate_frames_ref[i],
-                          i ? AV_PIX_FMT_GBRAP32 : AV_PIX_FMT_GBRAP16));
-    }
-
-    /* Setup shader */
-    RET(init_setup_shader(f, &ctx->s, &ctx->exec_pool, spv, &fv->setup));
-
-    /* Reset shaders */
-    for (int i = 0; i < 2; i++) { /* AC/Golomb */
-        RET(init_reset_shader(f, &ctx->s, &ctx->exec_pool,
-                              spv, &fv->reset[i], !i ? AC_RANGE_CUSTOM_TAB : 0));
-    }
-
-    /* Decode shaders */
-    for (int i = 0; i < 2; i++) { /* 16/32 bit */
-        for (int j = 0; j < 2; j++) { /* AC/Golomb */
-            for (int k = 0; k < 2; k++) { /* Normal/RGB */
-                AVHWFramesContext *dec_frames_ctx;
-                dec_frames_ctx = k ? (AVHWFramesContext *)fv->intermediate_frames_ref[i]->data :
-                                     (AVHWFramesContext *)avctx->hw_frames_ctx->data;
-                RET(init_decode_shader(f, &ctx->s, &ctx->exec_pool,
-                                       spv, &fv->decode[i][j][k],
-                                       dec_frames_ctx,
-                                       (AVHWFramesContext *)avctx->hw_frames_ctx->data,
-                                       i,
-                                       !j ? AC_RANGE_CUSTOM_TAB : AC_GOLOMB_RICE,
-                                       k));
-            }
-        }
-    }
-
-    /* Range coder data */
-    RET(ff_ffv1_vk_init_state_transition_data(&ctx->s,
-                                              &fv->rangecoder_static_buf,
-                                              f));
-
-    /* Quantization table data */
-    RET(ff_ffv1_vk_init_quant_table_data(&ctx->s,
-                                         &fv->quant_buf,
-                                         f));
-
-    /* CRC table buffer */
-    RET(ff_ffv1_vk_init_crc_table_data(&ctx->s,
-                                       &fv->crc_tab_buf,
-                                       f));
-
-    /* Update setup global descriptors */
-    RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
-                                        &fv->setup, 0, 0, 0,
-                                        &fv->rangecoder_static_buf,
-                                        0, fv->rangecoder_static_buf.size,
-                                        VK_FORMAT_UNDEFINED));
-    RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
-                                        &fv->setup, 0, 1, 0,
-                                        &fv->crc_tab_buf,
-                                        0, fv->crc_tab_buf.size,
-                                        VK_FORMAT_UNDEFINED));
-
-    /* Update decode global descriptors */
-    for (int i = 0; i < 2; i++) { /* 16/32 bit */
-        for (int j = 0; j < 2; j++) { /* AC/Golomb */
-            for (int k = 0; k < 2; k++) { /* Normal/RGB */
-                RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
-                                                    &fv->decode[i][j][k], 0, 0, 0,
-                                                    &fv->rangecoder_static_buf,
-                                                    0, fv->rangecoder_static_buf.size,
-                                                    VK_FORMAT_UNDEFINED));
-                RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
-                                                    &fv->decode[i][j][k], 0, 1, 0,
-                                                    &fv->quant_buf,
-                                                    0, fv->quant_buf.size,
-                                                    VK_FORMAT_UNDEFINED));
-            }
-        }
-    }
-
-fail:
-    spv->uninit(&spv);
-
-    return err;
-}
-
-static void vk_ffv1_free_frame_priv(AVRefStructOpaque _hwctx, void *data)
-{
-    AVHWDeviceContext *dev_ctx = _hwctx.nc;
-    AVVulkanDeviceContext *hwctx = dev_ctx->hwctx;
-
-    FFv1VulkanDecodePicture *fp = data;
-    FFVulkanDecodePicture *vp = &fp->vp;
-    FFVkBuffer *slice_status = (FFVkBuffer *)fp->slice_status_buf->data;
-
-    ff_vk_decode_free_frame(dev_ctx, vp);
-
-    /* Invalidate slice/output data if needed */
-    if (!(slice_status->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
-        VkMappedMemoryRange invalidate_data = {
-            .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
-            .memory = slice_status->mem,
-            .offset = 0,
-            .size = 2*fp->slice_num*sizeof(uint32_t),
-        };
-        vp->invalidate_memory_ranges(hwctx->act_dev,
-                                     1, &invalidate_data);
-    }
-
-    for (int i = 0; i < fp->slice_num; i++) {
-        uint32_t crc_res = 0;
-        if (fp->crc_checked)
-            crc_res = AV_RN32(slice_status->mapped_mem + 2*i*sizeof(uint32_t) + 0);
-        uint32_t status = AV_RN32(slice_status->mapped_mem + 2*i*sizeof(uint32_t) + 4);
-        if (status || crc_res)
-            av_log(dev_ctx, AV_LOG_ERROR, "Slice %i status: 0x%x, CRC 0x%x\n",
-                   i, status, crc_res);
-    }
-
-    av_buffer_unref(&vp->slices_buf);
-    av_buffer_unref(&fp->slice_state);
-    av_buffer_unref(&fp->slice_offset_buf);
-    av_buffer_unref(&fp->slice_status_buf);
-}
-
-const FFHWAccel ff_ffv1_vulkan_hwaccel = {
-    .p.name                = "ffv1_vulkan",
-    .p.type                = AVMEDIA_TYPE_VIDEO,
-    .p.id                  = AV_CODEC_ID_FFV1,
-    .p.pix_fmt             = AV_PIX_FMT_VULKAN,
-    .start_frame           = &vk_ffv1_start_frame,
-    .decode_slice          = &vk_ffv1_decode_slice,
-    .end_frame             = &vk_ffv1_end_frame,
-    .free_frame_priv       = &vk_ffv1_free_frame_priv,
-    .frame_priv_data_size  = sizeof(FFv1VulkanDecodePicture),
-    .init                  = &vk_decode_ffv1_init,
-    .update_thread_context = &ff_vk_update_thread_context,
-    .decode_params         = &ff_vk_params_invalidate,
-    .flush                 = &ff_vk_decode_flush,
-    .uninit                = &ff_vk_decode_uninit,
-    .frame_params          = &ff_vk_frame_params,
-    .priv_data_size        = sizeof(FFVulkanDecodeContext),
-    .caps_internal         = HWACCEL_CAP_ASYNC_SAFE | HWACCEL_CAP_THREAD_SAFE,
-};
-- 
2.49.1


From 841a4eb1e1f486510a7165168f56acbe1e73b0f1 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:36:48 +0000
Subject: [PATCH 080/118] Changing vulkan file directory

---
 libavcodec/vulkan/vulkan_ffv1.c | 1175 +++++++++++++++++++++++++++++++
 1 file changed, 1175 insertions(+)
 create mode 100644 libavcodec/vulkan/vulkan_ffv1.c

diff --git a/libavcodec/vulkan/vulkan_ffv1.c b/libavcodec/vulkan/vulkan_ffv1.c
new file mode 100644
index 0000000000..5bc5c84a57
--- /dev/null
+++ b/libavcodec/vulkan/vulkan_ffv1.c
@@ -0,0 +1,1175 @@
+/*
+ * Copyright (c) 2024 Lynne <dev@lynne.ee>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "vulkan_decode.h"
+#include "libavcodec/hwaccel_internal.h"
+
+#include "libavcodec/ffv1.h"
+#include "ffv1_vulkan.h"
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+#include "libavutil/mem.h"
+
+#define RGB_LINECACHE 2
+
+extern const char *ff_source_common_comp;
+extern const char *ff_source_rangecoder_comp;
+extern const char *ff_source_ffv1_vlc_comp;
+extern const char *ff_source_ffv1_common_comp;
+extern const char *ff_source_ffv1_dec_setup_comp;
+extern const char *ff_source_ffv1_reset_comp;
+extern const char *ff_source_ffv1_dec_comp;
+
+const FFVulkanDecodeDescriptor ff_vk_dec_ffv1_desc = {
+    .codec_id         = AV_CODEC_ID_FFV1,
+    .decode_extension = FF_VK_EXT_PUSH_DESCRIPTOR,
+    .queue_flags      = VK_QUEUE_COMPUTE_BIT,
+};
+
+typedef struct FFv1VulkanDecodePicture {
+    FFVulkanDecodePicture vp;
+
+    AVBufferRef *slice_state;
+    uint32_t plane_state_size;
+    uint32_t slice_state_size;
+    uint32_t slice_data_size;
+
+    AVBufferRef *slice_offset_buf;
+    uint32_t    *slice_offset;
+    int          slice_num;
+
+    AVBufferRef *slice_status_buf;
+    int crc_checked;
+} FFv1VulkanDecodePicture;
+
+typedef struct FFv1VulkanDecodeContext {
+    AVBufferRef *intermediate_frames_ref[2]; /* 16/32 bit */
+
+    FFVulkanShader setup;
+    FFVulkanShader reset[2]; /* AC/Golomb */
+    FFVulkanShader decode[2][2][2]; /* 16/32 bit, AC/Golomb, Normal/RGB */
+
+    FFVkBuffer rangecoder_static_buf;
+    FFVkBuffer quant_buf;
+    FFVkBuffer crc_tab_buf;
+
+    AVBufferPool *slice_state_pool;
+    AVBufferPool *slice_offset_pool;
+    AVBufferPool *slice_status_pool;
+} FFv1VulkanDecodeContext;
+
+typedef struct FFv1VkParameters {
+    VkDeviceAddress slice_data;
+    VkDeviceAddress slice_state;
+
+    int fmt_lut[4];
+    uint32_t img_size[2];
+    uint32_t chroma_shift[2];
+
+    uint32_t plane_state_size;
+    uint32_t crcref;
+    int rct_offset;
+
+    uint8_t extend_lookup[8];
+    uint8_t bits_per_raw_sample;
+    uint8_t quant_table_count;
+    uint8_t version;
+    uint8_t micro_version;
+    uint8_t key_frame;
+    uint8_t planes;
+    uint8_t codec_planes;
+    uint8_t color_planes;
+    uint8_t transparency;
+    uint8_t planar_rgb;
+    uint8_t colorspace;
+    uint8_t ec;
+    uint8_t golomb;
+    uint8_t check_crc;
+    uint8_t padding[3];
+} FFv1VkParameters;
+
+static void add_push_data(FFVulkanShader *shd)
+{
+    GLSLC(0, layout(push_constant, scalar) uniform pushConstants {  );
+    GLSLC(1,    u8buf slice_data;                                   );
+    GLSLC(1,    u8buf slice_state;                                  );
+    GLSLC(0,                                                        );
+    GLSLC(1,    ivec4 fmt_lut;                                      );
+    GLSLC(1,    uvec2 img_size;                                     );
+    GLSLC(1,    uvec2 chroma_shift;                                 );
+    GLSLC(0,                                                        );
+    GLSLC(1,    uint plane_state_size;                              );
+    GLSLC(1,    uint32_t crcref;                                    );
+    GLSLC(1,    int rct_offset;                                     );
+    GLSLC(0,                                                        );
+    GLSLC(1,    uint8_t extend_lookup[8];                           );
+    GLSLC(1,    uint8_t bits_per_raw_sample;                        );
+    GLSLC(1,    uint8_t quant_table_count;                          );
+    GLSLC(1,    uint8_t version;                                    );
+    GLSLC(1,    uint8_t micro_version;                              );
+    GLSLC(1,    uint8_t key_frame;                                  );
+    GLSLC(1,    uint8_t planes;                                     );
+    GLSLC(1,    uint8_t codec_planes;                               );
+    GLSLC(1,    uint8_t color_planes;                               );
+    GLSLC(1,    uint8_t transparency;                               );
+    GLSLC(1,    uint8_t planar_rgb;                                 );
+    GLSLC(1,    uint8_t colorspace;                                 );
+    GLSLC(1,    uint8_t ec;                                         );
+    GLSLC(1,    uint8_t golomb;                                     );
+    GLSLC(1,    uint8_t check_crc;                                  );
+    GLSLC(1,    uint8_t padding[3];                                 );
+    GLSLC(0, };                                                     );
+    ff_vk_shader_add_push_const(shd, 0, sizeof(FFv1VkParameters),
+                                VK_SHADER_STAGE_COMPUTE_BIT);
+}
+
+static int vk_ffv1_start_frame(AVCodecContext          *avctx,
+                               const AVBufferRef       *buffer_ref,
+                               av_unused const uint8_t *buffer,
+                               av_unused uint32_t       size)
+{
+    int err;
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+    FFv1VulkanDecodeContext *fv = ctx->sd_ctx;
+    FFV1Context *f = avctx->priv_data;
+
+    FFv1VulkanDecodePicture *fp = f->hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &fp->vp;
+
+    AVHWFramesContext *hwfc = (AVHWFramesContext *)avctx->hw_frames_ctx->data;
+    enum AVPixelFormat sw_format = hwfc->sw_format;
+
+    int max_contexts;
+    int is_rgb = !(f->colorspace == 0 && sw_format != AV_PIX_FMT_YA8) &&
+                 !(sw_format == AV_PIX_FMT_YA8);
+
+    fp->slice_num = 0;
+
+    max_contexts = 0;
+    for (int i = 0; i < f->quant_table_count; i++)
+        max_contexts = FFMAX(f->context_count[i], max_contexts);
+
+    /* Allocate slice buffer data */
+    if (f->ac == AC_GOLOMB_RICE)
+        fp->plane_state_size = 8;
+    else
+        fp->plane_state_size = CONTEXT_SIZE;
+
+    fp->plane_state_size *= max_contexts;
+    fp->slice_state_size = fp->plane_state_size*f->plane_count;
+
+    fp->slice_data_size = 256; /* Overestimation for the SliceContext struct */
+    fp->slice_state_size += fp->slice_data_size;
+    fp->slice_state_size = FFALIGN(fp->slice_state_size, 8);
+
+    fp->crc_checked = f->ec && (avctx->err_recognition & AV_EF_CRCCHECK);
+
+    /* Host map the input slices data if supported */
+    if (ctx->s.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY)
+        ff_vk_host_map_buffer(&ctx->s, &vp->slices_buf, buffer_ref->data,
+                              buffer_ref,
+                              VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
+                              VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
+
+    /* Allocate slice state data */
+    if (f->picture.f->flags & AV_FRAME_FLAG_KEY) {
+        err = ff_vk_get_pooled_buffer(&ctx->s, &fv->slice_state_pool,
+                                      &fp->slice_state,
+                                      VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
+                                      VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
+                                      NULL, f->slice_count*fp->slice_state_size,
+                                      VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+        if (err < 0)
+            return err;
+    } else {
+        FFv1VulkanDecodePicture *fpl = f->hwaccel_last_picture_private;
+        fp->slice_state = av_buffer_ref(fpl->slice_state);
+        if (!fp->slice_state)
+            return AVERROR(ENOMEM);
+    }
+
+    /* Allocate slice offsets buffer */
+    err = ff_vk_get_pooled_buffer(&ctx->s, &fv->slice_offset_pool,
+                                  &fp->slice_offset_buf,
+                                  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
+                                  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
+                                  NULL, 2*f->slice_count*sizeof(uint32_t),
+                                  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+                                  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
+    if (err < 0)
+        return err;
+
+    /* Allocate slice status buffer */
+    err = ff_vk_get_pooled_buffer(&ctx->s, &fv->slice_status_pool,
+                                  &fp->slice_status_buf,
+                                  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
+                                  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
+                                  NULL, 2*f->slice_count*sizeof(uint32_t),
+                                  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+                                  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
+    if (err < 0)
+        return err;
+
+    /* Prepare frame to be used */
+    err = ff_vk_decode_prepare_frame_sdr(dec, f->picture.f, vp, 1,
+                                         FF_VK_REP_NATIVE, 0);
+    if (err < 0)
+        return err;
+
+    /* Create a temporaty frame for RGB */
+    if (is_rgb) {
+        vp->dpb_frame = av_frame_alloc();
+        if (!vp->dpb_frame)
+            return AVERROR(ENOMEM);
+
+        err = av_hwframe_get_buffer(fv->intermediate_frames_ref[f->use32bit],
+                                    vp->dpb_frame, 0);
+        if (err < 0)
+            return err;
+    }
+
+    return 0;
+}
+
+static int vk_ffv1_decode_slice(AVCodecContext *avctx,
+                                const uint8_t  *data,
+                                uint32_t        size)
+{
+    FFV1Context *f = avctx->priv_data;
+
+    FFv1VulkanDecodePicture *fp = f->hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &fp->vp;
+
+    FFVkBuffer *slice_offset = (FFVkBuffer *)fp->slice_offset_buf->data;
+    FFVkBuffer *slices_buf = vp->slices_buf ? (FFVkBuffer *)vp->slices_buf->data : NULL;
+
+    if (slices_buf && slices_buf->host_ref) {
+        AV_WN32(slice_offset->mapped_mem + (2*fp->slice_num + 0)*sizeof(uint32_t),
+                data - slices_buf->mapped_mem);
+        AV_WN32(slice_offset->mapped_mem + (2*fp->slice_num + 1)*sizeof(uint32_t),
+                size);
+
+        fp->slice_num++;
+    } else {
+        int err = ff_vk_decode_add_slice(avctx, vp, data, size, 0,
+                                         &fp->slice_num,
+                                         (const uint32_t **)&fp->slice_offset);
+        if (err < 0)
+            return err;
+
+        AV_WN32(slice_offset->mapped_mem + (2*(fp->slice_num - 1) + 0)*sizeof(uint32_t),
+                fp->slice_offset[fp->slice_num - 1]);
+        AV_WN32(slice_offset->mapped_mem + (2*(fp->slice_num - 1) + 1)*sizeof(uint32_t),
+                size);
+    }
+
+    return 0;
+}
+
+static int vk_ffv1_end_frame(AVCodecContext *avctx)
+{
+    int err;
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+
+    FFV1Context *f = avctx->priv_data;
+    FFv1VulkanDecodeContext *fv = ctx->sd_ctx;
+    FFv1VkParameters pd;
+    FFv1VkResetParameters pd_reset;
+
+    AVHWFramesContext *hwfc = (AVHWFramesContext *)avctx->hw_frames_ctx->data;
+    enum AVPixelFormat sw_format = hwfc->sw_format;
+
+    int bits = f->avctx->bits_per_raw_sample > 0 ? f->avctx->bits_per_raw_sample : 8;
+    int is_rgb = !(f->colorspace == 0 && sw_format != AV_PIX_FMT_YA8) &&
+                 !(sw_format == AV_PIX_FMT_YA8);
+    int color_planes = av_pix_fmt_desc_get(avctx->sw_pix_fmt)->nb_components;
+
+    FFVulkanShader *reset_shader;
+    FFVulkanShader *decode_shader;
+
+    FFv1VulkanDecodePicture *fp = f->hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &fp->vp;
+
+    FFVkBuffer *slices_buf = (FFVkBuffer *)vp->slices_buf->data;
+    FFVkBuffer *slice_state = (FFVkBuffer *)fp->slice_state->data;
+    FFVkBuffer *slice_offset = (FFVkBuffer *)fp->slice_offset_buf->data;
+    FFVkBuffer *slice_status = (FFVkBuffer *)fp->slice_status_buf->data;
+
+    VkImageView rct_image_views[AV_NUM_DATA_POINTERS];
+
+    AVFrame *decode_dst = is_rgb ? vp->dpb_frame : f->picture.f;
+    VkImageView *decode_dst_view = is_rgb ? rct_image_views : vp->view.out;
+
+    VkImageMemoryBarrier2 img_bar[37];
+    int nb_img_bar = 0;
+    VkBufferMemoryBarrier2 buf_bar[8];
+    int nb_buf_bar = 0;
+
+    FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
+    ff_vk_exec_start(&ctx->s, exec);
+
+    /* Prepare deps */
+    RET(ff_vk_exec_add_dep_frame(&ctx->s, exec, f->picture.f,
+                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
+
+    err = ff_vk_exec_mirror_sem_value(&ctx->s, exec, &vp->sem, &vp->sem_value,
+                                      f->picture.f);
+    if (err < 0)
+        return err;
+
+    if (is_rgb) {
+        RET(ff_vk_create_imageviews(&ctx->s, exec, rct_image_views,
+                                    vp->dpb_frame, FF_VK_REP_NATIVE));
+        RET(ff_vk_exec_add_dep_frame(&ctx->s, exec, vp->dpb_frame,
+                                     VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                     VK_PIPELINE_STAGE_2_CLEAR_BIT));
+        ff_vk_frame_barrier(&ctx->s, exec, decode_dst, img_bar, &nb_img_bar,
+                            VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                            VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                            VK_ACCESS_2_TRANSFER_WRITE_BIT,
+                            VK_IMAGE_LAYOUT_GENERAL,
+                            VK_QUEUE_FAMILY_IGNORED);
+    }
+
+    if (!(f->picture.f->flags & AV_FRAME_FLAG_KEY)) {
+        FFv1VulkanDecodePicture *fpl = f->hwaccel_last_picture_private;
+        FFVulkanDecodePicture *vpl = &fpl->vp;
+
+        /* Wait on the previous frame */
+        RET(ff_vk_exec_add_dep_wait_sem(&ctx->s, exec, vpl->sem, vpl->sem_value,
+                                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT));
+    }
+
+    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &fp->slice_state, 1, 1));
+    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &fp->slice_status_buf, 1, 1));
+    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0));
+    vp->slices_buf = NULL;
+    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &fp->slice_offset_buf, 1, 0));
+    fp->slice_offset_buf = NULL;
+
+    /* Entry barrier for the slice state */
+    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
+        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+        .srcStageMask = slice_state->stage,
+        .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+        .srcAccessMask = slice_state->access,
+        .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
+                         VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
+        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .buffer = slice_state->buf,
+        .offset = 0,
+        .size = fp->slice_data_size*f->slice_count,
+    };
+
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+        .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+        .pImageMemoryBarriers = img_bar,
+        .imageMemoryBarrierCount = nb_img_bar,
+        .pBufferMemoryBarriers = buf_bar,
+        .bufferMemoryBarrierCount = nb_buf_bar,
+    });
+    slice_state->stage = buf_bar[0].dstStageMask;
+    slice_state->access = buf_bar[0].dstAccessMask;
+    nb_buf_bar = 0;
+    nb_img_bar = 0;
+
+    /* Setup shader */
+    ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->setup,
+                                    1, 0, 0,
+                                    slice_state,
+                                    0, fp->slice_data_size*f->slice_count,
+                                    VK_FORMAT_UNDEFINED);
+    ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->setup,
+                                    1, 1, 0,
+                                    slice_offset,
+                                    0, 2*f->slice_count*sizeof(uint32_t),
+                                    VK_FORMAT_UNDEFINED);
+    ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->setup,
+                                    1, 2, 0,
+                                    slice_status,
+                                    0, 2*f->slice_count*sizeof(uint32_t),
+                                    VK_FORMAT_UNDEFINED);
+
+    ff_vk_exec_bind_shader(&ctx->s, exec, &fv->setup);
+    pd = (FFv1VkParameters) {
+        .slice_data = slices_buf->address,
+        .slice_state  = slice_state->address + f->slice_count*fp->slice_data_size,
+
+        .img_size[0] = f->picture.f->width,
+        .img_size[1] = f->picture.f->height,
+        .chroma_shift[0] = f->chroma_h_shift,
+        .chroma_shift[1] = f->chroma_v_shift,
+
+        .plane_state_size = fp->plane_state_size,
+        .crcref = f->crcref,
+        .rct_offset = 1 << bits,
+
+        .bits_per_raw_sample = bits,
+        .quant_table_count = f->quant_table_count,
+        .version = f->version,
+        .micro_version = f->micro_version,
+        .key_frame = f->picture.f->flags & AV_FRAME_FLAG_KEY,
+        .planes = av_pix_fmt_count_planes(sw_format),
+        .codec_planes = f->plane_count,
+        .color_planes = color_planes,
+        .transparency = f->transparency,
+        .planar_rgb = ff_vk_mt_is_np_rgb(sw_format) &&
+                      (ff_vk_count_images((AVVkFrame *)f->picture.f->data[0]) > 1),
+        .colorspace = f->colorspace,
+        .ec = f->ec,
+        .golomb = f->ac == AC_GOLOMB_RICE,
+        .check_crc = !!(avctx->err_recognition & AV_EF_CRCCHECK),
+    };
+    for (int i = 0; i < f->quant_table_count; i++)
+        pd.extend_lookup[i] = (f->quant_tables[i][3][127] != 0) ||
+                              (f->quant_tables[i][4][127] != 0);
+
+
+    /* For some reason the C FFv1 encoder/decoder treats these differently */
+    if (sw_format == AV_PIX_FMT_GBRP10 || sw_format == AV_PIX_FMT_GBRP12 ||
+        sw_format == AV_PIX_FMT_GBRP14)
+        memcpy(pd.fmt_lut, (int [4]) { 2, 1, 0, 3 }, 4*sizeof(int));
+    else if (sw_format == AV_PIX_FMT_X2BGR10)
+        memcpy(pd.fmt_lut, (int [4]) { 0, 2, 1, 3 }, 4*sizeof(int));
+    else
+        ff_vk_set_perm(sw_format, pd.fmt_lut, 0);
+
+    ff_vk_shader_update_push_const(&ctx->s, exec, &fv->setup,
+                                   VK_SHADER_STAGE_COMPUTE_BIT,
+                                   0, sizeof(pd), &pd);
+
+    vk->CmdDispatch(exec->buf, f->num_h_slices, f->num_v_slices, 1);
+
+    if (is_rgb) {
+        AVVkFrame *vkf = (AVVkFrame *)vp->dpb_frame->data[0];
+        for (int i = 0; i < color_planes; i++)
+            vk->CmdClearColorImage(exec->buf, vkf->img[i], VK_IMAGE_LAYOUT_GENERAL,
+                                   &((VkClearColorValue) { 0 }),
+                                   1, &((VkImageSubresourceRange) {
+                                       .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+                                       .levelCount = 1,
+                                       .layerCount = 1,
+                                   }));
+    }
+
+    /* Reset shader */
+    reset_shader = &fv->reset[f->ac == AC_GOLOMB_RICE];
+    ff_vk_shader_update_desc_buffer(&ctx->s, exec, reset_shader,
+                                    1, 0, 0,
+                                    slice_state,
+                                    0, fp->slice_data_size*f->slice_count,
+                                    VK_FORMAT_UNDEFINED);
+
+    ff_vk_exec_bind_shader(&ctx->s, exec, reset_shader);
+
+    pd_reset = (FFv1VkResetParameters) {
+        .slice_state = slice_state->address + f->slice_count*fp->slice_data_size,
+        .plane_state_size = fp->plane_state_size,
+        .codec_planes = f->plane_count,
+        .key_frame = f->picture.f->flags & AV_FRAME_FLAG_KEY,
+        .version = f->version,
+        .micro_version = f->micro_version,
+    };
+    for (int i = 0; i < f->quant_table_count; i++)
+        pd_reset.context_count[i] = f->context_count[i];
+
+    ff_vk_shader_update_push_const(&ctx->s, exec, reset_shader,
+                                   VK_SHADER_STAGE_COMPUTE_BIT,
+                                   0, sizeof(pd_reset), &pd_reset);
+
+    /* Sync between setup and reset shaders */
+    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
+        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+        .srcStageMask = slice_state->stage,
+        .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+        .srcAccessMask = slice_state->access,
+        .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT,
+        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .buffer = slice_state->buf,
+        .offset = 0,
+        .size = fp->slice_data_size*f->slice_count,
+    };
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+        .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+        .pImageMemoryBarriers = img_bar,
+        .imageMemoryBarrierCount = nb_img_bar,
+        .pBufferMemoryBarriers = buf_bar,
+        .bufferMemoryBarrierCount = nb_buf_bar,
+    });
+    slice_state->stage = buf_bar[0].dstStageMask;
+    slice_state->access = buf_bar[0].dstAccessMask;
+    nb_buf_bar = 0;
+    nb_img_bar = 0;
+
+    vk->CmdDispatch(exec->buf, f->num_h_slices, f->num_v_slices,
+                    f->plane_count);
+
+    /* Decode */
+    decode_shader = &fv->decode[f->use32bit][f->ac == AC_GOLOMB_RICE][is_rgb];
+    ff_vk_shader_update_desc_buffer(&ctx->s, exec, decode_shader,
+                                    1, 0, 0,
+                                    slice_state,
+                                    0, fp->slice_data_size*f->slice_count,
+                                    VK_FORMAT_UNDEFINED);
+    ff_vk_shader_update_img_array(&ctx->s, exec, decode_shader,
+                                  decode_dst, decode_dst_view,
+                                  1, 1,
+                                  VK_IMAGE_LAYOUT_GENERAL,
+                                  VK_NULL_HANDLE);
+    ff_vk_shader_update_desc_buffer(&ctx->s, exec, decode_shader,
+                                    1, 2, 0,
+                                    slice_status,
+                                    0, 2*f->slice_count*sizeof(uint32_t),
+                                    VK_FORMAT_UNDEFINED);
+    if (is_rgb)
+        ff_vk_shader_update_img_array(&ctx->s, exec, decode_shader,
+                                      f->picture.f, vp->view.out,
+                                      1, 3,
+                                      VK_IMAGE_LAYOUT_GENERAL,
+                                      VK_NULL_HANDLE);
+
+    ff_vk_exec_bind_shader(&ctx->s, exec, decode_shader);
+    ff_vk_shader_update_push_const(&ctx->s, exec, decode_shader,
+                                   VK_SHADER_STAGE_COMPUTE_BIT,
+                                   0, sizeof(pd), &pd);
+
+    /* Sync between reset and decode shaders */
+    buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
+        .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
+        .srcStageMask = slice_state->stage,
+        .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+        .srcAccessMask = slice_state->access,
+        .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
+                         VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
+        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+        .buffer = slice_state->buf,
+        .offset = fp->slice_data_size*f->slice_count,
+        .size = f->slice_count*(fp->slice_state_size - fp->slice_data_size),
+    };
+
+    /* Input frame barrier */
+    ff_vk_frame_barrier(&ctx->s, exec, f->picture.f, img_bar, &nb_img_bar,
+                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                        VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                        VK_ACCESS_SHADER_WRITE_BIT |
+                        (!is_rgb ? VK_ACCESS_SHADER_READ_BIT : 0),
+                        VK_IMAGE_LAYOUT_GENERAL,
+                        VK_QUEUE_FAMILY_IGNORED);
+    if (is_rgb)
+        ff_vk_frame_barrier(&ctx->s, exec, vp->dpb_frame, img_bar, &nb_img_bar,
+                            VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                            VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
+                            VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
+                            VK_IMAGE_LAYOUT_GENERAL,
+                            VK_QUEUE_FAMILY_IGNORED);
+
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+        .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+        .pImageMemoryBarriers = img_bar,
+        .imageMemoryBarrierCount = nb_img_bar,
+        .pBufferMemoryBarriers = buf_bar,
+        .bufferMemoryBarrierCount = nb_buf_bar,
+    });
+    slice_state->stage = buf_bar[0].dstStageMask;
+    slice_state->access = buf_bar[0].dstAccessMask;
+    nb_img_bar = 0;
+    nb_buf_bar = 0;
+
+    vk->CmdDispatch(exec->buf, f->num_h_slices, f->num_v_slices, 1);
+
+    err = ff_vk_exec_submit(&ctx->s, exec);
+    if (err < 0)
+        return err;
+
+    /* We don't need the temporary frame after decoding */
+    av_frame_free(&vp->dpb_frame);
+
+fail:
+    return 0;
+}
+
+static void define_shared_code(FFVulkanShader *shd, int use32bit)
+{
+    int smp_bits = use32bit ? 32 : 16;
+
+    GLSLC(0, #define DECODE                                              );
+
+    av_bprintf(&shd->src, "#define RGB_LINECACHE %i\n"                   ,RGB_LINECACHE);
+    av_bprintf(&shd->src, "#define CONTEXT_SIZE %i\n"                    ,CONTEXT_SIZE);
+    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_MASK 0x%x\n"          ,MAX_QUANT_TABLE_MASK);
+
+    GLSLF(0, #define TYPE int%i_t                                        ,smp_bits);
+    GLSLF(0, #define VTYPE2 i%ivec2                                      ,smp_bits);
+    GLSLF(0, #define VTYPE3 i%ivec3                                      ,smp_bits);
+    GLSLD(ff_source_rangecoder_comp);
+    GLSLD(ff_source_ffv1_common_comp);
+}
+
+static int init_setup_shader(FFV1Context *f, FFVulkanContext *s,
+                             FFVkExecPool *pool, FFVkSPIRVCompiler *spv,
+                             FFVulkanShader *shd)
+{
+    int err;
+    FFVulkanDescriptorSetBinding *desc_set;
+
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+
+    RET(ff_vk_shader_init(s, shd, "ffv1_dec_setup",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          (const char *[]) { "GL_EXT_buffer_reference",
+                                             "GL_EXT_buffer_reference2" }, 2,
+                          1, 1, 1,
+                          0));
+
+    /* Common codec header */
+    GLSLD(ff_source_common_comp);
+
+    add_push_data(shd);
+
+    av_bprintf(&shd->src, "#define MAX_QUANT_TABLES %i\n", MAX_QUANT_TABLES);
+    av_bprintf(&shd->src, "#define MAX_CONTEXT_INPUTS %i\n", MAX_CONTEXT_INPUTS);
+    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_SIZE %i\n", MAX_QUANT_TABLE_SIZE);
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "rangecoder_static_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "uint8_t zero_one_state[512];",
+        },
+        {
+            .name        = "crc_ieee_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "uint32_t crc_ieee[256];",
+        },
+        {
+            .name        = "quant_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "int16_t quant_table[MAX_QUANT_TABLES]"
+                           "[MAX_CONTEXT_INPUTS][MAX_QUANT_TABLE_SIZE];",
+        },
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(s, shd, desc_set, 3, 1, 0));
+
+    define_shared_code(shd, 0 /* Irrelevant */);
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "slice_data_buf",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "SliceContext slice_ctx",
+            .buf_elems   = f->max_slice_count,
+        },
+        {
+            .name        = "slice_offsets_buf",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_quali   = "readonly",
+            .buf_content = "uint32_t slice_offsets",
+            .buf_elems   = 2*f->max_slice_count,
+        },
+        {
+            .name        = "slice_status_buf",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_quali   = "writeonly",
+            .buf_content = "uint32_t slice_status",
+            .buf_elems   = 2*f->max_slice_count,
+        },
+    };
+    RET(ff_vk_shader_add_descriptor_set(s, shd, desc_set, 3, 0, 0));
+
+    GLSLD(ff_source_ffv1_dec_setup_comp);
+
+    RET(spv->compile_shader(s, spv, shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(s, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(s, pool, shd));
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+
+    return err;
+}
+
+static int init_reset_shader(FFV1Context *f, FFVulkanContext *s,
+                             FFVkExecPool *pool, FFVkSPIRVCompiler *spv,
+                             FFVulkanShader *shd, int ac)
+{
+    int err;
+    FFVulkanDescriptorSetBinding *desc_set;
+
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    int wg_dim = FFMIN(s->props.properties.limits.maxComputeWorkGroupSize[0], 1024);
+
+    RET(ff_vk_shader_init(s, shd, "ffv1_dec_reset",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          (const char *[]) { "GL_EXT_buffer_reference",
+                                             "GL_EXT_buffer_reference2" }, 2,
+                          wg_dim, 1, 1,
+                          0));
+
+    if (ac == AC_GOLOMB_RICE)
+        av_bprintf(&shd->src, "#define GOLOMB\n");
+
+    /* Common codec header */
+    GLSLD(ff_source_common_comp);
+
+    GLSLC(0, layout(push_constant, scalar) uniform pushConstants {             );
+    GLSLF(1,    uint context_count[%i];                                        ,MAX_QUANT_TABLES);
+    GLSLC(1,    u8buf slice_state;                                             );
+    GLSLC(1,    uint plane_state_size;                                         );
+    GLSLC(1,    uint8_t codec_planes;                                          );
+    GLSLC(1,    uint8_t key_frame;                                             );
+    GLSLC(1,    uint8_t version;                                               );
+    GLSLC(1,    uint8_t micro_version;                                         );
+    GLSLC(1,    uint8_t padding[1];                                            );
+    GLSLC(0, };                                                                );
+    ff_vk_shader_add_push_const(shd, 0, sizeof(FFv1VkResetParameters),
+                                VK_SHADER_STAGE_COMPUTE_BIT);
+
+    av_bprintf(&shd->src, "#define MAX_QUANT_TABLES %i\n", MAX_QUANT_TABLES);
+    av_bprintf(&shd->src, "#define MAX_CONTEXT_INPUTS %i\n", MAX_CONTEXT_INPUTS);
+    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_SIZE %i\n", MAX_QUANT_TABLE_SIZE);
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "rangecoder_static_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "uint8_t zero_one_state[512];",
+        },
+        {
+            .name        = "quant_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "int16_t quant_table[MAX_QUANT_TABLES]"
+                           "[MAX_CONTEXT_INPUTS][MAX_QUANT_TABLE_SIZE];",
+        },
+    };
+    RET(ff_vk_shader_add_descriptor_set(s, shd, desc_set, 2, 1, 0));
+
+    define_shared_code(shd, 0 /* Bit depth irrelevant for the reset shader */);
+    if (ac == AC_GOLOMB_RICE)
+        GLSLD(ff_source_ffv1_vlc_comp);
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "slice_data_buf",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .mem_quali   = "readonly",
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "SliceContext slice_ctx",
+            .buf_elems   = f->max_slice_count,
+        },
+    };
+    RET(ff_vk_shader_add_descriptor_set(s, shd, desc_set, 1, 0, 0));
+
+    GLSLD(ff_source_ffv1_reset_comp);
+
+    RET(spv->compile_shader(s, spv, shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(s, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(s, pool, shd));
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+
+    return err;
+}
+
+static int init_decode_shader(FFV1Context *f, FFVulkanContext *s,
+                              FFVkExecPool *pool, FFVkSPIRVCompiler *spv,
+                              FFVulkanShader *shd,
+                              AVHWFramesContext *dec_frames_ctx,
+                              AVHWFramesContext *out_frames_ctx,
+                              int use32bit, int ac, int rgb)
+{
+    int err;
+    FFVulkanDescriptorSetBinding *desc_set;
+
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+    int use_cached_reader = ac != AC_GOLOMB_RICE &&
+                            s->driver_props.driverID == VK_DRIVER_ID_MESA_RADV;
+
+    RET(ff_vk_shader_init(s, shd, "ffv1_dec",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          (const char *[]) { "GL_EXT_buffer_reference",
+                                             "GL_EXT_buffer_reference2" }, 2,
+                          use_cached_reader ? CONTEXT_SIZE : 1, 1, 1,
+                          0));
+
+    if (ac == AC_GOLOMB_RICE)
+        av_bprintf(&shd->src, "#define GOLOMB\n");
+
+    if (rgb)
+        av_bprintf(&shd->src, "#define RGB\n");
+
+    if (use_cached_reader)
+        av_bprintf(&shd->src, "#define CACHED_SYMBOL_READER 1\n");
+
+    /* Common codec header */
+    GLSLD(ff_source_common_comp);
+
+    add_push_data(shd);
+
+    av_bprintf(&shd->src, "#define MAX_QUANT_TABLES %i\n", MAX_QUANT_TABLES);
+    av_bprintf(&shd->src, "#define MAX_CONTEXT_INPUTS %i\n", MAX_CONTEXT_INPUTS);
+    av_bprintf(&shd->src, "#define MAX_QUANT_TABLE_SIZE %i\n", MAX_QUANT_TABLE_SIZE);
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "rangecoder_static_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "uint8_t zero_one_state[512];",
+        },
+        {
+            .name        = "quant_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "int16_t quant_table[MAX_QUANT_TABLES]"
+                           "[MAX_CONTEXT_INPUTS][MAX_QUANT_TABLE_SIZE];",
+        },
+    };
+
+    RET(ff_vk_shader_add_descriptor_set(s, shd, desc_set, 2, 1, 0));
+
+    define_shared_code(shd, use32bit);
+    if (ac == AC_GOLOMB_RICE)
+        GLSLD(ff_source_ffv1_vlc_comp);
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "slice_data_buf",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .buf_content = "SliceContext slice_ctx",
+            .buf_elems   = f->max_slice_count,
+        },
+        {
+            .name       = "dec",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .dimensions = 2,
+            .mem_layout = ff_vk_shader_rep_fmt(dec_frames_ctx->sw_format,
+                                               FF_VK_REP_NATIVE),
+            .elems      = av_pix_fmt_count_planes(dec_frames_ctx->sw_format),
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+        {
+            .name        = "slice_status_buf",
+            .type        = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_quali   = "writeonly",
+            .buf_content = "uint32_t slice_status",
+            .buf_elems   = 2*f->max_slice_count,
+        },
+        {
+            .name       = "dst",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .dimensions = 2,
+            .mem_layout = ff_vk_shader_rep_fmt(out_frames_ctx->sw_format,
+                                               FF_VK_REP_NATIVE),
+            .mem_quali  = "writeonly",
+            .elems      = av_pix_fmt_count_planes(out_frames_ctx->sw_format),
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+    };
+    RET(ff_vk_shader_add_descriptor_set(s, shd, desc_set, 3 + rgb, 0, 0));
+
+    GLSLD(ff_source_ffv1_dec_comp);
+
+    RET(spv->compile_shader(s, spv, shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(s, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(s, pool, shd));
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+
+    return err;
+}
+
+static int init_indirect(AVCodecContext *avctx, FFVulkanContext *s,
+                         AVBufferRef **dst, enum AVPixelFormat sw_format)
+{
+    int err;
+    AVHWFramesContext *frames_ctx;
+    AVVulkanFramesContext *vk_frames;
+    FFV1Context *f = avctx->priv_data;
+
+    *dst = av_hwframe_ctx_alloc(s->device_ref);
+    if (!(*dst))
+        return AVERROR(ENOMEM);
+
+    frames_ctx = (AVHWFramesContext *)((*dst)->data);
+    frames_ctx->format    = AV_PIX_FMT_VULKAN;
+    frames_ctx->sw_format = sw_format;
+    frames_ctx->width     = s->frames->width;
+    frames_ctx->height    = f->num_v_slices*RGB_LINECACHE;
+
+    vk_frames = frames_ctx->hwctx;
+    vk_frames->tiling    = VK_IMAGE_TILING_OPTIMAL;
+    vk_frames->img_flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
+    vk_frames->usage     = VK_IMAGE_USAGE_STORAGE_BIT |
+                           VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+
+    err = av_hwframe_ctx_init(*dst);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to initialize frame pool with format %s: %s\n",
+               av_get_pix_fmt_name(sw_format), av_err2str(err));
+        av_buffer_unref(dst);
+        return err;
+    }
+
+    return 0;
+}
+
+static void vk_decode_ffv1_uninit(FFVulkanDecodeShared *ctx)
+{
+    FFv1VulkanDecodeContext *fv = ctx->sd_ctx;
+
+    ff_vk_shader_free(&ctx->s, &fv->setup);
+
+    for (int i = 0; i < 2; i++) /* 16/32 bit */
+        av_buffer_unref(&fv->intermediate_frames_ref[i]);
+
+    for (int i = 0; i < 2; i++) /* AC/Golomb */
+        ff_vk_shader_free(&ctx->s, &fv->reset[i]);
+
+    for (int i = 0; i < 2; i++) /* 16/32 bit */
+        for (int j = 0; j < 2; j++) /* AC/Golomb */
+            for (int k = 0; k < 2; k++) /* Normal/RGB */
+                ff_vk_shader_free(&ctx->s, &fv->decode[i][j][k]);
+
+    ff_vk_free_buf(&ctx->s, &fv->quant_buf);
+    ff_vk_free_buf(&ctx->s, &fv->rangecoder_static_buf);
+    ff_vk_free_buf(&ctx->s, &fv->crc_tab_buf);
+
+    av_buffer_pool_uninit(&fv->slice_state_pool);
+    av_buffer_pool_uninit(&fv->slice_offset_pool);
+    av_buffer_pool_uninit(&fv->slice_status_pool);
+
+    av_freep(&fv);
+}
+
+static int vk_decode_ffv1_init(AVCodecContext *avctx)
+{
+    int err;
+    FFV1Context *f = avctx->priv_data;
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = NULL;
+    FFv1VulkanDecodeContext *fv;
+    FFVkSPIRVCompiler *spv;
+
+    if (f->version < 3 ||
+        (f->version == 4 && f->micro_version > 3))
+        return AVERROR(ENOTSUP);
+
+    spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    err = ff_vk_decode_init(avctx);
+    if (err < 0)
+        return err;
+    ctx = dec->shared_ctx;
+
+    fv = ctx->sd_ctx = av_mallocz(sizeof(*fv));
+    if (!fv) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    ctx->sd_ctx_free = &vk_decode_ffv1_uninit;
+
+    /* Intermediate frame pool for RCT */
+    for (int i = 0; i < 2; i++) { /* 16/32 bit */
+        RET(init_indirect(avctx, &ctx->s, &fv->intermediate_frames_ref[i],
+                          i ? AV_PIX_FMT_GBRAP32 : AV_PIX_FMT_GBRAP16));
+    }
+
+    /* Setup shader */
+    RET(init_setup_shader(f, &ctx->s, &ctx->exec_pool, spv, &fv->setup));
+
+    /* Reset shaders */
+    for (int i = 0; i < 2; i++) { /* AC/Golomb */
+        RET(init_reset_shader(f, &ctx->s, &ctx->exec_pool,
+                              spv, &fv->reset[i], !i ? AC_RANGE_CUSTOM_TAB : 0));
+    }
+
+    /* Decode shaders */
+    for (int i = 0; i < 2; i++) { /* 16/32 bit */
+        for (int j = 0; j < 2; j++) { /* AC/Golomb */
+            for (int k = 0; k < 2; k++) { /* Normal/RGB */
+                AVHWFramesContext *dec_frames_ctx;
+                dec_frames_ctx = k ? (AVHWFramesContext *)fv->intermediate_frames_ref[i]->data :
+                                     (AVHWFramesContext *)avctx->hw_frames_ctx->data;
+                RET(init_decode_shader(f, &ctx->s, &ctx->exec_pool,
+                                       spv, &fv->decode[i][j][k],
+                                       dec_frames_ctx,
+                                       (AVHWFramesContext *)avctx->hw_frames_ctx->data,
+                                       i,
+                                       !j ? AC_RANGE_CUSTOM_TAB : AC_GOLOMB_RICE,
+                                       k));
+            }
+        }
+    }
+
+    /* Range coder data */
+    RET(ff_ffv1_vk_init_state_transition_data(&ctx->s,
+                                              &fv->rangecoder_static_buf,
+                                              f));
+
+    /* Quantization table data */
+    RET(ff_ffv1_vk_init_quant_table_data(&ctx->s,
+                                         &fv->quant_buf,
+                                         f));
+
+    /* CRC table buffer */
+    RET(ff_ffv1_vk_init_crc_table_data(&ctx->s,
+                                       &fv->crc_tab_buf,
+                                       f));
+
+    /* Update setup global descriptors */
+    RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
+                                        &fv->setup, 0, 0, 0,
+                                        &fv->rangecoder_static_buf,
+                                        0, fv->rangecoder_static_buf.size,
+                                        VK_FORMAT_UNDEFINED));
+    RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
+                                        &fv->setup, 0, 1, 0,
+                                        &fv->crc_tab_buf,
+                                        0, fv->crc_tab_buf.size,
+                                        VK_FORMAT_UNDEFINED));
+
+    /* Update decode global descriptors */
+    for (int i = 0; i < 2; i++) { /* 16/32 bit */
+        for (int j = 0; j < 2; j++) { /* AC/Golomb */
+            for (int k = 0; k < 2; k++) { /* Normal/RGB */
+                RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
+                                                    &fv->decode[i][j][k], 0, 0, 0,
+                                                    &fv->rangecoder_static_buf,
+                                                    0, fv->rangecoder_static_buf.size,
+                                                    VK_FORMAT_UNDEFINED));
+                RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
+                                                    &fv->decode[i][j][k], 0, 1, 0,
+                                                    &fv->quant_buf,
+                                                    0, fv->quant_buf.size,
+                                                    VK_FORMAT_UNDEFINED));
+            }
+        }
+    }
+
+fail:
+    spv->uninit(&spv);
+
+    return err;
+}
+
+static void vk_ffv1_free_frame_priv(AVRefStructOpaque _hwctx, void *data)
+{
+    AVHWDeviceContext *dev_ctx = _hwctx.nc;
+    AVVulkanDeviceContext *hwctx = dev_ctx->hwctx;
+
+    FFv1VulkanDecodePicture *fp = data;
+    FFVulkanDecodePicture *vp = &fp->vp;
+    FFVkBuffer *slice_status = (FFVkBuffer *)fp->slice_status_buf->data;
+
+    ff_vk_decode_free_frame(dev_ctx, vp);
+
+    /* Invalidate slice/output data if needed */
+    if (!(slice_status->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
+        VkMappedMemoryRange invalidate_data = {
+            .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+            .memory = slice_status->mem,
+            .offset = 0,
+            .size = 2*fp->slice_num*sizeof(uint32_t),
+        };
+        vp->invalidate_memory_ranges(hwctx->act_dev,
+                                     1, &invalidate_data);
+    }
+
+    for (int i = 0; i < fp->slice_num; i++) {
+        uint32_t crc_res = 0;
+        if (fp->crc_checked)
+            crc_res = AV_RN32(slice_status->mapped_mem + 2*i*sizeof(uint32_t) + 0);
+        uint32_t status = AV_RN32(slice_status->mapped_mem + 2*i*sizeof(uint32_t) + 4);
+        if (status || crc_res)
+            av_log(dev_ctx, AV_LOG_ERROR, "Slice %i status: 0x%x, CRC 0x%x\n",
+                   i, status, crc_res);
+    }
+
+    av_buffer_unref(&vp->slices_buf);
+    av_buffer_unref(&fp->slice_state);
+    av_buffer_unref(&fp->slice_offset_buf);
+    av_buffer_unref(&fp->slice_status_buf);
+}
+
+const FFHWAccel ff_ffv1_vulkan_hwaccel = {
+    .p.name                = "ffv1_vulkan",
+    .p.type                = AVMEDIA_TYPE_VIDEO,
+    .p.id                  = AV_CODEC_ID_FFV1,
+    .p.pix_fmt             = AV_PIX_FMT_VULKAN,
+    .start_frame           = &vk_ffv1_start_frame,
+    .decode_slice          = &vk_ffv1_decode_slice,
+    .end_frame             = &vk_ffv1_end_frame,
+    .free_frame_priv       = &vk_ffv1_free_frame_priv,
+    .frame_priv_data_size  = sizeof(FFv1VulkanDecodePicture),
+    .init                  = &vk_decode_ffv1_init,
+    .update_thread_context = &ff_vk_update_thread_context,
+    .decode_params         = &ff_vk_params_invalidate,
+    .flush                 = &ff_vk_decode_flush,
+    .uninit                = &ff_vk_decode_uninit,
+    .frame_params          = &ff_vk_frame_params,
+    .priv_data_size        = sizeof(FFVulkanDecodeContext),
+    .caps_internal         = HWACCEL_CAP_ASYNC_SAFE | HWACCEL_CAP_THREAD_SAFE,
+};
-- 
2.49.1


From a7c4e07d3442f9b0313e4d37befaf34aff822f93 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:37:11 +0000
Subject: [PATCH 081/118] Changing vulkan file directory

---
 libavcodec/vulkan_h264.c | 592 ---------------------------------------
 1 file changed, 592 deletions(-)
 delete mode 100644 libavcodec/vulkan_h264.c

diff --git a/libavcodec/vulkan_h264.c b/libavcodec/vulkan_h264.c
deleted file mode 100644
index ebe305e7b5..0000000000
--- a/libavcodec/vulkan_h264.c
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "h264dec.h"
-#include "h264_ps.h"
-
-#include "vulkan_decode.h"
-
-const FFVulkanDecodeDescriptor ff_vk_dec_h264_desc = {
-    .codec_id         = AV_CODEC_ID_H264,
-    .decode_extension = FF_VK_EXT_VIDEO_DECODE_H264,
-    .queue_flags      = VK_QUEUE_VIDEO_DECODE_BIT_KHR,
-    .decode_op        = VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR,
-    .ext_props = {
-        .extensionName = VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME,
-        .specVersion   = VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION,
-    },
-};
-
-typedef struct H264VulkanDecodePicture {
-    FFVulkanDecodePicture           vp;
-
-    /* Current picture */
-    StdVideoDecodeH264ReferenceInfo h264_ref;
-    VkVideoDecodeH264DpbSlotInfoKHR vkh264_ref;
-
-    /* Picture refs */
-    H264Picture                    *ref_src    [H264_MAX_PICTURE_COUNT];
-    StdVideoDecodeH264ReferenceInfo h264_refs  [H264_MAX_PICTURE_COUNT];
-    VkVideoDecodeH264DpbSlotInfoKHR vkh264_refs[H264_MAX_PICTURE_COUNT];
-
-    /* Current picture (contd.) */
-    StdVideoDecodeH264PictureInfo   h264pic;
-    VkVideoDecodeH264PictureInfoKHR h264_pic_info;
-} H264VulkanDecodePicture;
-
-const static int h264_scaling_list8_order[] = { 0, 3, 1, 4, 2, 5 };
-
-static int vk_h264_fill_pict(AVCodecContext *avctx, H264Picture **ref_src,
-                             VkVideoReferenceSlotInfoKHR *ref_slot,       /* Main structure */
-                             VkVideoPictureResourceInfoKHR *ref,          /* Goes in ^ */
-                             VkVideoDecodeH264DpbSlotInfoKHR *vkh264_ref, /* Goes in ^ */
-                             StdVideoDecodeH264ReferenceInfo *h264_ref,   /* Goes in ^ */
-                             H264Picture *pic, int is_current,
-                             int is_field, int picture_structure,
-                             int dpb_slot_index)
-{
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-    H264VulkanDecodePicture *hp = pic->hwaccel_picture_private;
-    FFVulkanDecodePicture *vkpic = &hp->vp;
-
-    int err = ff_vk_decode_prepare_frame(dec, pic->f, vkpic, is_current,
-                                         dec->dedicated_dpb);
-    if (err < 0)
-        return err;
-
-    *h264_ref = (StdVideoDecodeH264ReferenceInfo) {
-        .FrameNum = pic->long_ref ? pic->pic_id : pic->frame_num,
-        .PicOrderCnt = { pic->field_poc[0], pic->field_poc[1] },
-        .flags = (StdVideoDecodeH264ReferenceInfoFlags) {
-            .top_field_flag    = is_field ? !!(picture_structure & PICT_TOP_FIELD)    : 0,
-            .bottom_field_flag = is_field ? !!(picture_structure & PICT_BOTTOM_FIELD) : 0,
-            .used_for_long_term_reference = pic->reference && pic->long_ref,
-            /*
-             * flags.is_non_existing is used to indicate whether the picture is marked as
-             * “non-existing” as defined in section 8.2.5.2 of the ITU-T H.264 Specification;
-             * 8.2.5.2 Decoding process for gaps in frame_num
-             * corresponds to the code in h264_slice.c:h264_field_start,
-             * which sets the invalid_gap flag when decoding.
-             */
-            .is_non_existing = pic->invalid_gap,
-        },
-    };
-
-    *vkh264_ref = (VkVideoDecodeH264DpbSlotInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR,
-        .pStdReferenceInfo = h264_ref,
-    };
-
-    *ref = (VkVideoPictureResourceInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
-        .codedOffset = (VkOffset2D){ 0, 0 },
-        .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
-        .baseArrayLayer = ctx->common.layered_dpb ? dpb_slot_index : 0,
-        .imageViewBinding = vkpic->view.ref[0],
-    };
-
-    *ref_slot = (VkVideoReferenceSlotInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
-        .pNext = vkh264_ref,
-        .slotIndex = dpb_slot_index,
-        .pPictureResource = ref,
-    };
-
-    if (ref_src)
-        *ref_src = pic;
-
-    return 0;
-}
-
-static StdVideoH264LevelIdc convert_to_vk_level_idc(int level_idc)
-{
-    switch (level_idc) {
-    case 10: return STD_VIDEO_H264_LEVEL_IDC_1_0;
-    case 11: return STD_VIDEO_H264_LEVEL_IDC_1_1;
-    case 12: return STD_VIDEO_H264_LEVEL_IDC_1_2;
-    case 13: return STD_VIDEO_H264_LEVEL_IDC_1_3;
-    case 20: return STD_VIDEO_H264_LEVEL_IDC_2_0;
-    case 21: return STD_VIDEO_H264_LEVEL_IDC_2_1;
-    case 22: return STD_VIDEO_H264_LEVEL_IDC_2_2;
-    case 30: return STD_VIDEO_H264_LEVEL_IDC_3_0;
-    case 31: return STD_VIDEO_H264_LEVEL_IDC_3_1;
-    case 32: return STD_VIDEO_H264_LEVEL_IDC_3_2;
-    case 40: return STD_VIDEO_H264_LEVEL_IDC_4_0;
-    case 41: return STD_VIDEO_H264_LEVEL_IDC_4_1;
-    case 42: return STD_VIDEO_H264_LEVEL_IDC_4_2;
-    case 50: return STD_VIDEO_H264_LEVEL_IDC_5_0;
-    case 51: return STD_VIDEO_H264_LEVEL_IDC_5_1;
-    case 52: return STD_VIDEO_H264_LEVEL_IDC_5_2;
-    case 60: return STD_VIDEO_H264_LEVEL_IDC_6_0;
-    case 61: return STD_VIDEO_H264_LEVEL_IDC_6_1;
-    default:
-    case 62: return STD_VIDEO_H264_LEVEL_IDC_6_2;
-    }
-}
-
-static void set_sps(const SPS *sps,
-                    StdVideoH264ScalingLists *vksps_scaling,
-                    StdVideoH264HrdParameters *vksps_vui_header,
-                    StdVideoH264SequenceParameterSetVui *vksps_vui,
-                    StdVideoH264SequenceParameterSet *vksps)
-{
-    *vksps_scaling = (StdVideoH264ScalingLists) {
-        .scaling_list_present_mask = sps->scaling_matrix_present_mask,
-        .use_default_scaling_matrix_mask = 0, /* We already fill in the default matrix */
-    };
-
-    for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS; i++)
-        for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS; j++)
-            vksps_scaling->ScalingList4x4[i][j] = sps->scaling_matrix4[i][ff_zigzag_scan[j]];
-
-    for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS; i++)
-        for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS; j++)
-            vksps_scaling->ScalingList8x8[i][j] =
-                sps->scaling_matrix8[h264_scaling_list8_order[i]][ff_zigzag_direct[j]];
-
-    *vksps_vui_header = (StdVideoH264HrdParameters) {
-        .cpb_cnt_minus1 = sps->cpb_cnt - 1,
-        .bit_rate_scale = sps->bit_rate_scale,
-        .initial_cpb_removal_delay_length_minus1 = sps->initial_cpb_removal_delay_length - 1,
-        .cpb_removal_delay_length_minus1 = sps->cpb_removal_delay_length - 1,
-        .dpb_output_delay_length_minus1 = sps->dpb_output_delay_length - 1,
-        .time_offset_length = sps->time_offset_length,
-    };
-
-    for (int i = 0; i < sps->cpb_cnt; i++) {
-        vksps_vui_header->bit_rate_value_minus1[i] = sps->bit_rate_value[i] - 1;
-        vksps_vui_header->cpb_size_value_minus1[i] = sps->cpb_size_value[i] - 1;
-        vksps_vui_header->cbr_flag[i] = (sps->cpr_flag >> i) & 0x1;
-    }
-
-    *vksps_vui = (StdVideoH264SequenceParameterSetVui) {
-        .aspect_ratio_idc = sps->vui.aspect_ratio_idc,
-        .sar_width = sps->vui.sar.num,
-        .sar_height = sps->vui.sar.den,
-        .video_format = sps->vui.video_format,
-        .colour_primaries = sps->vui.colour_primaries,
-        .transfer_characteristics = sps->vui.transfer_characteristics,
-        .matrix_coefficients = sps->vui.matrix_coeffs,
-        .num_units_in_tick = sps->num_units_in_tick,
-        .time_scale = sps->time_scale,
-        .pHrdParameters = vksps_vui_header,
-        .max_num_reorder_frames = sps->num_reorder_frames,
-        .max_dec_frame_buffering = sps->max_dec_frame_buffering,
-        .flags = (StdVideoH264SpsVuiFlags) {
-            .aspect_ratio_info_present_flag = sps->vui.aspect_ratio_info_present_flag,
-            .overscan_info_present_flag = sps->vui.overscan_info_present_flag,
-            .overscan_appropriate_flag = sps->vui.overscan_appropriate_flag,
-            .video_signal_type_present_flag = sps->vui.video_signal_type_present_flag,
-            .video_full_range_flag = sps->vui.video_full_range_flag,
-            .color_description_present_flag = sps->vui.colour_description_present_flag,
-            .chroma_loc_info_present_flag = sps->vui.chroma_location,
-            .timing_info_present_flag = sps->timing_info_present_flag,
-            .fixed_frame_rate_flag = sps->fixed_frame_rate_flag,
-            .bitstream_restriction_flag = sps->bitstream_restriction_flag,
-            .nal_hrd_parameters_present_flag = sps->nal_hrd_parameters_present_flag,
-            .vcl_hrd_parameters_present_flag = sps->vcl_hrd_parameters_present_flag,
-        },
-    };
-
-    *vksps = (StdVideoH264SequenceParameterSet) {
-        .profile_idc = sps->profile_idc,
-        .level_idc = convert_to_vk_level_idc(sps->level_idc),
-        .seq_parameter_set_id = sps->sps_id,
-        .chroma_format_idc = sps->chroma_format_idc,
-        .bit_depth_luma_minus8 = sps->bit_depth_luma - 8,
-        .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8,
-        .log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4,
-        .pic_order_cnt_type = sps->poc_type,
-        .log2_max_pic_order_cnt_lsb_minus4 = sps->poc_type ? 0 : sps->log2_max_poc_lsb - 4,
-        .offset_for_non_ref_pic = sps->offset_for_non_ref_pic,
-        .offset_for_top_to_bottom_field = sps->offset_for_top_to_bottom_field,
-        .num_ref_frames_in_pic_order_cnt_cycle = sps->poc_cycle_length,
-        .max_num_ref_frames = sps->ref_frame_count,
-        .pic_width_in_mbs_minus1 = sps->mb_width - 1,
-        .pic_height_in_map_units_minus1 = (sps->mb_height/(2 - sps->frame_mbs_only_flag)) - 1,
-        .frame_crop_left_offset = sps->crop_left,
-        .frame_crop_right_offset = sps->crop_right,
-        .frame_crop_top_offset = sps->crop_top,
-        .frame_crop_bottom_offset = sps->crop_bottom,
-        .flags = (StdVideoH264SpsFlags) {
-            .constraint_set0_flag = (sps->constraint_set_flags >> 0) & 0x1,
-            .constraint_set1_flag = (sps->constraint_set_flags >> 1) & 0x1,
-            .constraint_set2_flag = (sps->constraint_set_flags >> 2) & 0x1,
-            .constraint_set3_flag = (sps->constraint_set_flags >> 3) & 0x1,
-            .constraint_set4_flag = (sps->constraint_set_flags >> 4) & 0x1,
-            .constraint_set5_flag = (sps->constraint_set_flags >> 5) & 0x1,
-            .direct_8x8_inference_flag = sps->direct_8x8_inference_flag,
-            .mb_adaptive_frame_field_flag = sps->mb_aff,
-            .frame_mbs_only_flag = sps->frame_mbs_only_flag,
-            .delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag,
-            .separate_colour_plane_flag = sps->residual_color_transform_flag,
-            .gaps_in_frame_num_value_allowed_flag = sps->gaps_in_frame_num_allowed_flag,
-            .qpprime_y_zero_transform_bypass_flag = sps->transform_bypass,
-            .frame_cropping_flag = sps->crop,
-            .seq_scaling_matrix_present_flag = sps->scaling_matrix_present,
-            .vui_parameters_present_flag = sps->vui_parameters_present_flag,
-        },
-        .pOffsetForRefFrame = sps->offset_for_ref_frame,
-        .pScalingLists = vksps_scaling,
-        .pSequenceParameterSetVui = vksps_vui,
-    };
-}
-
-static void set_pps(const PPS *pps, const SPS *sps,
-                    StdVideoH264ScalingLists *vkpps_scaling,
-                    StdVideoH264PictureParameterSet *vkpps)
-{
-    *vkpps_scaling = (StdVideoH264ScalingLists) {
-        .scaling_list_present_mask = pps->pic_scaling_matrix_present_mask,
-        .use_default_scaling_matrix_mask = 0, /* We already fill in the default matrix */
-    };
-
-    for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS; i++)
-        for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS; j++)
-            vkpps_scaling->ScalingList4x4[i][j] = pps->scaling_matrix4[i][ff_zigzag_scan[j]];
-
-    for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS; i++)
-        for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS; j++)
-            vkpps_scaling->ScalingList8x8[i][j] =
-                pps->scaling_matrix8[h264_scaling_list8_order[i]][ff_zigzag_direct[j]];
-
-    *vkpps = (StdVideoH264PictureParameterSet) {
-        .seq_parameter_set_id = pps->sps_id,
-        .pic_parameter_set_id = pps->pps_id,
-        .num_ref_idx_l0_default_active_minus1 = pps->ref_count[0] - 1,
-        .num_ref_idx_l1_default_active_minus1 = pps->ref_count[1] - 1,
-        .weighted_bipred_idc = pps->weighted_bipred_idc,
-        .pic_init_qp_minus26 = pps->init_qp - 26,
-        .pic_init_qs_minus26 = pps->init_qs - 26,
-        .chroma_qp_index_offset = pps->chroma_qp_index_offset[0],
-        .second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1],
-        .flags = (StdVideoH264PpsFlags) {
-            .transform_8x8_mode_flag = pps->transform_8x8_mode,
-            .redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present,
-            .constrained_intra_pred_flag = pps->constrained_intra_pred,
-            .deblocking_filter_control_present_flag = pps->deblocking_filter_parameters_present,
-            .weighted_pred_flag = pps->weighted_pred,
-            .bottom_field_pic_order_in_frame_present_flag = pps->pic_order_present,
-            .entropy_coding_mode_flag = pps->cabac,
-            .pic_scaling_matrix_present_flag = pps->pic_scaling_matrix_present_flag,
-        },
-        .pScalingLists = vkpps_scaling,
-    };
-}
-
-static int vk_h264_create_params(AVCodecContext *avctx, AVBufferRef **buf)
-{
-    int err;
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-    const H264Context *h = avctx->priv_data;
-
-    /* SPS */
-    StdVideoH264ScalingLists vksps_scaling[MAX_SPS_COUNT];
-    StdVideoH264HrdParameters vksps_vui_header[MAX_SPS_COUNT];
-    StdVideoH264SequenceParameterSetVui vksps_vui[MAX_SPS_COUNT];
-    StdVideoH264SequenceParameterSet vksps[MAX_SPS_COUNT];
-
-    /* PPS */
-    StdVideoH264ScalingLists vkpps_scaling[MAX_PPS_COUNT];
-    StdVideoH264PictureParameterSet vkpps[MAX_PPS_COUNT];
-
-    VkVideoDecodeH264SessionParametersAddInfoKHR h264_params_info = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR,
-        .pStdSPSs = vksps,
-        .stdSPSCount = 0,
-        .pStdPPSs = vkpps,
-        .stdPPSCount = 0,
-    };
-    VkVideoDecodeH264SessionParametersCreateInfoKHR h264_params = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR,
-        .pParametersAddInfo = &h264_params_info,
-    };
-    VkVideoSessionParametersCreateInfoKHR session_params_create = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
-        .pNext = &h264_params,
-        .videoSession = ctx->common.session,
-        .videoSessionParametersTemplate = VK_NULL_HANDLE,
-    };
-
-    /* SPS list */
-    for (int i = 0; i < FF_ARRAY_ELEMS(h->ps.sps_list); i++) {
-        if (h->ps.sps_list[i]) {
-            const SPS *sps_l = h->ps.sps_list[i];
-            int idx = h264_params_info.stdSPSCount;
-            set_sps(sps_l, &vksps_scaling[idx], &vksps_vui_header[idx], &vksps_vui[idx], &vksps[idx]);
-            h264_params_info.stdSPSCount++;
-        }
-    }
-
-    /* PPS list */
-    for (int i = 0; i < FF_ARRAY_ELEMS(h->ps.pps_list); i++) {
-        if (h->ps.pps_list[i]) {
-            const PPS *pps_l = h->ps.pps_list[i];
-            int idx = h264_params_info.stdPPSCount;
-            set_pps(pps_l, pps_l->sps, &vkpps_scaling[idx], &vkpps[idx]);
-            h264_params_info.stdPPSCount++;
-        }
-    }
-
-    h264_params.maxStdSPSCount = h264_params_info.stdSPSCount;
-    h264_params.maxStdPPSCount = h264_params_info.stdPPSCount;
-
-    err = ff_vk_decode_create_params(buf, avctx, ctx, &session_params_create);
-    if (err < 0)
-        return err;
-
-    av_log(avctx, AV_LOG_DEBUG, "Created frame parameters: %i SPS %i PPS\n",
-           h264_params_info.stdSPSCount, h264_params_info.stdPPSCount);
-
-    return 0;
-}
-
-static int vk_h264_start_frame(AVCodecContext          *avctx,
-                               av_unused const AVBufferRef *buffer_ref,
-                               av_unused const uint8_t *buffer,
-                               av_unused uint32_t       size)
-{
-    int err;
-    int dpb_slot_index = 0;
-    H264Context *h = avctx->priv_data;
-
-    H264Picture *pic = h->cur_pic_ptr;
-    H264VulkanDecodePicture *hp = pic->hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &hp->vp;
-
-    /* Fill in main slot */
-    dpb_slot_index = 0;
-    for (unsigned slot = 0; slot < H264_MAX_PICTURE_COUNT; slot++) {
-        if (pic == &h->DPB[slot]) {
-            dpb_slot_index = slot;
-            break;
-        }
-    }
-
-    err = vk_h264_fill_pict(avctx, NULL, &vp->ref_slot, &vp->ref,
-                            &hp->vkh264_ref, &hp->h264_ref, pic, 1,
-                            h->DPB[dpb_slot_index].field_picture,
-                            h->DPB[dpb_slot_index].reference,
-                            dpb_slot_index);
-    if (err < 0)
-        return err;
-
-    /* Fill in short-term references */
-    for (int i = 0; i < h->short_ref_count; i++) {
-        dpb_slot_index = 0;
-        for (unsigned slot = 0; slot < H264_MAX_PICTURE_COUNT; slot++) {
-            if (h->short_ref[i] == &h->DPB[slot]) {
-                dpb_slot_index = slot;
-                break;
-            }
-        }
-        err = vk_h264_fill_pict(avctx, &hp->ref_src[i], &vp->ref_slots[i],
-                                &vp->refs[i], &hp->vkh264_refs[i],
-                                &hp->h264_refs[i], h->short_ref[i], 0,
-                                h->DPB[dpb_slot_index].field_picture,
-                                h->DPB[dpb_slot_index].reference,
-                                dpb_slot_index);
-        if (err < 0)
-            return err;
-    }
-
-    /* Fill in long-term refs */
-    for (int r = 0, i = h->short_ref_count; r < H264_MAX_DPB_FRAMES &&
-         i < h->short_ref_count + h->long_ref_count; r++) {
-        if (!h->long_ref[r])
-            continue;
-
-        dpb_slot_index = 0;
-        for (unsigned slot = 0; slot < 16; slot++) {
-            if (h->long_ref[r] == &h->DPB[slot]) {
-                dpb_slot_index = slot;
-                break;
-            }
-        }
-        err = vk_h264_fill_pict(avctx, &hp->ref_src[i], &vp->ref_slots[i],
-                                &vp->refs[i], &hp->vkh264_refs[i],
-                                &hp->h264_refs[i], h->long_ref[r], 0,
-                                h->DPB[dpb_slot_index].field_picture,
-                                h->DPB[dpb_slot_index].reference,
-                                dpb_slot_index);
-        if (err < 0)
-            return err;
-        i++;
-    }
-
-    hp->h264pic = (StdVideoDecodeH264PictureInfo) {
-        .seq_parameter_set_id = pic->pps->sps_id,
-        .pic_parameter_set_id = pic->pps->pps_id,
-        .frame_num = 0,  /* Set later */
-        .idr_pic_id = 0, /* Set later */
-        .PicOrderCnt[0] = pic->field_poc[0],
-        .PicOrderCnt[1] = pic->field_poc[1],
-        .flags = (StdVideoDecodeH264PictureInfoFlags) {
-            .field_pic_flag = FIELD_PICTURE(h),
-            .is_intra = 1, /* Set later */
-            .IdrPicFlag = h->picture_idr,
-            .bottom_field_flag = h->picture_structure != PICT_FRAME &&
-                                 h->picture_structure & PICT_BOTTOM_FIELD,
-            .is_reference = h->nal_ref_idc != 0,
-            .complementary_field_pair = h->first_field && FIELD_PICTURE(h),
-        },
-    };
-
-    hp->h264_pic_info = (VkVideoDecodeH264PictureInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_KHR,
-        .pStdPictureInfo = &hp->h264pic,
-    };
-
-    vp->decode_info = (VkVideoDecodeInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR,
-        .pNext = &hp->h264_pic_info,
-        .flags = 0x0,
-        .pSetupReferenceSlot = &vp->ref_slot,
-        .referenceSlotCount = h->short_ref_count + h->long_ref_count,
-        .pReferenceSlots = vp->ref_slots,
-        .dstPictureResource = (VkVideoPictureResourceInfoKHR) {
-            .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
-            .codedOffset = (VkOffset2D){ 0, 0 },
-            .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
-            .baseArrayLayer = 0,
-            .imageViewBinding = vp->view.out[0],
-        },
-    };
-
-    return 0;
-}
-
-static int vk_h264_decode_slice(AVCodecContext *avctx,
-                                const uint8_t  *data,
-                                uint32_t        size)
-{
-    const H264Context *h = avctx->priv_data;
-    const H264SliceContext *sl  = &h->slice_ctx[0];
-    H264VulkanDecodePicture *hp = h->cur_pic_ptr->hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &hp->vp;
-
-    int err = ff_vk_decode_add_slice(avctx, vp, data, size, 1,
-                                     &hp->h264_pic_info.sliceCount,
-                                     &hp->h264_pic_info.pSliceOffsets);
-    if (err < 0)
-        return err;
-
-    hp->h264pic.frame_num = sl->frame_num;
-    hp->h264pic.idr_pic_id = sl->idr_pic_id;
-
-    /* Frame is only intra of all slices are marked as intra */
-    if (sl->slice_type != AV_PICTURE_TYPE_I && sl->slice_type != AV_PICTURE_TYPE_SI)
-        hp->h264pic.flags.is_intra = 0;
-
-    return 0;
-}
-
-static int vk_h264_end_frame(AVCodecContext *avctx)
-{
-    const H264Context *h = avctx->priv_data;
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-
-    H264Picture *pic = h->cur_pic_ptr;
-    H264VulkanDecodePicture *hp = pic->hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &hp->vp;
-    FFVulkanDecodePicture *rvp[H264_MAX_PICTURE_COUNT] = { 0 };
-    AVFrame *rav[H264_MAX_PICTURE_COUNT] = { 0 };
-
-#ifdef VK_KHR_video_maintenance2
-    StdVideoH264ScalingLists vksps_scaling;
-    StdVideoH264HrdParameters vksps_vui_header;
-    StdVideoH264SequenceParameterSetVui vksps_vui;
-    StdVideoH264SequenceParameterSet vksps;
-    StdVideoH264ScalingLists vkpps_scaling;
-    StdVideoH264PictureParameterSet vkpps;
-    VkVideoDecodeH264InlineSessionParametersInfoKHR h264_params;
-
-    if (ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2) {
-        set_sps(h->ps.sps, &vksps_scaling,
-                &vksps_vui_header, &vksps_vui, &vksps);
-        set_pps(h->ps.pps, h->ps.sps, &vkpps_scaling, &vkpps);
-        h264_params = (VkVideoDecodeH264InlineSessionParametersInfoKHR) {
-            .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_INLINE_SESSION_PARAMETERS_INFO_KHR,
-            .pStdSPS = &vksps,
-            .pStdPPS = &vkpps,
-        };
-        hp->h264_pic_info.pNext = &h264_params;
-    }
-#endif
-
-    if (!hp->h264_pic_info.sliceCount)
-        return 0;
-
-    if (!vp->slices_buf)
-        return AVERROR(EINVAL);
-
-    if (!dec->session_params &&
-        !(ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)) {
-        int err = vk_h264_create_params(avctx, &dec->session_params);
-        if (err < 0)
-            return err;
-
-        hp->h264pic.seq_parameter_set_id = pic->pps->sps_id;
-        hp->h264pic.pic_parameter_set_id = pic->pps->pps_id;
-    }
-
-    for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
-        H264Picture *rp = hp->ref_src[i];
-        H264VulkanDecodePicture *rhp = rp->hwaccel_picture_private;
-
-        rvp[i] = &rhp->vp;
-        rav[i] = hp->ref_src[i]->f;
-    }
-
-    av_log(avctx, AV_LOG_DEBUG, "Decoding frame, %"SIZE_SPECIFIER" bytes, %i slices\n",
-           vp->slices_size, hp->h264_pic_info.sliceCount);
-
-    return ff_vk_decode_frame(avctx, pic->f, vp, rav, rvp);
-}
-
-static void vk_h264_free_frame_priv(AVRefStructOpaque _hwctx, void *data)
-{
-    AVHWDeviceContext *hwctx = _hwctx.nc;
-    H264VulkanDecodePicture *hp = data;
-
-    /* Free frame resources, this also destroys the session parameters. */
-    ff_vk_decode_free_frame(hwctx, &hp->vp);
-}
-
-const FFHWAccel ff_h264_vulkan_hwaccel = {
-    .p.name                = "h264_vulkan",
-    .p.type                = AVMEDIA_TYPE_VIDEO,
-    .p.id                  = AV_CODEC_ID_H264,
-    .p.pix_fmt             = AV_PIX_FMT_VULKAN,
-    .start_frame           = &vk_h264_start_frame,
-    .decode_slice          = &vk_h264_decode_slice,
-    .end_frame             = &vk_h264_end_frame,
-    .free_frame_priv       = &vk_h264_free_frame_priv,
-    .frame_priv_data_size  = sizeof(H264VulkanDecodePicture),
-    .init                  = &ff_vk_decode_init,
-    .update_thread_context = &ff_vk_update_thread_context,
-    .decode_params         = &ff_vk_params_invalidate,
-    .flush                 = &ff_vk_decode_flush,
-    .uninit                = &ff_vk_decode_uninit,
-    .frame_params          = &ff_vk_frame_params,
-    .priv_data_size        = sizeof(FFVulkanDecodeContext),
-    .caps_internal         = HWACCEL_CAP_ASYNC_SAFE,
-};
-- 
2.49.1


From 84fd250275d641ad757fcf6a3e0a362a72f814a2 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:38:00 +0000
Subject: [PATCH 082/118] Changing vulkan file directory

---
 libavcodec/vulkan/vulkan_h264.c | 592 ++++++++++++++++++++++++++++++++
 1 file changed, 592 insertions(+)
 create mode 100644 libavcodec/vulkan/vulkan_h264.c

diff --git a/libavcodec/vulkan/vulkan_h264.c b/libavcodec/vulkan/vulkan_h264.c
new file mode 100644
index 0000000000..aebfd4b738
--- /dev/null
+++ b/libavcodec/vulkan/vulkan_h264.c
@@ -0,0 +1,592 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavcodec/h264dec.h"
+#include "libavcodec/h264_ps.h"
+
+#include "vulkan_decode.h"
+
+const FFVulkanDecodeDescriptor ff_vk_dec_h264_desc = {
+    .codec_id         = AV_CODEC_ID_H264,
+    .decode_extension = FF_VK_EXT_VIDEO_DECODE_H264,
+    .queue_flags      = VK_QUEUE_VIDEO_DECODE_BIT_KHR,
+    .decode_op        = VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR,
+    .ext_props = {
+        .extensionName = VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME,
+        .specVersion   = VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION,
+    },
+};
+
+typedef struct H264VulkanDecodePicture {
+    FFVulkanDecodePicture           vp;
+
+    /* Current picture */
+    StdVideoDecodeH264ReferenceInfo h264_ref;
+    VkVideoDecodeH264DpbSlotInfoKHR vkh264_ref;
+
+    /* Picture refs */
+    H264Picture                    *ref_src    [H264_MAX_PICTURE_COUNT];
+    StdVideoDecodeH264ReferenceInfo h264_refs  [H264_MAX_PICTURE_COUNT];
+    VkVideoDecodeH264DpbSlotInfoKHR vkh264_refs[H264_MAX_PICTURE_COUNT];
+
+    /* Current picture (contd.) */
+    StdVideoDecodeH264PictureInfo   h264pic;
+    VkVideoDecodeH264PictureInfoKHR h264_pic_info;
+} H264VulkanDecodePicture;
+
+const static int h264_scaling_list8_order[] = { 0, 3, 1, 4, 2, 5 };
+
+static int vk_h264_fill_pict(AVCodecContext *avctx, H264Picture **ref_src,
+                             VkVideoReferenceSlotInfoKHR *ref_slot,       /* Main structure */
+                             VkVideoPictureResourceInfoKHR *ref,          /* Goes in ^ */
+                             VkVideoDecodeH264DpbSlotInfoKHR *vkh264_ref, /* Goes in ^ */
+                             StdVideoDecodeH264ReferenceInfo *h264_ref,   /* Goes in ^ */
+                             H264Picture *pic, int is_current,
+                             int is_field, int picture_structure,
+                             int dpb_slot_index)
+{
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+    H264VulkanDecodePicture *hp = pic->hwaccel_picture_private;
+    FFVulkanDecodePicture *vkpic = &hp->vp;
+
+    int err = ff_vk_decode_prepare_frame(dec, pic->f, vkpic, is_current,
+                                         dec->dedicated_dpb);
+    if (err < 0)
+        return err;
+
+    *h264_ref = (StdVideoDecodeH264ReferenceInfo) {
+        .FrameNum = pic->long_ref ? pic->pic_id : pic->frame_num,
+        .PicOrderCnt = { pic->field_poc[0], pic->field_poc[1] },
+        .flags = (StdVideoDecodeH264ReferenceInfoFlags) {
+            .top_field_flag    = is_field ? !!(picture_structure & PICT_TOP_FIELD)    : 0,
+            .bottom_field_flag = is_field ? !!(picture_structure & PICT_BOTTOM_FIELD) : 0,
+            .used_for_long_term_reference = pic->reference && pic->long_ref,
+            /*
+             * flags.is_non_existing is used to indicate whether the picture is marked as
+             * “non-existing” as defined in section 8.2.5.2 of the ITU-T H.264 Specification;
+             * 8.2.5.2 Decoding process for gaps in frame_num
+             * corresponds to the code in h264_slice.c:h264_field_start,
+             * which sets the invalid_gap flag when decoding.
+             */
+            .is_non_existing = pic->invalid_gap,
+        },
+    };
+
+    *vkh264_ref = (VkVideoDecodeH264DpbSlotInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR,
+        .pStdReferenceInfo = h264_ref,
+    };
+
+    *ref = (VkVideoPictureResourceInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
+        .codedOffset = (VkOffset2D){ 0, 0 },
+        .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
+        .baseArrayLayer = ctx->common.layered_dpb ? dpb_slot_index : 0,
+        .imageViewBinding = vkpic->view.ref[0],
+    };
+
+    *ref_slot = (VkVideoReferenceSlotInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
+        .pNext = vkh264_ref,
+        .slotIndex = dpb_slot_index,
+        .pPictureResource = ref,
+    };
+
+    if (ref_src)
+        *ref_src = pic;
+
+    return 0;
+}
+
+static StdVideoH264LevelIdc convert_to_vk_level_idc(int level_idc)
+{
+    switch (level_idc) {
+    case 10: return STD_VIDEO_H264_LEVEL_IDC_1_0;
+    case 11: return STD_VIDEO_H264_LEVEL_IDC_1_1;
+    case 12: return STD_VIDEO_H264_LEVEL_IDC_1_2;
+    case 13: return STD_VIDEO_H264_LEVEL_IDC_1_3;
+    case 20: return STD_VIDEO_H264_LEVEL_IDC_2_0;
+    case 21: return STD_VIDEO_H264_LEVEL_IDC_2_1;
+    case 22: return STD_VIDEO_H264_LEVEL_IDC_2_2;
+    case 30: return STD_VIDEO_H264_LEVEL_IDC_3_0;
+    case 31: return STD_VIDEO_H264_LEVEL_IDC_3_1;
+    case 32: return STD_VIDEO_H264_LEVEL_IDC_3_2;
+    case 40: return STD_VIDEO_H264_LEVEL_IDC_4_0;
+    case 41: return STD_VIDEO_H264_LEVEL_IDC_4_1;
+    case 42: return STD_VIDEO_H264_LEVEL_IDC_4_2;
+    case 50: return STD_VIDEO_H264_LEVEL_IDC_5_0;
+    case 51: return STD_VIDEO_H264_LEVEL_IDC_5_1;
+    case 52: return STD_VIDEO_H264_LEVEL_IDC_5_2;
+    case 60: return STD_VIDEO_H264_LEVEL_IDC_6_0;
+    case 61: return STD_VIDEO_H264_LEVEL_IDC_6_1;
+    default:
+    case 62: return STD_VIDEO_H264_LEVEL_IDC_6_2;
+    }
+}
+
+static void set_sps(const SPS *sps,
+                    StdVideoH264ScalingLists *vksps_scaling,
+                    StdVideoH264HrdParameters *vksps_vui_header,
+                    StdVideoH264SequenceParameterSetVui *vksps_vui,
+                    StdVideoH264SequenceParameterSet *vksps)
+{
+    *vksps_scaling = (StdVideoH264ScalingLists) {
+        .scaling_list_present_mask = sps->scaling_matrix_present_mask,
+        .use_default_scaling_matrix_mask = 0, /* We already fill in the default matrix */
+    };
+
+    for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS; i++)
+        for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS; j++)
+            vksps_scaling->ScalingList4x4[i][j] = sps->scaling_matrix4[i][ff_zigzag_scan[j]];
+
+    for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS; i++)
+        for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS; j++)
+            vksps_scaling->ScalingList8x8[i][j] =
+                sps->scaling_matrix8[h264_scaling_list8_order[i]][ff_zigzag_direct[j]];
+
+    *vksps_vui_header = (StdVideoH264HrdParameters) {
+        .cpb_cnt_minus1 = sps->cpb_cnt - 1,
+        .bit_rate_scale = sps->bit_rate_scale,
+        .initial_cpb_removal_delay_length_minus1 = sps->initial_cpb_removal_delay_length - 1,
+        .cpb_removal_delay_length_minus1 = sps->cpb_removal_delay_length - 1,
+        .dpb_output_delay_length_minus1 = sps->dpb_output_delay_length - 1,
+        .time_offset_length = sps->time_offset_length,
+    };
+
+    for (int i = 0; i < sps->cpb_cnt; i++) {
+        vksps_vui_header->bit_rate_value_minus1[i] = sps->bit_rate_value[i] - 1;
+        vksps_vui_header->cpb_size_value_minus1[i] = sps->cpb_size_value[i] - 1;
+        vksps_vui_header->cbr_flag[i] = (sps->cpr_flag >> i) & 0x1;
+    }
+
+    *vksps_vui = (StdVideoH264SequenceParameterSetVui) {
+        .aspect_ratio_idc = sps->vui.aspect_ratio_idc,
+        .sar_width = sps->vui.sar.num,
+        .sar_height = sps->vui.sar.den,
+        .video_format = sps->vui.video_format,
+        .colour_primaries = sps->vui.colour_primaries,
+        .transfer_characteristics = sps->vui.transfer_characteristics,
+        .matrix_coefficients = sps->vui.matrix_coeffs,
+        .num_units_in_tick = sps->num_units_in_tick,
+        .time_scale = sps->time_scale,
+        .pHrdParameters = vksps_vui_header,
+        .max_num_reorder_frames = sps->num_reorder_frames,
+        .max_dec_frame_buffering = sps->max_dec_frame_buffering,
+        .flags = (StdVideoH264SpsVuiFlags) {
+            .aspect_ratio_info_present_flag = sps->vui.aspect_ratio_info_present_flag,
+            .overscan_info_present_flag = sps->vui.overscan_info_present_flag,
+            .overscan_appropriate_flag = sps->vui.overscan_appropriate_flag,
+            .video_signal_type_present_flag = sps->vui.video_signal_type_present_flag,
+            .video_full_range_flag = sps->vui.video_full_range_flag,
+            .color_description_present_flag = sps->vui.colour_description_present_flag,
+            .chroma_loc_info_present_flag = sps->vui.chroma_location,
+            .timing_info_present_flag = sps->timing_info_present_flag,
+            .fixed_frame_rate_flag = sps->fixed_frame_rate_flag,
+            .bitstream_restriction_flag = sps->bitstream_restriction_flag,
+            .nal_hrd_parameters_present_flag = sps->nal_hrd_parameters_present_flag,
+            .vcl_hrd_parameters_present_flag = sps->vcl_hrd_parameters_present_flag,
+        },
+    };
+
+    *vksps = (StdVideoH264SequenceParameterSet) {
+        .profile_idc = sps->profile_idc,
+        .level_idc = convert_to_vk_level_idc(sps->level_idc),
+        .seq_parameter_set_id = sps->sps_id,
+        .chroma_format_idc = sps->chroma_format_idc,
+        .bit_depth_luma_minus8 = sps->bit_depth_luma - 8,
+        .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8,
+        .log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4,
+        .pic_order_cnt_type = sps->poc_type,
+        .log2_max_pic_order_cnt_lsb_minus4 = sps->poc_type ? 0 : sps->log2_max_poc_lsb - 4,
+        .offset_for_non_ref_pic = sps->offset_for_non_ref_pic,
+        .offset_for_top_to_bottom_field = sps->offset_for_top_to_bottom_field,
+        .num_ref_frames_in_pic_order_cnt_cycle = sps->poc_cycle_length,
+        .max_num_ref_frames = sps->ref_frame_count,
+        .pic_width_in_mbs_minus1 = sps->mb_width - 1,
+        .pic_height_in_map_units_minus1 = (sps->mb_height/(2 - sps->frame_mbs_only_flag)) - 1,
+        .frame_crop_left_offset = sps->crop_left,
+        .frame_crop_right_offset = sps->crop_right,
+        .frame_crop_top_offset = sps->crop_top,
+        .frame_crop_bottom_offset = sps->crop_bottom,
+        .flags = (StdVideoH264SpsFlags) {
+            .constraint_set0_flag = (sps->constraint_set_flags >> 0) & 0x1,
+            .constraint_set1_flag = (sps->constraint_set_flags >> 1) & 0x1,
+            .constraint_set2_flag = (sps->constraint_set_flags >> 2) & 0x1,
+            .constraint_set3_flag = (sps->constraint_set_flags >> 3) & 0x1,
+            .constraint_set4_flag = (sps->constraint_set_flags >> 4) & 0x1,
+            .constraint_set5_flag = (sps->constraint_set_flags >> 5) & 0x1,
+            .direct_8x8_inference_flag = sps->direct_8x8_inference_flag,
+            .mb_adaptive_frame_field_flag = sps->mb_aff,
+            .frame_mbs_only_flag = sps->frame_mbs_only_flag,
+            .delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag,
+            .separate_colour_plane_flag = sps->residual_color_transform_flag,
+            .gaps_in_frame_num_value_allowed_flag = sps->gaps_in_frame_num_allowed_flag,
+            .qpprime_y_zero_transform_bypass_flag = sps->transform_bypass,
+            .frame_cropping_flag = sps->crop,
+            .seq_scaling_matrix_present_flag = sps->scaling_matrix_present,
+            .vui_parameters_present_flag = sps->vui_parameters_present_flag,
+        },
+        .pOffsetForRefFrame = sps->offset_for_ref_frame,
+        .pScalingLists = vksps_scaling,
+        .pSequenceParameterSetVui = vksps_vui,
+    };
+}
+
+static void set_pps(const PPS *pps, const SPS *sps,
+                    StdVideoH264ScalingLists *vkpps_scaling,
+                    StdVideoH264PictureParameterSet *vkpps)
+{
+    *vkpps_scaling = (StdVideoH264ScalingLists) {
+        .scaling_list_present_mask = pps->pic_scaling_matrix_present_mask,
+        .use_default_scaling_matrix_mask = 0, /* We already fill in the default matrix */
+    };
+
+    for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS; i++)
+        for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS; j++)
+            vkpps_scaling->ScalingList4x4[i][j] = pps->scaling_matrix4[i][ff_zigzag_scan[j]];
+
+    for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS; i++)
+        for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS; j++)
+            vkpps_scaling->ScalingList8x8[i][j] =
+                pps->scaling_matrix8[h264_scaling_list8_order[i]][ff_zigzag_direct[j]];
+
+    *vkpps = (StdVideoH264PictureParameterSet) {
+        .seq_parameter_set_id = pps->sps_id,
+        .pic_parameter_set_id = pps->pps_id,
+        .num_ref_idx_l0_default_active_minus1 = pps->ref_count[0] - 1,
+        .num_ref_idx_l1_default_active_minus1 = pps->ref_count[1] - 1,
+        .weighted_bipred_idc = pps->weighted_bipred_idc,
+        .pic_init_qp_minus26 = pps->init_qp - 26,
+        .pic_init_qs_minus26 = pps->init_qs - 26,
+        .chroma_qp_index_offset = pps->chroma_qp_index_offset[0],
+        .second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1],
+        .flags = (StdVideoH264PpsFlags) {
+            .transform_8x8_mode_flag = pps->transform_8x8_mode,
+            .redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present,
+            .constrained_intra_pred_flag = pps->constrained_intra_pred,
+            .deblocking_filter_control_present_flag = pps->deblocking_filter_parameters_present,
+            .weighted_pred_flag = pps->weighted_pred,
+            .bottom_field_pic_order_in_frame_present_flag = pps->pic_order_present,
+            .entropy_coding_mode_flag = pps->cabac,
+            .pic_scaling_matrix_present_flag = pps->pic_scaling_matrix_present_flag,
+        },
+        .pScalingLists = vkpps_scaling,
+    };
+}
+
+static int vk_h264_create_params(AVCodecContext *avctx, AVBufferRef **buf)
+{
+    int err;
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+    const H264Context *h = avctx->priv_data;
+
+    /* SPS */
+    StdVideoH264ScalingLists vksps_scaling[MAX_SPS_COUNT];
+    StdVideoH264HrdParameters vksps_vui_header[MAX_SPS_COUNT];
+    StdVideoH264SequenceParameterSetVui vksps_vui[MAX_SPS_COUNT];
+    StdVideoH264SequenceParameterSet vksps[MAX_SPS_COUNT];
+
+    /* PPS */
+    StdVideoH264ScalingLists vkpps_scaling[MAX_PPS_COUNT];
+    StdVideoH264PictureParameterSet vkpps[MAX_PPS_COUNT];
+
+    VkVideoDecodeH264SessionParametersAddInfoKHR h264_params_info = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR,
+        .pStdSPSs = vksps,
+        .stdSPSCount = 0,
+        .pStdPPSs = vkpps,
+        .stdPPSCount = 0,
+    };
+    VkVideoDecodeH264SessionParametersCreateInfoKHR h264_params = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR,
+        .pParametersAddInfo = &h264_params_info,
+    };
+    VkVideoSessionParametersCreateInfoKHR session_params_create = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
+        .pNext = &h264_params,
+        .videoSession = ctx->common.session,
+        .videoSessionParametersTemplate = VK_NULL_HANDLE,
+    };
+
+    /* SPS list */
+    for (int i = 0; i < FF_ARRAY_ELEMS(h->ps.sps_list); i++) {
+        if (h->ps.sps_list[i]) {
+            const SPS *sps_l = h->ps.sps_list[i];
+            int idx = h264_params_info.stdSPSCount;
+            set_sps(sps_l, &vksps_scaling[idx], &vksps_vui_header[idx], &vksps_vui[idx], &vksps[idx]);
+            h264_params_info.stdSPSCount++;
+        }
+    }
+
+    /* PPS list */
+    for (int i = 0; i < FF_ARRAY_ELEMS(h->ps.pps_list); i++) {
+        if (h->ps.pps_list[i]) {
+            const PPS *pps_l = h->ps.pps_list[i];
+            int idx = h264_params_info.stdPPSCount;
+            set_pps(pps_l, pps_l->sps, &vkpps_scaling[idx], &vkpps[idx]);
+            h264_params_info.stdPPSCount++;
+        }
+    }
+
+    h264_params.maxStdSPSCount = h264_params_info.stdSPSCount;
+    h264_params.maxStdPPSCount = h264_params_info.stdPPSCount;
+
+    err = ff_vk_decode_create_params(buf, avctx, ctx, &session_params_create);
+    if (err < 0)
+        return err;
+
+    av_log(avctx, AV_LOG_DEBUG, "Created frame parameters: %i SPS %i PPS\n",
+           h264_params_info.stdSPSCount, h264_params_info.stdPPSCount);
+
+    return 0;
+}
+
+static int vk_h264_start_frame(AVCodecContext          *avctx,
+                               av_unused const AVBufferRef *buffer_ref,
+                               av_unused const uint8_t *buffer,
+                               av_unused uint32_t       size)
+{
+    int err;
+    int dpb_slot_index = 0;
+    H264Context *h = avctx->priv_data;
+
+    H264Picture *pic = h->cur_pic_ptr;
+    H264VulkanDecodePicture *hp = pic->hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &hp->vp;
+
+    /* Fill in main slot */
+    dpb_slot_index = 0;
+    for (unsigned slot = 0; slot < H264_MAX_PICTURE_COUNT; slot++) {
+        if (pic == &h->DPB[slot]) {
+            dpb_slot_index = slot;
+            break;
+        }
+    }
+
+    err = vk_h264_fill_pict(avctx, NULL, &vp->ref_slot, &vp->ref,
+                            &hp->vkh264_ref, &hp->h264_ref, pic, 1,
+                            h->DPB[dpb_slot_index].field_picture,
+                            h->DPB[dpb_slot_index].reference,
+                            dpb_slot_index);
+    if (err < 0)
+        return err;
+
+    /* Fill in short-term references */
+    for (int i = 0; i < h->short_ref_count; i++) {
+        dpb_slot_index = 0;
+        for (unsigned slot = 0; slot < H264_MAX_PICTURE_COUNT; slot++) {
+            if (h->short_ref[i] == &h->DPB[slot]) {
+                dpb_slot_index = slot;
+                break;
+            }
+        }
+        err = vk_h264_fill_pict(avctx, &hp->ref_src[i], &vp->ref_slots[i],
+                                &vp->refs[i], &hp->vkh264_refs[i],
+                                &hp->h264_refs[i], h->short_ref[i], 0,
+                                h->DPB[dpb_slot_index].field_picture,
+                                h->DPB[dpb_slot_index].reference,
+                                dpb_slot_index);
+        if (err < 0)
+            return err;
+    }
+
+    /* Fill in long-term refs */
+    for (int r = 0, i = h->short_ref_count; r < H264_MAX_DPB_FRAMES &&
+         i < h->short_ref_count + h->long_ref_count; r++) {
+        if (!h->long_ref[r])
+            continue;
+
+        dpb_slot_index = 0;
+        for (unsigned slot = 0; slot < 16; slot++) {
+            if (h->long_ref[r] == &h->DPB[slot]) {
+                dpb_slot_index = slot;
+                break;
+            }
+        }
+        err = vk_h264_fill_pict(avctx, &hp->ref_src[i], &vp->ref_slots[i],
+                                &vp->refs[i], &hp->vkh264_refs[i],
+                                &hp->h264_refs[i], h->long_ref[r], 0,
+                                h->DPB[dpb_slot_index].field_picture,
+                                h->DPB[dpb_slot_index].reference,
+                                dpb_slot_index);
+        if (err < 0)
+            return err;
+        i++;
+    }
+
+    hp->h264pic = (StdVideoDecodeH264PictureInfo) {
+        .seq_parameter_set_id = pic->pps->sps_id,
+        .pic_parameter_set_id = pic->pps->pps_id,
+        .frame_num = 0,  /* Set later */
+        .idr_pic_id = 0, /* Set later */
+        .PicOrderCnt[0] = pic->field_poc[0],
+        .PicOrderCnt[1] = pic->field_poc[1],
+        .flags = (StdVideoDecodeH264PictureInfoFlags) {
+            .field_pic_flag = FIELD_PICTURE(h),
+            .is_intra = 1, /* Set later */
+            .IdrPicFlag = h->picture_idr,
+            .bottom_field_flag = h->picture_structure != PICT_FRAME &&
+                                 h->picture_structure & PICT_BOTTOM_FIELD,
+            .is_reference = h->nal_ref_idc != 0,
+            .complementary_field_pair = h->first_field && FIELD_PICTURE(h),
+        },
+    };
+
+    hp->h264_pic_info = (VkVideoDecodeH264PictureInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_KHR,
+        .pStdPictureInfo = &hp->h264pic,
+    };
+
+    vp->decode_info = (VkVideoDecodeInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR,
+        .pNext = &hp->h264_pic_info,
+        .flags = 0x0,
+        .pSetupReferenceSlot = &vp->ref_slot,
+        .referenceSlotCount = h->short_ref_count + h->long_ref_count,
+        .pReferenceSlots = vp->ref_slots,
+        .dstPictureResource = (VkVideoPictureResourceInfoKHR) {
+            .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
+            .codedOffset = (VkOffset2D){ 0, 0 },
+            .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
+            .baseArrayLayer = 0,
+            .imageViewBinding = vp->view.out[0],
+        },
+    };
+
+    return 0;
+}
+
+static int vk_h264_decode_slice(AVCodecContext *avctx,
+                                const uint8_t  *data,
+                                uint32_t        size)
+{
+    const H264Context *h = avctx->priv_data;
+    const H264SliceContext *sl  = &h->slice_ctx[0];
+    H264VulkanDecodePicture *hp = h->cur_pic_ptr->hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &hp->vp;
+
+    int err = ff_vk_decode_add_slice(avctx, vp, data, size, 1,
+                                     &hp->h264_pic_info.sliceCount,
+                                     &hp->h264_pic_info.pSliceOffsets);
+    if (err < 0)
+        return err;
+
+    hp->h264pic.frame_num = sl->frame_num;
+    hp->h264pic.idr_pic_id = sl->idr_pic_id;
+
+    /* Frame is only intra of all slices are marked as intra */
+    if (sl->slice_type != AV_PICTURE_TYPE_I && sl->slice_type != AV_PICTURE_TYPE_SI)
+        hp->h264pic.flags.is_intra = 0;
+
+    return 0;
+}
+
+static int vk_h264_end_frame(AVCodecContext *avctx)
+{
+    const H264Context *h = avctx->priv_data;
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+
+    H264Picture *pic = h->cur_pic_ptr;
+    H264VulkanDecodePicture *hp = pic->hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &hp->vp;
+    FFVulkanDecodePicture *rvp[H264_MAX_PICTURE_COUNT] = { 0 };
+    AVFrame *rav[H264_MAX_PICTURE_COUNT] = { 0 };
+
+#ifdef VK_KHR_video_maintenance2
+    StdVideoH264ScalingLists vksps_scaling;
+    StdVideoH264HrdParameters vksps_vui_header;
+    StdVideoH264SequenceParameterSetVui vksps_vui;
+    StdVideoH264SequenceParameterSet vksps;
+    StdVideoH264ScalingLists vkpps_scaling;
+    StdVideoH264PictureParameterSet vkpps;
+    VkVideoDecodeH264InlineSessionParametersInfoKHR h264_params;
+
+    if (ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2) {
+        set_sps(h->ps.sps, &vksps_scaling,
+                &vksps_vui_header, &vksps_vui, &vksps);
+        set_pps(h->ps.pps, h->ps.sps, &vkpps_scaling, &vkpps);
+        h264_params = (VkVideoDecodeH264InlineSessionParametersInfoKHR) {
+            .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_INLINE_SESSION_PARAMETERS_INFO_KHR,
+            .pStdSPS = &vksps,
+            .pStdPPS = &vkpps,
+        };
+        hp->h264_pic_info.pNext = &h264_params;
+    }
+#endif
+
+    if (!hp->h264_pic_info.sliceCount)
+        return 0;
+
+    if (!vp->slices_buf)
+        return AVERROR(EINVAL);
+
+    if (!dec->session_params &&
+        !(ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)) {
+        int err = vk_h264_create_params(avctx, &dec->session_params);
+        if (err < 0)
+            return err;
+
+        hp->h264pic.seq_parameter_set_id = pic->pps->sps_id;
+        hp->h264pic.pic_parameter_set_id = pic->pps->pps_id;
+    }
+
+    for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
+        H264Picture *rp = hp->ref_src[i];
+        H264VulkanDecodePicture *rhp = rp->hwaccel_picture_private;
+
+        rvp[i] = &rhp->vp;
+        rav[i] = hp->ref_src[i]->f;
+    }
+
+    av_log(avctx, AV_LOG_DEBUG, "Decoding frame, %"SIZE_SPECIFIER" bytes, %i slices\n",
+           vp->slices_size, hp->h264_pic_info.sliceCount);
+
+    return ff_vk_decode_frame(avctx, pic->f, vp, rav, rvp);
+}
+
+static void vk_h264_free_frame_priv(AVRefStructOpaque _hwctx, void *data)
+{
+    AVHWDeviceContext *hwctx = _hwctx.nc;
+    H264VulkanDecodePicture *hp = data;
+
+    /* Free frame resources, this also destroys the session parameters. */
+    ff_vk_decode_free_frame(hwctx, &hp->vp);
+}
+
+const FFHWAccel ff_h264_vulkan_hwaccel = {
+    .p.name                = "h264_vulkan",
+    .p.type                = AVMEDIA_TYPE_VIDEO,
+    .p.id                  = AV_CODEC_ID_H264,
+    .p.pix_fmt             = AV_PIX_FMT_VULKAN,
+    .start_frame           = &vk_h264_start_frame,
+    .decode_slice          = &vk_h264_decode_slice,
+    .end_frame             = &vk_h264_end_frame,
+    .free_frame_priv       = &vk_h264_free_frame_priv,
+    .frame_priv_data_size  = sizeof(H264VulkanDecodePicture),
+    .init                  = &ff_vk_decode_init,
+    .update_thread_context = &ff_vk_update_thread_context,
+    .decode_params         = &ff_vk_params_invalidate,
+    .flush                 = &ff_vk_decode_flush,
+    .uninit                = &ff_vk_decode_uninit,
+    .frame_params          = &ff_vk_frame_params,
+    .priv_data_size        = sizeof(FFVulkanDecodeContext),
+    .caps_internal         = HWACCEL_CAP_ASYNC_SAFE,
+};
-- 
2.49.1


From 78b6ad6ce91af3ba55cb81a538b4fbc4c8dce703 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:38:26 +0000
Subject: [PATCH 083/118] Changing vulkan file directory

---
 libavcodec/vulkan_hevc.c | 957 ---------------------------------------
 1 file changed, 957 deletions(-)
 delete mode 100644 libavcodec/vulkan_hevc.c

diff --git a/libavcodec/vulkan_hevc.c b/libavcodec/vulkan_hevc.c
deleted file mode 100644
index 5e15c6b931..0000000000
--- a/libavcodec/vulkan_hevc.c
+++ /dev/null
@@ -1,957 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/mem.h"
-#include "hevc/hevcdec.h"
-#include "hevc/data.h"
-#include "hevc/ps.h"
-
-#include "vulkan_decode.h"
-
-const FFVulkanDecodeDescriptor ff_vk_dec_hevc_desc = {
-    .codec_id         = AV_CODEC_ID_HEVC,
-    .decode_extension = FF_VK_EXT_VIDEO_DECODE_H265,
-    .queue_flags      = VK_QUEUE_VIDEO_DECODE_BIT_KHR,
-    .decode_op        = VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR,
-    .ext_props = {
-        .extensionName = VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME,
-        .specVersion   = VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION,
-    },
-};
-
-typedef struct HEVCHeaderSPS {
-    StdVideoH265ScalingLists scaling;
-    StdVideoH265HrdParameters vui_header;
-    StdVideoH265SequenceParameterSetVui vui;
-    StdVideoH265ProfileTierLevel ptl;
-    StdVideoH265DecPicBufMgr dpbm;
-    StdVideoH265PredictorPaletteEntries pal;
-    StdVideoH265SubLayerHrdParameters nal_hdr[HEVC_MAX_SUB_LAYERS];
-    StdVideoH265SubLayerHrdParameters vcl_hdr[HEVC_MAX_SUB_LAYERS];
-    StdVideoH265ShortTermRefPicSet str[HEVC_MAX_SHORT_TERM_REF_PIC_SETS];
-    StdVideoH265LongTermRefPicsSps ltr;
-} HEVCHeaderSPS;
-
-typedef struct HEVCHeaderPPS {
-    StdVideoH265ScalingLists scaling;
-    StdVideoH265PredictorPaletteEntries pal;
-} HEVCHeaderPPS;
-
-typedef struct HEVCHeaderVPSSet {
-    StdVideoH265SubLayerHrdParameters nal_hdr[HEVC_MAX_SUB_LAYERS];
-    StdVideoH265SubLayerHrdParameters vcl_hdr[HEVC_MAX_SUB_LAYERS];
-} HEVCHeaderVPSSet;
-
-typedef struct HEVCHeaderVPS {
-    StdVideoH265ProfileTierLevel ptl;
-    StdVideoH265DecPicBufMgr dpbm;
-    StdVideoH265HrdParameters hdr[HEVC_MAX_LAYER_SETS];
-    HEVCHeaderVPSSet *sls;
-} HEVCHeaderVPS;
-
-typedef struct HEVCHeaderSet {
-    StdVideoH265SequenceParameterSet sps[HEVC_MAX_SPS_COUNT];
-    HEVCHeaderSPS hsps[HEVC_MAX_SPS_COUNT];
-
-    StdVideoH265PictureParameterSet pps[HEVC_MAX_PPS_COUNT];
-    HEVCHeaderPPS hpps[HEVC_MAX_PPS_COUNT];
-
-    StdVideoH265VideoParameterSet vps[HEVC_MAX_PPS_COUNT];
-    HEVCHeaderVPS *hvps;
-} HEVCHeaderSet;
-
-static int alloc_hevc_header_structs(FFVulkanDecodeContext *s,
-                                     int nb_vps,
-                                     const int vps_list_idx[HEVC_MAX_VPS_COUNT],
-                                     const HEVCVPS * const vps_list[HEVC_MAX_VPS_COUNT])
-{
-    uint8_t *data_ptr;
-    HEVCHeaderSet *hdr;
-
-    size_t buf_size = sizeof(HEVCHeaderSet) + nb_vps*sizeof(HEVCHeaderVPS);
-    for (int i = 0; i < nb_vps; i++) {
-        const HEVCVPS *vps = vps_list[vps_list_idx[i]];
-        buf_size += sizeof(HEVCHeaderVPSSet)*vps->vps_num_hrd_parameters;
-    }
-
-    if (buf_size > s->hevc_headers_size) {
-        av_freep(&s->hevc_headers);
-        s->hevc_headers_size = 0;
-        s->hevc_headers = av_mallocz(buf_size);
-        if (!s->hevc_headers)
-            return AVERROR(ENOMEM);
-        s->hevc_headers_size = buf_size;
-    }
-
-    /* Setup struct pointers */
-    hdr = s->hevc_headers;
-    data_ptr = (uint8_t *)hdr;
-    hdr->hvps = (HEVCHeaderVPS *)(data_ptr + sizeof(HEVCHeaderSet));
-    data_ptr += sizeof(HEVCHeaderSet) + nb_vps*sizeof(HEVCHeaderVPS);
-    for (int i = 0; i < nb_vps; i++) {
-        const HEVCVPS *vps = vps_list[vps_list_idx[i]];
-        hdr->hvps[i].sls = (HEVCHeaderVPSSet *)data_ptr;
-        data_ptr += sizeof(HEVCHeaderVPSSet)*vps->vps_num_hrd_parameters;
-    }
-
-    return 0;
-}
-
-typedef struct HEVCVulkanDecodePicture {
-    FFVulkanDecodePicture           vp;
-
-    /* Current picture */
-    StdVideoDecodeH265ReferenceInfo h265_ref;
-    VkVideoDecodeH265DpbSlotInfoKHR vkh265_ref;
-
-    /* Picture refs */
-    HEVCFrame                      *ref_src    [HEVC_MAX_REFS];
-    StdVideoDecodeH265ReferenceInfo h265_refs  [HEVC_MAX_REFS];
-    VkVideoDecodeH265DpbSlotInfoKHR vkh265_refs[HEVC_MAX_REFS];
-
-    /* Current picture (contd.) */
-    StdVideoDecodeH265PictureInfo   h265pic;
-    VkVideoDecodeH265PictureInfoKHR h265_pic_info;
-} HEVCVulkanDecodePicture;
-
-static int vk_hevc_fill_pict(AVCodecContext *avctx, HEVCFrame **ref_src,
-                             VkVideoReferenceSlotInfoKHR *ref_slot,       /* Main structure */
-                             VkVideoPictureResourceInfoKHR *ref,          /* Goes in ^ */
-                             VkVideoDecodeH265DpbSlotInfoKHR *vkh265_ref, /* Goes in ^ */
-                             StdVideoDecodeH265ReferenceInfo *h265_ref,   /* Goes in ^ */
-                             HEVCFrame *pic, int is_current, int pic_id)
-{
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-    HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private;
-    FFVulkanDecodePicture *vkpic = &hp->vp;
-
-    int err = ff_vk_decode_prepare_frame(dec, pic->f, vkpic, is_current,
-                                         dec->dedicated_dpb);
-    if (err < 0)
-        return err;
-
-    *h265_ref = (StdVideoDecodeH265ReferenceInfo) {
-        .flags = (StdVideoDecodeH265ReferenceInfoFlags) {
-            .used_for_long_term_reference = pic->flags & HEVC_FRAME_FLAG_LONG_REF,
-            .unused_for_reference = 0,
-        },
-        .PicOrderCntVal = pic->poc,
-    };
-
-    *vkh265_ref = (VkVideoDecodeH265DpbSlotInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_KHR,
-        .pStdReferenceInfo = h265_ref,
-    };
-
-    *ref = (VkVideoPictureResourceInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
-        .codedOffset = (VkOffset2D){ 0, 0 },
-        .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
-        .baseArrayLayer = ctx->common.layered_dpb ? pic_id : 0,
-        .imageViewBinding = vkpic->view.ref[0],
-    };
-
-    *ref_slot = (VkVideoReferenceSlotInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
-        .pNext = vkh265_ref,
-        .slotIndex = pic_id,
-        .pPictureResource = ref,
-    };
-
-    if (ref_src)
-        *ref_src = pic;
-
-    return 0;
-}
-
-static void copy_scaling_list(const ScalingList *sl, StdVideoH265ScalingLists *vksl)
-{
-    for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS; i++) {
-        for (int j = 0; j < STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS; j++) {
-            uint8_t pos = 4 * ff_hevc_diag_scan4x4_y[j] + ff_hevc_diag_scan4x4_x[j];
-            vksl->ScalingList4x4[i][j] = sl->sl[0][i][pos];
-        }
-    }
-
-    for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS; i++) {
-        for (int j = 0; j < STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS; j++) {
-            uint8_t pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j];
-            vksl->ScalingList8x8[i][j] = sl->sl[1][i][pos];
-        }
-    }
-
-    for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS; i++) {
-        for (int j = 0; j < STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS; j++) {
-            uint8_t pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j];
-            vksl->ScalingList16x16[i][j] = sl->sl[2][i][pos];
-        }
-    }
-
-    for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) {
-        for (int j = 0; j < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS; j++) {
-            uint8_t pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j];
-            vksl->ScalingList32x32[i][j] = sl->sl[3][i * 3][pos];
-        }
-    }
-
-    memcpy(vksl->ScalingListDCCoef16x16, sl->sl_dc[0],
-           STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS * sizeof(*vksl->ScalingListDCCoef16x16));
-
-    for (int i = 0; i <  STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++)
-        vksl->ScalingListDCCoef32x32[i] = sl->sl_dc[1][i * 3];
-}
-
-static void set_sps(const HEVCSPS *sps, int sps_idx,
-                    StdVideoH265ScalingLists *vksps_scaling,
-                    StdVideoH265HrdParameters *vksps_vui_header,
-                    StdVideoH265SequenceParameterSetVui *vksps_vui,
-                    StdVideoH265SequenceParameterSet *vksps,
-                    StdVideoH265SubLayerHrdParameters *slhdrnal,
-                    StdVideoH265SubLayerHrdParameters *slhdrvcl,
-                    StdVideoH265ProfileTierLevel *ptl,
-                    StdVideoH265DecPicBufMgr *dpbm,
-                    StdVideoH265PredictorPaletteEntries *pal,
-                    StdVideoH265ShortTermRefPicSet *str,
-                    StdVideoH265LongTermRefPicsSps *ltr)
-{
-    copy_scaling_list(&sps->scaling_list, vksps_scaling);
-
-    *vksps_vui_header = (StdVideoH265HrdParameters) {
-        .flags = (StdVideoH265HrdFlags) {
-            .nal_hrd_parameters_present_flag = sps->hdr.nal_hrd_parameters_present_flag,
-            .vcl_hrd_parameters_present_flag = sps->hdr.vcl_hrd_parameters_present_flag,
-            .sub_pic_hrd_params_present_flag = sps->hdr.sub_pic_hrd_params_present_flag,
-            .sub_pic_cpb_params_in_pic_timing_sei_flag = sps->hdr.sub_pic_cpb_params_in_pic_timing_sei_flag,
-            .fixed_pic_rate_general_flag = sps->hdr.flags.fixed_pic_rate_general_flag,
-            .fixed_pic_rate_within_cvs_flag = sps->hdr.flags.fixed_pic_rate_within_cvs_flag,
-            .low_delay_hrd_flag = sps->hdr.flags.low_delay_hrd_flag,
-        },
-        .tick_divisor_minus2 = sps->hdr.tick_divisor_minus2,
-        .du_cpb_removal_delay_increment_length_minus1 = sps->hdr.du_cpb_removal_delay_increment_length_minus1,
-        .dpb_output_delay_du_length_minus1 = sps->hdr.dpb_output_delay_du_length_minus1,
-        .bit_rate_scale = sps->hdr.bit_rate_scale,
-        .cpb_size_scale = sps->hdr.cpb_size_scale,
-        .cpb_size_du_scale = sps->hdr.cpb_size_du_scale,
-        .initial_cpb_removal_delay_length_minus1 = sps->hdr.initial_cpb_removal_delay_length_minus1,
-        .au_cpb_removal_delay_length_minus1 = sps->hdr.au_cpb_removal_delay_length_minus1,
-        .dpb_output_delay_length_minus1 = sps->hdr.dpb_output_delay_length_minus1,
-        /* Reserved - 3*16 bits */
-        .pSubLayerHrdParametersNal = slhdrnal,
-        .pSubLayerHrdParametersVcl = slhdrvcl,
-    };
-
-    memcpy(vksps_vui_header->cpb_cnt_minus1, sps->hdr.cpb_cnt_minus1,
-           STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*vksps_vui_header->cpb_cnt_minus1));
-    memcpy(vksps_vui_header->elemental_duration_in_tc_minus1, sps->hdr.elemental_duration_in_tc_minus1,
-           STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*vksps_vui_header->elemental_duration_in_tc_minus1));
-
-    memcpy(slhdrnal, sps->hdr.nal_params, HEVC_MAX_SUB_LAYERS*sizeof(*slhdrnal));
-    memcpy(slhdrvcl, sps->hdr.vcl_params, HEVC_MAX_SUB_LAYERS*sizeof(*slhdrvcl));
-
-    *vksps_vui = (StdVideoH265SequenceParameterSetVui) {
-        .flags = (StdVideoH265SpsVuiFlags) {
-            .aspect_ratio_info_present_flag = sps->vui.common.aspect_ratio_info_present_flag,
-            .overscan_info_present_flag = sps->vui.common.overscan_info_present_flag,
-            .overscan_appropriate_flag = sps->vui.common.overscan_appropriate_flag,
-            .video_signal_type_present_flag = sps->vui.common.video_signal_type_present_flag,
-            .video_full_range_flag = sps->vui.common.video_full_range_flag,
-            .colour_description_present_flag = sps->vui.common.colour_description_present_flag,
-            .chroma_loc_info_present_flag = sps->vui.common.chroma_loc_info_present_flag,
-            .neutral_chroma_indication_flag = sps->vui.neutra_chroma_indication_flag,
-            .field_seq_flag = sps->vui.field_seq_flag,
-            .frame_field_info_present_flag = sps->vui.frame_field_info_present_flag,
-            .default_display_window_flag = sps->vui.default_display_window_flag,
-            .vui_timing_info_present_flag = sps->vui.vui_timing_info_present_flag,
-            .vui_poc_proportional_to_timing_flag = sps->vui.vui_poc_proportional_to_timing_flag,
-            .vui_hrd_parameters_present_flag = sps->vui.vui_hrd_parameters_present_flag,
-            .bitstream_restriction_flag = sps->vui.bitstream_restriction_flag,
-            .tiles_fixed_structure_flag = sps->vui.tiles_fixed_structure_flag,
-            .motion_vectors_over_pic_boundaries_flag = sps->vui.motion_vectors_over_pic_boundaries_flag,
-            .restricted_ref_pic_lists_flag = sps->vui.restricted_ref_pic_lists_flag,
-        },
-        .aspect_ratio_idc = sps->vui.common.aspect_ratio_idc,
-        .sar_width = sps->vui.common.sar.num,
-        .sar_height = sps->vui.common.sar.den,
-        .video_format = sps->vui.common.video_format,
-        .colour_primaries = sps->vui.common.colour_primaries,
-        .transfer_characteristics = sps->vui.common.transfer_characteristics,
-        .matrix_coeffs = sps->vui.common.matrix_coeffs,
-        .chroma_sample_loc_type_top_field = sps->vui.common.chroma_sample_loc_type_top_field,
-        .chroma_sample_loc_type_bottom_field = sps->vui.common.chroma_sample_loc_type_bottom_field,
-        /* Reserved */
-        /* Reserved */
-        .def_disp_win_left_offset = sps->vui.def_disp_win.left_offset,
-        .def_disp_win_right_offset = sps->vui.def_disp_win.right_offset,
-        .def_disp_win_top_offset = sps->vui.def_disp_win.top_offset,
-        .def_disp_win_bottom_offset = sps->vui.def_disp_win.bottom_offset,
-        .vui_num_units_in_tick = sps->vui.vui_num_units_in_tick,
-        .vui_time_scale = sps->vui.vui_time_scale,
-        .vui_num_ticks_poc_diff_one_minus1 = sps->vui.vui_num_ticks_poc_diff_one_minus1,
-        .min_spatial_segmentation_idc = sps->vui.min_spatial_segmentation_idc,
-        .max_bytes_per_pic_denom = sps->vui.max_bytes_per_pic_denom,
-        .max_bits_per_min_cu_denom = sps->vui.max_bits_per_min_cu_denom,
-        .log2_max_mv_length_horizontal = sps->vui.log2_max_mv_length_horizontal,
-        .log2_max_mv_length_vertical = sps->vui.log2_max_mv_length_vertical,
-        .pHrdParameters = vksps_vui_header,
-    };
-
-    *ptl = (StdVideoH265ProfileTierLevel) {
-        .flags = (StdVideoH265ProfileTierLevelFlags) {
-            .general_tier_flag = sps->ptl.general_ptl.tier_flag,
-            .general_progressive_source_flag = sps->ptl.general_ptl.progressive_source_flag,
-            .general_interlaced_source_flag = sps->ptl.general_ptl.interlaced_source_flag,
-            .general_non_packed_constraint_flag = sps->ptl.general_ptl.non_packed_constraint_flag,
-            .general_frame_only_constraint_flag = sps->ptl.general_ptl.frame_only_constraint_flag,
-        },
-        .general_profile_idc = sps->ptl.general_ptl.profile_idc,
-        .general_level_idc = ff_vk_h265_level_to_vk(sps->ptl.general_ptl.level_idc),
-    };
-
-    for (int i = 0; i < sps->max_sub_layers; i++) {
-        dpbm->max_latency_increase_plus1[i] = sps->temporal_layer[i].max_latency_increase + 1;
-        dpbm->max_dec_pic_buffering_minus1[i] = sps->temporal_layer[i].max_dec_pic_buffering - 1;
-        dpbm->max_num_reorder_pics[i] = sps->temporal_layer[i].num_reorder_pics;
-    }
-
-    for (int i = 0; i < (sps->chroma_format_idc ? 3 : 1); i++)
-        for (int j = 0; j < sps->sps_num_palette_predictor_initializers; j++)
-            pal->PredictorPaletteEntries[i][j] = sps->sps_palette_predictor_initializer[i][j];
-
-    for (int i = 0; i < sps->nb_st_rps; i++) {
-        const ShortTermRPS *st_rps = &sps->st_rps[i];
-
-        str[i] = (StdVideoH265ShortTermRefPicSet) {
-            .flags = (StdVideoH265ShortTermRefPicSetFlags) {
-                .inter_ref_pic_set_prediction_flag = sps->st_rps[i].rps_predict,
-                .delta_rps_sign = sps->st_rps[i].delta_rps_sign,
-            },
-            .delta_idx_minus1 = sps->st_rps[i].delta_idx - 1,
-            .use_delta_flag = sps->st_rps[i].use_delta,
-            .abs_delta_rps_minus1 = sps->st_rps[i].abs_delta_rps - 1,
-            .used_by_curr_pic_flag    = 0x0,
-            .used_by_curr_pic_s0_flag = 0x0,
-            .used_by_curr_pic_s1_flag = 0x0,
-            /* Reserved */
-            /* Reserved */
-            /* Reserved */
-            .num_negative_pics = sps->st_rps[i].num_negative_pics,
-            .num_positive_pics = sps->st_rps[i].num_delta_pocs - sps->st_rps[i].num_negative_pics,
-        };
-
-        /* NOTE: This is the predicted, and *reordered* version.
-         * Probably incorrect, but the spec doesn't say which version to use. */
-        str[i].used_by_curr_pic_flag = st_rps->used;
-        str[i].used_by_curr_pic_s0_flag = av_zero_extend(st_rps->used, str[i].num_negative_pics);
-        str[i].used_by_curr_pic_s1_flag = st_rps->used >> str[i].num_negative_pics;
-
-        for (int j = 0; j < str[i].num_negative_pics; j++)
-            str[i].delta_poc_s0_minus1[j] = st_rps->delta_poc[j] - (j ? st_rps->delta_poc[j - 1] : 0) - 1;
-
-        for (int j = 0; j < str[i].num_positive_pics; j++)
-            str[i].delta_poc_s1_minus1[j] = st_rps->delta_poc[st_rps->num_negative_pics + j] -
-                                            (j ? st_rps->delta_poc[st_rps->num_negative_pics + j - 1] : 0) - 1;
-    }
-
-    *ltr = (StdVideoH265LongTermRefPicsSps) {
-        .used_by_curr_pic_lt_sps_flag = sps->used_by_curr_pic_lt,
-    };
-
-    for (int i = 0; i < sps->num_long_term_ref_pics_sps; i++) {
-        ltr->lt_ref_pic_poc_lsb_sps[i]     = sps->lt_ref_pic_poc_lsb_sps[i];
-    }
-
-    *vksps = (StdVideoH265SequenceParameterSet) {
-        .flags = (StdVideoH265SpsFlags) {
-            .sps_temporal_id_nesting_flag = sps->temporal_id_nesting,
-            .separate_colour_plane_flag = sps->separate_colour_plane,
-            .conformance_window_flag = sps->conformance_window,
-            .sps_sub_layer_ordering_info_present_flag = sps->sublayer_ordering_info,
-            .scaling_list_enabled_flag = sps->scaling_list_enabled,
-            .sps_scaling_list_data_present_flag = sps->scaling_list_enabled,
-            .amp_enabled_flag = sps->amp_enabled,
-            .sample_adaptive_offset_enabled_flag = sps->sao_enabled,
-            .pcm_enabled_flag = sps->pcm_enabled,
-            .pcm_loop_filter_disabled_flag = sps->pcm_loop_filter_disabled,
-            .long_term_ref_pics_present_flag = sps->long_term_ref_pics_present,
-            .sps_temporal_mvp_enabled_flag = sps->temporal_mvp_enabled,
-            .strong_intra_smoothing_enabled_flag = sps->strong_intra_smoothing_enabled,
-            .vui_parameters_present_flag = sps->vui_present,
-            .sps_extension_present_flag = sps->extension_present,
-            .sps_range_extension_flag = sps->range_extension,
-            .transform_skip_rotation_enabled_flag = sps->transform_skip_rotation_enabled,
-            .transform_skip_context_enabled_flag = sps->transform_skip_context_enabled,
-            .implicit_rdpcm_enabled_flag = sps->implicit_rdpcm_enabled,
-            .explicit_rdpcm_enabled_flag = sps->explicit_rdpcm_enabled,
-            .extended_precision_processing_flag = sps->extended_precision_processing,
-            .intra_smoothing_disabled_flag = sps->intra_smoothing_disabled,
-            .high_precision_offsets_enabled_flag = sps->high_precision_offsets_enabled,
-            .persistent_rice_adaptation_enabled_flag = sps->persistent_rice_adaptation_enabled,
-            .cabac_bypass_alignment_enabled_flag = sps->cabac_bypass_alignment_enabled,
-            .sps_scc_extension_flag = sps->scc_extension,
-            .sps_curr_pic_ref_enabled_flag = sps->curr_pic_ref_enabled,
-            .palette_mode_enabled_flag = sps->palette_mode_enabled,
-            .sps_palette_predictor_initializers_present_flag = sps->palette_predictor_initializers_present,
-            .intra_boundary_filtering_disabled_flag = sps->intra_boundary_filtering_disabled,
-        },
-        .chroma_format_idc = sps->chroma_format_idc,
-        .pic_width_in_luma_samples = sps->width,
-        .pic_height_in_luma_samples = sps->height,
-        .sps_video_parameter_set_id = sps->vps_id,
-        .sps_max_sub_layers_minus1 = sps->max_sub_layers - 1,
-        .sps_seq_parameter_set_id = sps_idx,
-        .bit_depth_luma_minus8 = sps->bit_depth - 8,
-        .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8,
-        .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4,
-        .log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3,
-        .log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size,
-        .log2_min_luma_transform_block_size_minus2 = sps->log2_min_tb_size - 2,
-        .log2_diff_max_min_luma_transform_block_size = sps->log2_diff_max_min_transform_block_size,
-        .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter,
-        .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra,
-        .num_short_term_ref_pic_sets = sps->nb_st_rps,
-        .num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps,
-        .pcm_sample_bit_depth_luma_minus1 = sps->pcm.bit_depth - 1,
-        .pcm_sample_bit_depth_chroma_minus1 = sps->pcm.bit_depth_chroma - 1,
-        .log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm.log2_min_pcm_cb_size - 3,
-        .log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size,
-        /* Reserved */
-        /* Reserved */
-        .palette_max_size = sps->palette_max_size,
-        .delta_palette_max_predictor_size = sps->delta_palette_max_predictor_size,
-        .motion_vector_resolution_control_idc = sps->motion_vector_resolution_control_idc,
-        .sps_num_palette_predictor_initializers_minus1 = sps->sps_num_palette_predictor_initializers - 1,
-        .conf_win_left_offset = sps->pic_conf_win.left_offset,
-        .conf_win_right_offset = sps->pic_conf_win.right_offset,
-        .conf_win_top_offset = sps->pic_conf_win.top_offset,
-        .conf_win_bottom_offset = sps->pic_conf_win.bottom_offset,
-        .pProfileTierLevel = ptl,
-        .pDecPicBufMgr = dpbm,
-        .pScalingLists = vksps_scaling,
-        .pShortTermRefPicSet = str,
-        .pLongTermRefPicsSps = ltr,
-        .pSequenceParameterSetVui = vksps_vui,
-        .pPredictorPaletteEntries = pal,
-    };
-}
-
-static void set_pps(const HEVCPPS *pps, const HEVCSPS *sps,
-                    StdVideoH265ScalingLists *vkpps_scaling,
-                    StdVideoH265PictureParameterSet *vkpps,
-                    StdVideoH265PredictorPaletteEntries *pal)
-{
-    copy_scaling_list(&pps->scaling_list, vkpps_scaling);
-
-    *vkpps = (StdVideoH265PictureParameterSet) {
-        .flags = (StdVideoH265PpsFlags) {
-            .dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag,
-            .output_flag_present_flag = pps->output_flag_present_flag,
-            .sign_data_hiding_enabled_flag = pps->sign_data_hiding_flag,
-            .cabac_init_present_flag = pps->cabac_init_present_flag,
-            .constrained_intra_pred_flag = pps->constrained_intra_pred_flag,
-            .transform_skip_enabled_flag = pps->transform_skip_enabled_flag,
-            .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag,
-            .pps_slice_chroma_qp_offsets_present_flag = pps->pic_slice_level_chroma_qp_offsets_present_flag,
-            .weighted_pred_flag = pps->weighted_pred_flag,
-            .weighted_bipred_flag = pps->weighted_bipred_flag,
-            .transquant_bypass_enabled_flag = pps->transquant_bypass_enable_flag,
-            .tiles_enabled_flag = pps->tiles_enabled_flag,
-            .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag,
-            .uniform_spacing_flag = pps->uniform_spacing_flag,
-            .loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag,
-            .pps_loop_filter_across_slices_enabled_flag = pps->seq_loop_filter_across_slices_enabled_flag,
-            .deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag,
-            .deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag,
-            .pps_deblocking_filter_disabled_flag = pps->disable_dbf,
-            .pps_scaling_list_data_present_flag = pps->scaling_list_data_present_flag,
-            .lists_modification_present_flag = pps->lists_modification_present_flag,
-            .slice_segment_header_extension_present_flag = pps->slice_header_extension_present_flag,
-            .pps_extension_present_flag = pps->pps_extension_present_flag,
-            .cross_component_prediction_enabled_flag = pps->cross_component_prediction_enabled_flag,
-            .chroma_qp_offset_list_enabled_flag = pps->chroma_qp_offset_list_enabled_flag,
-            .pps_curr_pic_ref_enabled_flag = pps->pps_curr_pic_ref_enabled_flag,
-            .residual_adaptive_colour_transform_enabled_flag = pps->residual_adaptive_colour_transform_enabled_flag,
-            .pps_slice_act_qp_offsets_present_flag = pps->pps_slice_act_qp_offsets_present_flag,
-            .pps_palette_predictor_initializers_present_flag = pps->pps_palette_predictor_initializers_present_flag,
-            .monochrome_palette_flag = pps->monochrome_palette_flag,
-            .pps_range_extension_flag = pps->pps_range_extensions_flag,
-        },
-        .pps_pic_parameter_set_id = pps->pps_id,
-        .pps_seq_parameter_set_id = pps->sps_id,
-        .sps_video_parameter_set_id = sps->vps_id,
-        .num_extra_slice_header_bits = pps->num_extra_slice_header_bits,
-        .num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active - 1,
-        .num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active - 1,
-        .init_qp_minus26 = pps->pic_init_qp_minus26,
-        .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth,
-        .pps_cb_qp_offset = pps->cb_qp_offset,
-        .pps_cr_qp_offset = pps->cr_qp_offset,
-        .pps_beta_offset_div2 = pps->beta_offset >> 1,
-        .pps_tc_offset_div2 = pps->tc_offset >> 1,
-        .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2,
-        .log2_max_transform_skip_block_size_minus2 = pps->log2_max_transform_skip_block_size - 2,
-        .diff_cu_chroma_qp_offset_depth = pps->diff_cu_chroma_qp_offset_depth,
-        .chroma_qp_offset_list_len_minus1 = pps->chroma_qp_offset_list_len_minus1,
-        .log2_sao_offset_scale_luma = pps->log2_sao_offset_scale_luma,
-        .log2_sao_offset_scale_chroma = pps->log2_sao_offset_scale_chroma,
-        .pps_act_y_qp_offset_plus5 = pps->pps_act_y_qp_offset + 5,
-        .pps_act_cb_qp_offset_plus5 = pps->pps_act_cb_qp_offset + 5,
-        .pps_act_cr_qp_offset_plus3 = pps->pps_act_cr_qp_offset + 3,
-        .pps_num_palette_predictor_initializers = pps->pps_num_palette_predictor_initializers,
-        .luma_bit_depth_entry_minus8 = pps->luma_bit_depth_entry - 8,
-        .chroma_bit_depth_entry_minus8 = pps->chroma_bit_depth_entry - 8,
-        .num_tile_columns_minus1 = pps->num_tile_columns - 1,
-        .num_tile_rows_minus1 = pps->num_tile_rows - 1,
-        .pScalingLists = vkpps_scaling,
-        .pPredictorPaletteEntries = pal,
-    };
-
-    for (int i = 0; i < (pps->monochrome_palette_flag ? 1 : 3); i++) {
-        for (int j = 0; j < pps->pps_num_palette_predictor_initializers; j++)
-            pal->PredictorPaletteEntries[i][j] = pps->pps_palette_predictor_initializer[i][j];
-    }
-
-    for (int i = 0; i < pps->num_tile_columns - 1; i++)
-        vkpps->column_width_minus1[i] = pps->column_width[i] - 1;
-
-    for (int i = 0; i < pps->num_tile_rows - 1; i++)
-        vkpps->row_height_minus1[i] = pps->row_height[i] - 1;
-
-    for (int i = 0; i <= pps->chroma_qp_offset_list_len_minus1; i++) {
-        vkpps->cb_qp_offset_list[i] = pps->cb_qp_offset_list[i];
-        vkpps->cr_qp_offset_list[i] = pps->cr_qp_offset_list[i];
-    }
-}
-
-static void set_vps(const HEVCVPS *vps,
-                    StdVideoH265VideoParameterSet *vkvps,
-                    StdVideoH265ProfileTierLevel *ptl,
-                    StdVideoH265DecPicBufMgr *dpbm,
-                    StdVideoH265HrdParameters *sls_hdr,
-                    HEVCHeaderVPSSet sls[])
-{
-    for (int i = 0; i < vps->vps_num_hrd_parameters; i++) {
-        const HEVCHdrParams *src = &vps->hdr[i];
-
-        sls_hdr[i] = (StdVideoH265HrdParameters) {
-            .flags = (StdVideoH265HrdFlags) {
-                .nal_hrd_parameters_present_flag = src->nal_hrd_parameters_present_flag,
-                .vcl_hrd_parameters_present_flag = src->vcl_hrd_parameters_present_flag,
-                .sub_pic_hrd_params_present_flag = src->sub_pic_hrd_params_present_flag,
-                .sub_pic_cpb_params_in_pic_timing_sei_flag = src->sub_pic_cpb_params_in_pic_timing_sei_flag,
-                .fixed_pic_rate_general_flag = src->flags.fixed_pic_rate_general_flag,
-                .fixed_pic_rate_within_cvs_flag = src->flags.fixed_pic_rate_within_cvs_flag,
-                .low_delay_hrd_flag = src->flags.low_delay_hrd_flag,
-            },
-            .tick_divisor_minus2 = src->tick_divisor_minus2,
-            .du_cpb_removal_delay_increment_length_minus1 = src->du_cpb_removal_delay_increment_length_minus1,
-            .dpb_output_delay_du_length_minus1 = src->dpb_output_delay_du_length_minus1,
-            .bit_rate_scale = src->bit_rate_scale,
-            .cpb_size_scale = src->cpb_size_scale,
-            .cpb_size_du_scale = src->cpb_size_du_scale,
-            .initial_cpb_removal_delay_length_minus1 = src->initial_cpb_removal_delay_length_minus1,
-            .au_cpb_removal_delay_length_minus1 = src->au_cpb_removal_delay_length_minus1,
-            .dpb_output_delay_length_minus1 = src->dpb_output_delay_length_minus1,
-            /* Reserved - 3*16 bits */
-            .pSubLayerHrdParametersNal = sls[i].nal_hdr,
-            .pSubLayerHrdParametersVcl = sls[i].vcl_hdr,
-        };
-
-        memcpy(sls_hdr[i].cpb_cnt_minus1, src->cpb_cnt_minus1,
-               STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*sls_hdr[i].cpb_cnt_minus1));
-        memcpy(sls_hdr[i].elemental_duration_in_tc_minus1, src->elemental_duration_in_tc_minus1,
-               STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*sls_hdr[i].elemental_duration_in_tc_minus1));
-
-        memcpy(sls[i].nal_hdr, src->nal_params, HEVC_MAX_SUB_LAYERS*sizeof(*sls[i].nal_hdr));
-        memcpy(sls[i].vcl_hdr, src->vcl_params, HEVC_MAX_SUB_LAYERS*sizeof(*sls[i].vcl_hdr));
-    }
-
-    *ptl = (StdVideoH265ProfileTierLevel) {
-        .flags = (StdVideoH265ProfileTierLevelFlags) {
-            .general_tier_flag = vps->ptl.general_ptl.tier_flag,
-            .general_progressive_source_flag = vps->ptl.general_ptl.progressive_source_flag,
-            .general_interlaced_source_flag = vps->ptl.general_ptl.interlaced_source_flag,
-            .general_non_packed_constraint_flag = vps->ptl.general_ptl.non_packed_constraint_flag,
-            .general_frame_only_constraint_flag = vps->ptl.general_ptl.frame_only_constraint_flag,
-        },
-        .general_profile_idc = ff_vk_h265_profile_to_vk(vps->ptl.general_ptl.profile_idc),
-        .general_level_idc = ff_vk_h265_level_to_vk(vps->ptl.general_ptl.level_idc),
-    };
-
-    for (int i = 0; i < vps->vps_max_sub_layers; i++) {
-        dpbm->max_latency_increase_plus1[i] = vps->vps_max_latency_increase[i] + 1;
-        dpbm->max_dec_pic_buffering_minus1[i] = vps->vps_max_dec_pic_buffering[i] - 1;
-        dpbm->max_num_reorder_pics[i] = vps->vps_num_reorder_pics[i];
-    }
-
-    *vkvps = (StdVideoH265VideoParameterSet) {
-        .flags = (StdVideoH265VpsFlags) {
-            .vps_temporal_id_nesting_flag = vps->vps_temporal_id_nesting_flag,
-            .vps_sub_layer_ordering_info_present_flag = vps->vps_sub_layer_ordering_info_present_flag,
-            .vps_timing_info_present_flag = vps->vps_timing_info_present_flag,
-            .vps_poc_proportional_to_timing_flag = vps->vps_poc_proportional_to_timing_flag,
-        },
-        .vps_video_parameter_set_id = vps->vps_id,
-        .vps_max_sub_layers_minus1 = vps->vps_max_sub_layers - 1,
-        /* Reserved */
-        /* Reserved */
-        .vps_num_units_in_tick = vps->vps_num_units_in_tick,
-        .vps_time_scale = vps->vps_time_scale,
-        .vps_num_ticks_poc_diff_one_minus1 = vps->vps_num_ticks_poc_diff_one - 1,
-        /* Reserved */
-        .pDecPicBufMgr = dpbm,
-        .pHrdParameters = sls_hdr,
-        .pProfileTierLevel = ptl,
-    };
-}
-
-static int vk_hevc_create_params(AVCodecContext *avctx, AVBufferRef **buf)
-{
-    int err;
-    const HEVCContext *h = avctx->priv_data;
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-
-    VkVideoDecodeH265SessionParametersAddInfoKHR h265_params_info = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR,
-        .stdSPSCount = 0,
-        .stdPPSCount = 0,
-        .stdVPSCount = 0,
-    };
-    VkVideoDecodeH265SessionParametersCreateInfoKHR h265_params = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR,
-        .pParametersAddInfo = &h265_params_info,
-    };
-    VkVideoSessionParametersCreateInfoKHR session_params_create = {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
-        .pNext = &h265_params,
-        .videoSession = ctx->common.session,
-        .videoSessionParametersTemplate = VK_NULL_HANDLE,
-    };
-
-    HEVCHeaderSet *hdr;
-    int nb_vps = 0;
-    int vps_list_idx[HEVC_MAX_VPS_COUNT];
-
-    for (int i = 0; i < HEVC_MAX_VPS_COUNT; i++)
-        if (h->ps.vps_list[i])
-            vps_list_idx[nb_vps++] = i;
-
-    err = alloc_hevc_header_structs(dec, nb_vps, vps_list_idx, h->ps.vps_list);
-    if (err < 0)
-        return err;
-
-    hdr = dec->hevc_headers;
-
-    h265_params_info.pStdSPSs = hdr->sps;
-    h265_params_info.pStdPPSs = hdr->pps;
-    h265_params_info.pStdVPSs = hdr->vps;
-
-    /* SPS list */
-    for (int i = 0; i < HEVC_MAX_SPS_COUNT; i++) {
-        if (h->ps.sps_list[i]) {
-            const HEVCSPS *sps_l = h->ps.sps_list[i];
-            int idx = h265_params_info.stdSPSCount++;
-            set_sps(sps_l, i, &hdr->hsps[idx].scaling, &hdr->hsps[idx].vui_header,
-                    &hdr->hsps[idx].vui, &hdr->sps[idx], hdr->hsps[idx].nal_hdr,
-                    hdr->hsps[idx].vcl_hdr, &hdr->hsps[idx].ptl, &hdr->hsps[idx].dpbm,
-                    &hdr->hsps[idx].pal, hdr->hsps[idx].str, &hdr->hsps[idx].ltr);
-        }
-    }
-
-    /* PPS list */
-    for (int i = 0; i < HEVC_MAX_PPS_COUNT; i++) {
-        if (h->ps.pps_list[i]) {
-            const HEVCPPS *pps_l = h->ps.pps_list[i];
-            const HEVCSPS *sps_l = h->ps.sps_list[pps_l->sps_id];
-            int idx = h265_params_info.stdPPSCount++;
-            set_pps(pps_l, sps_l, &hdr->hpps[idx].scaling,
-                    &hdr->pps[idx], &hdr->hpps[idx].pal);
-        }
-    }
-
-    /* VPS list */
-    for (int i = 0; i < nb_vps; i++) {
-        const HEVCVPS *vps_l = h->ps.vps_list[vps_list_idx[i]];
-        set_vps(vps_l, &hdr->vps[i], &hdr->hvps[i].ptl, &hdr->hvps[i].dpbm,
-                hdr->hvps[i].hdr, hdr->hvps[i].sls);
-        h265_params_info.stdVPSCount++;
-    }
-
-    h265_params.maxStdSPSCount = h265_params_info.stdSPSCount;
-    h265_params.maxStdPPSCount = h265_params_info.stdPPSCount;
-    h265_params.maxStdVPSCount = h265_params_info.stdVPSCount;
-
-    err = ff_vk_decode_create_params(buf, avctx, ctx, &session_params_create);
-    if (err < 0)
-        return err;
-
-    av_log(avctx, AV_LOG_DEBUG, "Created frame parameters: %i SPS %i PPS %i VPS\n",
-           h265_params_info.stdSPSCount, h265_params_info.stdPPSCount,
-           h265_params_info.stdVPSCount);
-
-    return 0;
-}
-
-static int vk_hevc_start_frame(AVCodecContext          *avctx,
-                               av_unused const AVBufferRef *buffer_ref,
-                               av_unused const uint8_t *buffer,
-                               av_unused uint32_t       size)
-{
-    int err;
-    HEVCContext *h = avctx->priv_data;
-    HEVCLayerContext *l = &h->layers[h->cur_layer];
-
-    HEVCFrame *pic = h->cur_frame;
-    HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &hp->vp;
-    const HEVCPPS *pps = h->pps;
-    const HEVCSPS *sps = pps->sps;
-    int nb_refs = 0;
-
-    hp->h265pic = (StdVideoDecodeH265PictureInfo) {
-        .flags = (StdVideoDecodeH265PictureInfoFlags) {
-            .IrapPicFlag = IS_IRAP(h),
-            .IdrPicFlag = IS_IDR(h),
-            .IsReference = h->nal_unit_type < 16 ? h->nal_unit_type & 1 : 1,
-            .short_term_ref_pic_set_sps_flag = h->sh.short_term_ref_pic_set_sps_flag,
-        },
-        .sps_video_parameter_set_id = sps->vps_id,
-        .pps_seq_parameter_set_id = pps->sps_id,
-        .pps_pic_parameter_set_id = pps->pps_id,
-        .NumDeltaPocsOfRefRpsIdx = h->sh.short_term_rps ? h->sh.short_term_rps->rps_idx_num_delta_pocs : 0,
-        .PicOrderCntVal = h->poc,
-        .NumBitsForSTRefPicSetInSlice = !h->sh.short_term_ref_pic_set_sps_flag ?
-                                         h->sh.short_term_ref_pic_set_size : 0,
-    };
-
-    /* Fill in references */
-    for (int i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) {
-        const HEVCFrame *ref = &l->DPB[i];
-        int idx = nb_refs;
-
-        if (!(ref->flags & (HEVC_FRAME_FLAG_SHORT_REF | HEVC_FRAME_FLAG_LONG_REF)))
-            continue;
-
-        if (ref == pic) {
-            err = vk_hevc_fill_pict(avctx, NULL, &vp->ref_slot, &vp->ref,
-                                    &hp->vkh265_ref, &hp->h265_ref, pic, 1, i);
-            if (err < 0)
-                return err;
-
-            continue;
-        }
-
-        err = vk_hevc_fill_pict(avctx, &hp->ref_src[idx], &vp->ref_slots[idx],
-                                &vp->refs[idx], &hp->vkh265_refs[idx],
-                                &hp->h265_refs[idx], (HEVCFrame *)ref, 0, i);
-        if (err < 0)
-            return err;
-
-        nb_refs++;
-    }
-
-    memset(hp->h265pic.RefPicSetStCurrBefore, 0xff, 8);
-    for (int i = 0; i < h->rps[ST_CURR_BEF].nb_refs; i++) {
-        HEVCFrame *frame = h->rps[ST_CURR_BEF].ref[i];
-        for (int j = 0; j < FF_ARRAY_ELEMS(l->DPB); j++) {
-            const HEVCFrame *ref = &l->DPB[j];
-            if (ref == frame) {
-                hp->h265pic.RefPicSetStCurrBefore[i] = j;
-                break;
-            }
-        }
-    }
-    memset(hp->h265pic.RefPicSetStCurrAfter, 0xff, 8);
-    for (int i = 0; i < h->rps[ST_CURR_AFT].nb_refs; i++) {
-        HEVCFrame *frame = h->rps[ST_CURR_AFT].ref[i];
-        for (int j = 0; j < FF_ARRAY_ELEMS(l->DPB); j++) {
-            const HEVCFrame *ref = &l->DPB[j];
-            if (ref == frame) {
-                hp->h265pic.RefPicSetStCurrAfter[i] = j;
-                break;
-            }
-        }
-    }
-    memset(hp->h265pic.RefPicSetLtCurr, 0xff, 8);
-    for (int i = 0; i < h->rps[LT_CURR].nb_refs; i++) {
-        HEVCFrame *frame = h->rps[LT_CURR].ref[i];
-        for (int j = 0; j < FF_ARRAY_ELEMS(l->DPB); j++) {
-            const HEVCFrame *ref = &l->DPB[j];
-            if (ref == frame) {
-                hp->h265pic.RefPicSetLtCurr[i] = j;
-                break;
-            }
-        }
-    }
-
-    hp->h265_pic_info = (VkVideoDecodeH265PictureInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_KHR,
-        .pStdPictureInfo = &hp->h265pic,
-        .sliceSegmentCount = 0,
-    };
-
-    vp->decode_info = (VkVideoDecodeInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR,
-        .pNext = &hp->h265_pic_info,
-        .flags = 0x0,
-        .pSetupReferenceSlot = &vp->ref_slot,
-        .referenceSlotCount = nb_refs,
-        .pReferenceSlots = vp->ref_slots,
-        .dstPictureResource = (VkVideoPictureResourceInfoKHR) {
-            .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
-            .codedOffset = (VkOffset2D){ 0, 0 },
-            .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
-            .baseArrayLayer = 0,
-            .imageViewBinding = vp->view.out[0],
-        },
-    };
-
-    return 0;
-}
-
-static int vk_hevc_decode_slice(AVCodecContext *avctx,
-                                const uint8_t  *data,
-                                uint32_t        size)
-{
-    const HEVCContext *h = avctx->priv_data;
-    HEVCVulkanDecodePicture *hp = h->cur_frame->hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &hp->vp;
-
-    int err = ff_vk_decode_add_slice(avctx, vp, data, size, 1,
-                                     &hp->h265_pic_info.sliceSegmentCount,
-                                     &hp->h265_pic_info.pSliceSegmentOffsets);
-    if (err < 0)
-        return err;
-
-    return 0;
-}
-
-static int vk_hevc_end_frame(AVCodecContext *avctx)
-{
-    const HEVCContext *h = avctx->priv_data;
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-
-    HEVCFrame *pic = h->cur_frame;
-    HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &hp->vp;
-    FFVulkanDecodePicture *rvp[HEVC_MAX_REFS] = { 0 };
-    AVFrame *rav[HEVC_MAX_REFS] = { 0 };
-    int err;
-
-    const HEVCPPS *pps = h->pps;
-    const HEVCSPS *sps = pps->sps;
-
-#ifdef VK_KHR_video_maintenance2
-    HEVCHeaderPPS vkpps_p;
-    StdVideoH265PictureParameterSet vkpps;
-    HEVCHeaderSPS vksps_p;
-    StdVideoH265SequenceParameterSet vksps;
-    HEVCHeaderVPSSet vkvps_ps[HEVC_MAX_SUB_LAYERS];
-    HEVCHeaderVPS vkvps_p;
-    StdVideoH265VideoParameterSet vkvps;
-    VkVideoDecodeH265InlineSessionParametersInfoKHR h265_params;
-
-    if (ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2) {
-        set_pps(pps, sps, &vkpps_p.scaling, &vkpps, &vkpps_p.pal);
-        set_sps(sps, pps->sps_id, &vksps_p.scaling, &vksps_p.vui_header,
-                &vksps_p.vui, &vksps, vksps_p.nal_hdr,
-                vksps_p.vcl_hdr, &vksps_p.ptl, &vksps_p.dpbm,
-                &vksps_p.pal, vksps_p.str, &vksps_p.ltr);
-
-        vkvps_p.sls = vkvps_ps;
-        set_vps(sps->vps, &vkvps, &vkvps_p.ptl, &vkvps_p.dpbm,
-                vkvps_p.hdr, vkvps_p.sls);
-
-        h265_params = (VkVideoDecodeH265InlineSessionParametersInfoKHR) {
-            .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_INLINE_SESSION_PARAMETERS_INFO_KHR,
-            .pStdSPS = &vksps,
-            .pStdPPS = &vkpps,
-            .pStdVPS = &vkvps,
-        };
-        hp->h265_pic_info.pNext = &h265_params;
-    }
-#endif
-
-    if (!hp->h265_pic_info.sliceSegmentCount)
-        return 0;
-
-    if (!dec->session_params &&
-        !(ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)) {
-        if (!pps) {
-            unsigned int pps_id = h->sh.pps_id;
-            if (pps_id < HEVC_MAX_PPS_COUNT && h->ps.pps_list[pps_id] != NULL)
-                pps = h->ps.pps_list[pps_id];
-        }
-
-        if (!pps) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "Encountered frame without a valid active PPS reference.\n");
-            return AVERROR_INVALIDDATA;
-        }
-
-        err = vk_hevc_create_params(avctx, &dec->session_params);
-        if (err < 0)
-            return err;
-
-        hp->h265pic.sps_video_parameter_set_id = sps->vps_id;
-        hp->h265pic.pps_seq_parameter_set_id = pps->sps_id;
-        hp->h265pic.pps_pic_parameter_set_id = pps->pps_id;
-    }
-
-    for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
-        HEVCVulkanDecodePicture *rfhp = hp->ref_src[i]->hwaccel_picture_private;
-        rav[i] = hp->ref_src[i]->f;
-        rvp[i] = &rfhp->vp;
-    }
-
-    av_log(avctx, AV_LOG_DEBUG, "Decoding frame, %"SIZE_SPECIFIER" bytes, %i slices\n",
-           vp->slices_size, hp->h265_pic_info.sliceSegmentCount);
-
-    return ff_vk_decode_frame(avctx, pic->f, vp, rav, rvp);
-}
-
-static void vk_hevc_free_frame_priv(AVRefStructOpaque _hwctx, void *data)
-{
-    AVHWDeviceContext *hwctx = _hwctx.nc;
-    HEVCVulkanDecodePicture *hp = data;
-
-    /* Free frame resources */
-    ff_vk_decode_free_frame(hwctx, &hp->vp);
-}
-
-const FFHWAccel ff_hevc_vulkan_hwaccel = {
-    .p.name                = "hevc_vulkan",
-    .p.type                = AVMEDIA_TYPE_VIDEO,
-    .p.id                  = AV_CODEC_ID_HEVC,
-    .p.pix_fmt             = AV_PIX_FMT_VULKAN,
-    .start_frame           = &vk_hevc_start_frame,
-    .decode_slice          = &vk_hevc_decode_slice,
-    .end_frame             = &vk_hevc_end_frame,
-    .free_frame_priv       = &vk_hevc_free_frame_priv,
-    .frame_priv_data_size  = sizeof(HEVCVulkanDecodePicture),
-    .init                  = &ff_vk_decode_init,
-    .update_thread_context = &ff_vk_update_thread_context,
-    .decode_params         = &ff_vk_params_invalidate,
-    .flush                 = &ff_vk_decode_flush,
-    .uninit                = &ff_vk_decode_uninit,
-    .frame_params          = &ff_vk_frame_params,
-    .priv_data_size        = sizeof(FFVulkanDecodeContext),
-    .caps_internal         = HWACCEL_CAP_ASYNC_SAFE,
-};
-- 
2.49.1


From 8198504517fa809ad6662b23bd82ac7b38b7d509 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:38:53 +0000
Subject: [PATCH 084/118] Changing vulkan file directory

---
 libavcodec/vulkan/vulkan_hevc.c | 957 ++++++++++++++++++++++++++++++++
 1 file changed, 957 insertions(+)
 create mode 100644 libavcodec/vulkan/vulkan_hevc.c

diff --git a/libavcodec/vulkan/vulkan_hevc.c b/libavcodec/vulkan/vulkan_hevc.c
new file mode 100644
index 0000000000..15f7e7c950
--- /dev/null
+++ b/libavcodec/vulkan/vulkan_hevc.c
@@ -0,0 +1,957 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/mem.h"
+#include "libavcodec/hevcdec.h"
+#include "libavcodec/hevc_data.h"
+#include "libavcodec/hevc_ps.h"
+
+#include "vulkan_decode.h"
+
+const FFVulkanDecodeDescriptor ff_vk_dec_hevc_desc = {
+    .codec_id         = AV_CODEC_ID_HEVC,
+    .decode_extension = FF_VK_EXT_VIDEO_DECODE_H265,
+    .queue_flags      = VK_QUEUE_VIDEO_DECODE_BIT_KHR,
+    .decode_op        = VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR,
+    .ext_props = {
+        .extensionName = VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME,
+        .specVersion   = VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION,
+    },
+};
+
+typedef struct HEVCHeaderSPS {
+    StdVideoH265ScalingLists scaling;
+    StdVideoH265HrdParameters vui_header;
+    StdVideoH265SequenceParameterSetVui vui;
+    StdVideoH265ProfileTierLevel ptl;
+    StdVideoH265DecPicBufMgr dpbm;
+    StdVideoH265PredictorPaletteEntries pal;
+    StdVideoH265SubLayerHrdParameters nal_hdr[HEVC_MAX_SUB_LAYERS];
+    StdVideoH265SubLayerHrdParameters vcl_hdr[HEVC_MAX_SUB_LAYERS];
+    StdVideoH265ShortTermRefPicSet str[HEVC_MAX_SHORT_TERM_REF_PIC_SETS];
+    StdVideoH265LongTermRefPicsSps ltr;
+} HEVCHeaderSPS;
+
+typedef struct HEVCHeaderPPS {
+    StdVideoH265ScalingLists scaling;
+    StdVideoH265PredictorPaletteEntries pal;
+} HEVCHeaderPPS;
+
+typedef struct HEVCHeaderVPSSet {
+    StdVideoH265SubLayerHrdParameters nal_hdr[HEVC_MAX_SUB_LAYERS];
+    StdVideoH265SubLayerHrdParameters vcl_hdr[HEVC_MAX_SUB_LAYERS];
+} HEVCHeaderVPSSet;
+
+typedef struct HEVCHeaderVPS {
+    StdVideoH265ProfileTierLevel ptl;
+    StdVideoH265DecPicBufMgr dpbm;
+    StdVideoH265HrdParameters hdr[HEVC_MAX_LAYER_SETS];
+    HEVCHeaderVPSSet *sls;
+} HEVCHeaderVPS;
+
+typedef struct HEVCHeaderSet {
+    StdVideoH265SequenceParameterSet sps[HEVC_MAX_SPS_COUNT];
+    HEVCHeaderSPS hsps[HEVC_MAX_SPS_COUNT];
+
+    StdVideoH265PictureParameterSet pps[HEVC_MAX_PPS_COUNT];
+    HEVCHeaderPPS hpps[HEVC_MAX_PPS_COUNT];
+
+    StdVideoH265VideoParameterSet vps[HEVC_MAX_PPS_COUNT];
+    HEVCHeaderVPS *hvps;
+} HEVCHeaderSet;
+
+static int alloc_hevc_header_structs(FFVulkanDecodeContext *s,
+                                     int nb_vps,
+                                     const int vps_list_idx[HEVC_MAX_VPS_COUNT],
+                                     const HEVCVPS * const vps_list[HEVC_MAX_VPS_COUNT])
+{
+    uint8_t *data_ptr;
+    HEVCHeaderSet *hdr;
+
+    size_t buf_size = sizeof(HEVCHeaderSet) + nb_vps*sizeof(HEVCHeaderVPS);
+    for (int i = 0; i < nb_vps; i++) {
+        const HEVCVPS *vps = vps_list[vps_list_idx[i]];
+        buf_size += sizeof(HEVCHeaderVPSSet)*vps->vps_num_hrd_parameters;
+    }
+
+    if (buf_size > s->hevc_headers_size) {
+        av_freep(&s->hevc_headers);
+        s->hevc_headers_size = 0;
+        s->hevc_headers = av_mallocz(buf_size);
+        if (!s->hevc_headers)
+            return AVERROR(ENOMEM);
+        s->hevc_headers_size = buf_size;
+    }
+
+    /* Setup struct pointers */
+    hdr = s->hevc_headers;
+    data_ptr = (uint8_t *)hdr;
+    hdr->hvps = (HEVCHeaderVPS *)(data_ptr + sizeof(HEVCHeaderSet));
+    data_ptr += sizeof(HEVCHeaderSet) + nb_vps*sizeof(HEVCHeaderVPS);
+    for (int i = 0; i < nb_vps; i++) {
+        const HEVCVPS *vps = vps_list[vps_list_idx[i]];
+        hdr->hvps[i].sls = (HEVCHeaderVPSSet *)data_ptr;
+        data_ptr += sizeof(HEVCHeaderVPSSet)*vps->vps_num_hrd_parameters;
+    }
+
+    return 0;
+}
+
+typedef struct HEVCVulkanDecodePicture {
+    FFVulkanDecodePicture           vp;
+
+    /* Current picture */
+    StdVideoDecodeH265ReferenceInfo h265_ref;
+    VkVideoDecodeH265DpbSlotInfoKHR vkh265_ref;
+
+    /* Picture refs */
+    HEVCFrame                      *ref_src    [HEVC_MAX_REFS];
+    StdVideoDecodeH265ReferenceInfo h265_refs  [HEVC_MAX_REFS];
+    VkVideoDecodeH265DpbSlotInfoKHR vkh265_refs[HEVC_MAX_REFS];
+
+    /* Current picture (contd.) */
+    StdVideoDecodeH265PictureInfo   h265pic;
+    VkVideoDecodeH265PictureInfoKHR h265_pic_info;
+} HEVCVulkanDecodePicture;
+
+static int vk_hevc_fill_pict(AVCodecContext *avctx, HEVCFrame **ref_src,
+                             VkVideoReferenceSlotInfoKHR *ref_slot,       /* Main structure */
+                             VkVideoPictureResourceInfoKHR *ref,          /* Goes in ^ */
+                             VkVideoDecodeH265DpbSlotInfoKHR *vkh265_ref, /* Goes in ^ */
+                             StdVideoDecodeH265ReferenceInfo *h265_ref,   /* Goes in ^ */
+                             HEVCFrame *pic, int is_current, int pic_id)
+{
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+    HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private;
+    FFVulkanDecodePicture *vkpic = &hp->vp;
+
+    int err = ff_vk_decode_prepare_frame(dec, pic->f, vkpic, is_current,
+                                         dec->dedicated_dpb);
+    if (err < 0)
+        return err;
+
+    *h265_ref = (StdVideoDecodeH265ReferenceInfo) {
+        .flags = (StdVideoDecodeH265ReferenceInfoFlags) {
+            .used_for_long_term_reference = pic->flags & HEVC_FRAME_FLAG_LONG_REF,
+            .unused_for_reference = 0,
+        },
+        .PicOrderCntVal = pic->poc,
+    };
+
+    *vkh265_ref = (VkVideoDecodeH265DpbSlotInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_KHR,
+        .pStdReferenceInfo = h265_ref,
+    };
+
+    *ref = (VkVideoPictureResourceInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
+        .codedOffset = (VkOffset2D){ 0, 0 },
+        .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
+        .baseArrayLayer = ctx->common.layered_dpb ? pic_id : 0,
+        .imageViewBinding = vkpic->view.ref[0],
+    };
+
+    *ref_slot = (VkVideoReferenceSlotInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
+        .pNext = vkh265_ref,
+        .slotIndex = pic_id,
+        .pPictureResource = ref,
+    };
+
+    if (ref_src)
+        *ref_src = pic;
+
+    return 0;
+}
+
+static void copy_scaling_list(const ScalingList *sl, StdVideoH265ScalingLists *vksl)
+{
+    for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS; i++) {
+        for (int j = 0; j < STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS; j++) {
+            uint8_t pos = 4 * ff_hevc_diag_scan4x4_y[j] + ff_hevc_diag_scan4x4_x[j];
+            vksl->ScalingList4x4[i][j] = sl->sl[0][i][pos];
+        }
+    }
+
+    for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS; i++) {
+        for (int j = 0; j < STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS; j++) {
+            uint8_t pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j];
+            vksl->ScalingList8x8[i][j] = sl->sl[1][i][pos];
+        }
+    }
+
+    for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS; i++) {
+        for (int j = 0; j < STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS; j++) {
+            uint8_t pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j];
+            vksl->ScalingList16x16[i][j] = sl->sl[2][i][pos];
+        }
+    }
+
+    for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++) {
+        for (int j = 0; j < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS; j++) {
+            uint8_t pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j];
+            vksl->ScalingList32x32[i][j] = sl->sl[3][i * 3][pos];
+        }
+    }
+
+    memcpy(vksl->ScalingListDCCoef16x16, sl->sl_dc[0],
+           STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS * sizeof(*vksl->ScalingListDCCoef16x16));
+
+    for (int i = 0; i <  STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++)
+        vksl->ScalingListDCCoef32x32[i] = sl->sl_dc[1][i * 3];
+}
+
+static void set_sps(const HEVCSPS *sps, int sps_idx,
+                    StdVideoH265ScalingLists *vksps_scaling,
+                    StdVideoH265HrdParameters *vksps_vui_header,
+                    StdVideoH265SequenceParameterSetVui *vksps_vui,
+                    StdVideoH265SequenceParameterSet *vksps,
+                    StdVideoH265SubLayerHrdParameters *slhdrnal,
+                    StdVideoH265SubLayerHrdParameters *slhdrvcl,
+                    StdVideoH265ProfileTierLevel *ptl,
+                    StdVideoH265DecPicBufMgr *dpbm,
+                    StdVideoH265PredictorPaletteEntries *pal,
+                    StdVideoH265ShortTermRefPicSet *str,
+                    StdVideoH265LongTermRefPicsSps *ltr)
+{
+    copy_scaling_list(&sps->scaling_list, vksps_scaling);
+
+    *vksps_vui_header = (StdVideoH265HrdParameters) {
+        .flags = (StdVideoH265HrdFlags) {
+            .nal_hrd_parameters_present_flag = sps->hdr.nal_hrd_parameters_present_flag,
+            .vcl_hrd_parameters_present_flag = sps->hdr.vcl_hrd_parameters_present_flag,
+            .sub_pic_hrd_params_present_flag = sps->hdr.sub_pic_hrd_params_present_flag,
+            .sub_pic_cpb_params_in_pic_timing_sei_flag = sps->hdr.sub_pic_cpb_params_in_pic_timing_sei_flag,
+            .fixed_pic_rate_general_flag = sps->hdr.flags.fixed_pic_rate_general_flag,
+            .fixed_pic_rate_within_cvs_flag = sps->hdr.flags.fixed_pic_rate_within_cvs_flag,
+            .low_delay_hrd_flag = sps->hdr.flags.low_delay_hrd_flag,
+        },
+        .tick_divisor_minus2 = sps->hdr.tick_divisor_minus2,
+        .du_cpb_removal_delay_increment_length_minus1 = sps->hdr.du_cpb_removal_delay_increment_length_minus1,
+        .dpb_output_delay_du_length_minus1 = sps->hdr.dpb_output_delay_du_length_minus1,
+        .bit_rate_scale = sps->hdr.bit_rate_scale,
+        .cpb_size_scale = sps->hdr.cpb_size_scale,
+        .cpb_size_du_scale = sps->hdr.cpb_size_du_scale,
+        .initial_cpb_removal_delay_length_minus1 = sps->hdr.initial_cpb_removal_delay_length_minus1,
+        .au_cpb_removal_delay_length_minus1 = sps->hdr.au_cpb_removal_delay_length_minus1,
+        .dpb_output_delay_length_minus1 = sps->hdr.dpb_output_delay_length_minus1,
+        /* Reserved - 3*16 bits */
+        .pSubLayerHrdParametersNal = slhdrnal,
+        .pSubLayerHrdParametersVcl = slhdrvcl,
+    };
+
+    memcpy(vksps_vui_header->cpb_cnt_minus1, sps->hdr.cpb_cnt_minus1,
+           STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*vksps_vui_header->cpb_cnt_minus1));
+    memcpy(vksps_vui_header->elemental_duration_in_tc_minus1, sps->hdr.elemental_duration_in_tc_minus1,
+           STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*vksps_vui_header->elemental_duration_in_tc_minus1));
+
+    memcpy(slhdrnal, sps->hdr.nal_params, HEVC_MAX_SUB_LAYERS*sizeof(*slhdrnal));
+    memcpy(slhdrvcl, sps->hdr.vcl_params, HEVC_MAX_SUB_LAYERS*sizeof(*slhdrvcl));
+
+    *vksps_vui = (StdVideoH265SequenceParameterSetVui) {
+        .flags = (StdVideoH265SpsVuiFlags) {
+            .aspect_ratio_info_present_flag = sps->vui.common.aspect_ratio_info_present_flag,
+            .overscan_info_present_flag = sps->vui.common.overscan_info_present_flag,
+            .overscan_appropriate_flag = sps->vui.common.overscan_appropriate_flag,
+            .video_signal_type_present_flag = sps->vui.common.video_signal_type_present_flag,
+            .video_full_range_flag = sps->vui.common.video_full_range_flag,
+            .colour_description_present_flag = sps->vui.common.colour_description_present_flag,
+            .chroma_loc_info_present_flag = sps->vui.common.chroma_loc_info_present_flag,
+            .neutral_chroma_indication_flag = sps->vui.neutra_chroma_indication_flag,
+            .field_seq_flag = sps->vui.field_seq_flag,
+            .frame_field_info_present_flag = sps->vui.frame_field_info_present_flag,
+            .default_display_window_flag = sps->vui.default_display_window_flag,
+            .vui_timing_info_present_flag = sps->vui.vui_timing_info_present_flag,
+            .vui_poc_proportional_to_timing_flag = sps->vui.vui_poc_proportional_to_timing_flag,
+            .vui_hrd_parameters_present_flag = sps->vui.vui_hrd_parameters_present_flag,
+            .bitstream_restriction_flag = sps->vui.bitstream_restriction_flag,
+            .tiles_fixed_structure_flag = sps->vui.tiles_fixed_structure_flag,
+            .motion_vectors_over_pic_boundaries_flag = sps->vui.motion_vectors_over_pic_boundaries_flag,
+            .restricted_ref_pic_lists_flag = sps->vui.restricted_ref_pic_lists_flag,
+        },
+        .aspect_ratio_idc = sps->vui.common.aspect_ratio_idc,
+        .sar_width = sps->vui.common.sar.num,
+        .sar_height = sps->vui.common.sar.den,
+        .video_format = sps->vui.common.video_format,
+        .colour_primaries = sps->vui.common.colour_primaries,
+        .transfer_characteristics = sps->vui.common.transfer_characteristics,
+        .matrix_coeffs = sps->vui.common.matrix_coeffs,
+        .chroma_sample_loc_type_top_field = sps->vui.common.chroma_sample_loc_type_top_field,
+        .chroma_sample_loc_type_bottom_field = sps->vui.common.chroma_sample_loc_type_bottom_field,
+        /* Reserved */
+        /* Reserved */
+        .def_disp_win_left_offset = sps->vui.def_disp_win.left_offset,
+        .def_disp_win_right_offset = sps->vui.def_disp_win.right_offset,
+        .def_disp_win_top_offset = sps->vui.def_disp_win.top_offset,
+        .def_disp_win_bottom_offset = sps->vui.def_disp_win.bottom_offset,
+        .vui_num_units_in_tick = sps->vui.vui_num_units_in_tick,
+        .vui_time_scale = sps->vui.vui_time_scale,
+        .vui_num_ticks_poc_diff_one_minus1 = sps->vui.vui_num_ticks_poc_diff_one_minus1,
+        .min_spatial_segmentation_idc = sps->vui.min_spatial_segmentation_idc,
+        .max_bytes_per_pic_denom = sps->vui.max_bytes_per_pic_denom,
+        .max_bits_per_min_cu_denom = sps->vui.max_bits_per_min_cu_denom,
+        .log2_max_mv_length_horizontal = sps->vui.log2_max_mv_length_horizontal,
+        .log2_max_mv_length_vertical = sps->vui.log2_max_mv_length_vertical,
+        .pHrdParameters = vksps_vui_header,
+    };
+
+    *ptl = (StdVideoH265ProfileTierLevel) {
+        .flags = (StdVideoH265ProfileTierLevelFlags) {
+            .general_tier_flag = sps->ptl.general_ptl.tier_flag,
+            .general_progressive_source_flag = sps->ptl.general_ptl.progressive_source_flag,
+            .general_interlaced_source_flag = sps->ptl.general_ptl.interlaced_source_flag,
+            .general_non_packed_constraint_flag = sps->ptl.general_ptl.non_packed_constraint_flag,
+            .general_frame_only_constraint_flag = sps->ptl.general_ptl.frame_only_constraint_flag,
+        },
+        .general_profile_idc = sps->ptl.general_ptl.profile_idc,
+        .general_level_idc = ff_vk_h265_level_to_vk(sps->ptl.general_ptl.level_idc),
+    };
+
+    for (int i = 0; i < sps->max_sub_layers; i++) {
+        dpbm->max_latency_increase_plus1[i] = sps->temporal_layer[i].max_latency_increase + 1;
+        dpbm->max_dec_pic_buffering_minus1[i] = sps->temporal_layer[i].max_dec_pic_buffering - 1;
+        dpbm->max_num_reorder_pics[i] = sps->temporal_layer[i].num_reorder_pics;
+    }
+
+    for (int i = 0; i < (sps->chroma_format_idc ? 3 : 1); i++)
+        for (int j = 0; j < sps->sps_num_palette_predictor_initializers; j++)
+            pal->PredictorPaletteEntries[i][j] = sps->sps_palette_predictor_initializer[i][j];
+
+    for (int i = 0; i < sps->nb_st_rps; i++) {
+        const ShortTermRPS *st_rps = &sps->st_rps[i];
+
+        str[i] = (StdVideoH265ShortTermRefPicSet) {
+            .flags = (StdVideoH265ShortTermRefPicSetFlags) {
+                .inter_ref_pic_set_prediction_flag = sps->st_rps[i].rps_predict,
+                .delta_rps_sign = sps->st_rps[i].delta_rps_sign,
+            },
+            .delta_idx_minus1 = sps->st_rps[i].delta_idx - 1,
+            .use_delta_flag = sps->st_rps[i].use_delta,
+            .abs_delta_rps_minus1 = sps->st_rps[i].abs_delta_rps - 1,
+            .used_by_curr_pic_flag    = 0x0,
+            .used_by_curr_pic_s0_flag = 0x0,
+            .used_by_curr_pic_s1_flag = 0x0,
+            /* Reserved */
+            /* Reserved */
+            /* Reserved */
+            .num_negative_pics = sps->st_rps[i].num_negative_pics,
+            .num_positive_pics = sps->st_rps[i].num_delta_pocs - sps->st_rps[i].num_negative_pics,
+        };
+
+        /* NOTE: This is the predicted, and *reordered* version.
+         * Probably incorrect, but the spec doesn't say which version to use. */
+        str[i].used_by_curr_pic_flag = st_rps->used;
+        str[i].used_by_curr_pic_s0_flag = av_zero_extend(st_rps->used, str[i].num_negative_pics);
+        str[i].used_by_curr_pic_s1_flag = st_rps->used >> str[i].num_negative_pics;
+
+        for (int j = 0; j < str[i].num_negative_pics; j++)
+            str[i].delta_poc_s0_minus1[j] = st_rps->delta_poc[j] - (j ? st_rps->delta_poc[j - 1] : 0) - 1;
+
+        for (int j = 0; j < str[i].num_positive_pics; j++)
+            str[i].delta_poc_s1_minus1[j] = st_rps->delta_poc[st_rps->num_negative_pics + j] -
+                                            (j ? st_rps->delta_poc[st_rps->num_negative_pics + j - 1] : 0) - 1;
+    }
+
+    *ltr = (StdVideoH265LongTermRefPicsSps) {
+        .used_by_curr_pic_lt_sps_flag = sps->used_by_curr_pic_lt,
+    };
+
+    for (int i = 0; i < sps->num_long_term_ref_pics_sps; i++) {
+        ltr->lt_ref_pic_poc_lsb_sps[i]     = sps->lt_ref_pic_poc_lsb_sps[i];
+    }
+
+    *vksps = (StdVideoH265SequenceParameterSet) {
+        .flags = (StdVideoH265SpsFlags) {
+            .sps_temporal_id_nesting_flag = sps->temporal_id_nesting,
+            .separate_colour_plane_flag = sps->separate_colour_plane,
+            .conformance_window_flag = sps->conformance_window,
+            .sps_sub_layer_ordering_info_present_flag = sps->sublayer_ordering_info,
+            .scaling_list_enabled_flag = sps->scaling_list_enabled,
+            .sps_scaling_list_data_present_flag = sps->scaling_list_enabled,
+            .amp_enabled_flag = sps->amp_enabled,
+            .sample_adaptive_offset_enabled_flag = sps->sao_enabled,
+            .pcm_enabled_flag = sps->pcm_enabled,
+            .pcm_loop_filter_disabled_flag = sps->pcm_loop_filter_disabled,
+            .long_term_ref_pics_present_flag = sps->long_term_ref_pics_present,
+            .sps_temporal_mvp_enabled_flag = sps->temporal_mvp_enabled,
+            .strong_intra_smoothing_enabled_flag = sps->strong_intra_smoothing_enabled,
+            .vui_parameters_present_flag = sps->vui_present,
+            .sps_extension_present_flag = sps->extension_present,
+            .sps_range_extension_flag = sps->range_extension,
+            .transform_skip_rotation_enabled_flag = sps->transform_skip_rotation_enabled,
+            .transform_skip_context_enabled_flag = sps->transform_skip_context_enabled,
+            .implicit_rdpcm_enabled_flag = sps->implicit_rdpcm_enabled,
+            .explicit_rdpcm_enabled_flag = sps->explicit_rdpcm_enabled,
+            .extended_precision_processing_flag = sps->extended_precision_processing,
+            .intra_smoothing_disabled_flag = sps->intra_smoothing_disabled,
+            .high_precision_offsets_enabled_flag = sps->high_precision_offsets_enabled,
+            .persistent_rice_adaptation_enabled_flag = sps->persistent_rice_adaptation_enabled,
+            .cabac_bypass_alignment_enabled_flag = sps->cabac_bypass_alignment_enabled,
+            .sps_scc_extension_flag = sps->scc_extension,
+            .sps_curr_pic_ref_enabled_flag = sps->curr_pic_ref_enabled,
+            .palette_mode_enabled_flag = sps->palette_mode_enabled,
+            .sps_palette_predictor_initializers_present_flag = sps->palette_predictor_initializers_present,
+            .intra_boundary_filtering_disabled_flag = sps->intra_boundary_filtering_disabled,
+        },
+        .chroma_format_idc = sps->chroma_format_idc,
+        .pic_width_in_luma_samples = sps->width,
+        .pic_height_in_luma_samples = sps->height,
+        .sps_video_parameter_set_id = sps->vps_id,
+        .sps_max_sub_layers_minus1 = sps->max_sub_layers - 1,
+        .sps_seq_parameter_set_id = sps_idx,
+        .bit_depth_luma_minus8 = sps->bit_depth - 8,
+        .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8,
+        .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4,
+        .log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3,
+        .log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size,
+        .log2_min_luma_transform_block_size_minus2 = sps->log2_min_tb_size - 2,
+        .log2_diff_max_min_luma_transform_block_size = sps->log2_diff_max_min_transform_block_size,
+        .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter,
+        .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra,
+        .num_short_term_ref_pic_sets = sps->nb_st_rps,
+        .num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps,
+        .pcm_sample_bit_depth_luma_minus1 = sps->pcm.bit_depth - 1,
+        .pcm_sample_bit_depth_chroma_minus1 = sps->pcm.bit_depth_chroma - 1,
+        .log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm.log2_min_pcm_cb_size - 3,
+        .log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size,
+        /* Reserved */
+        /* Reserved */
+        .palette_max_size = sps->palette_max_size,
+        .delta_palette_max_predictor_size = sps->delta_palette_max_predictor_size,
+        .motion_vector_resolution_control_idc = sps->motion_vector_resolution_control_idc,
+        .sps_num_palette_predictor_initializers_minus1 = sps->sps_num_palette_predictor_initializers - 1,
+        .conf_win_left_offset = sps->pic_conf_win.left_offset,
+        .conf_win_right_offset = sps->pic_conf_win.right_offset,
+        .conf_win_top_offset = sps->pic_conf_win.top_offset,
+        .conf_win_bottom_offset = sps->pic_conf_win.bottom_offset,
+        .pProfileTierLevel = ptl,
+        .pDecPicBufMgr = dpbm,
+        .pScalingLists = vksps_scaling,
+        .pShortTermRefPicSet = str,
+        .pLongTermRefPicsSps = ltr,
+        .pSequenceParameterSetVui = vksps_vui,
+        .pPredictorPaletteEntries = pal,
+    };
+}
+
+static void set_pps(const HEVCPPS *pps, const HEVCSPS *sps,
+                    StdVideoH265ScalingLists *vkpps_scaling,
+                    StdVideoH265PictureParameterSet *vkpps,
+                    StdVideoH265PredictorPaletteEntries *pal)
+{
+    copy_scaling_list(&pps->scaling_list, vkpps_scaling);
+
+    *vkpps = (StdVideoH265PictureParameterSet) {
+        .flags = (StdVideoH265PpsFlags) {
+            .dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag,
+            .output_flag_present_flag = pps->output_flag_present_flag,
+            .sign_data_hiding_enabled_flag = pps->sign_data_hiding_flag,
+            .cabac_init_present_flag = pps->cabac_init_present_flag,
+            .constrained_intra_pred_flag = pps->constrained_intra_pred_flag,
+            .transform_skip_enabled_flag = pps->transform_skip_enabled_flag,
+            .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag,
+            .pps_slice_chroma_qp_offsets_present_flag = pps->pic_slice_level_chroma_qp_offsets_present_flag,
+            .weighted_pred_flag = pps->weighted_pred_flag,
+            .weighted_bipred_flag = pps->weighted_bipred_flag,
+            .transquant_bypass_enabled_flag = pps->transquant_bypass_enable_flag,
+            .tiles_enabled_flag = pps->tiles_enabled_flag,
+            .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag,
+            .uniform_spacing_flag = pps->uniform_spacing_flag,
+            .loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag,
+            .pps_loop_filter_across_slices_enabled_flag = pps->seq_loop_filter_across_slices_enabled_flag,
+            .deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag,
+            .deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag,
+            .pps_deblocking_filter_disabled_flag = pps->disable_dbf,
+            .pps_scaling_list_data_present_flag = pps->scaling_list_data_present_flag,
+            .lists_modification_present_flag = pps->lists_modification_present_flag,
+            .slice_segment_header_extension_present_flag = pps->slice_header_extension_present_flag,
+            .pps_extension_present_flag = pps->pps_extension_present_flag,
+            .cross_component_prediction_enabled_flag = pps->cross_component_prediction_enabled_flag,
+            .chroma_qp_offset_list_enabled_flag = pps->chroma_qp_offset_list_enabled_flag,
+            .pps_curr_pic_ref_enabled_flag = pps->pps_curr_pic_ref_enabled_flag,
+            .residual_adaptive_colour_transform_enabled_flag = pps->residual_adaptive_colour_transform_enabled_flag,
+            .pps_slice_act_qp_offsets_present_flag = pps->pps_slice_act_qp_offsets_present_flag,
+            .pps_palette_predictor_initializers_present_flag = pps->pps_palette_predictor_initializers_present_flag,
+            .monochrome_palette_flag = pps->monochrome_palette_flag,
+            .pps_range_extension_flag = pps->pps_range_extensions_flag,
+        },
+        .pps_pic_parameter_set_id = pps->pps_id,
+        .pps_seq_parameter_set_id = pps->sps_id,
+        .sps_video_parameter_set_id = sps->vps_id,
+        .num_extra_slice_header_bits = pps->num_extra_slice_header_bits,
+        .num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active - 1,
+        .num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active - 1,
+        .init_qp_minus26 = pps->pic_init_qp_minus26,
+        .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth,
+        .pps_cb_qp_offset = pps->cb_qp_offset,
+        .pps_cr_qp_offset = pps->cr_qp_offset,
+        .pps_beta_offset_div2 = pps->beta_offset >> 1,
+        .pps_tc_offset_div2 = pps->tc_offset >> 1,
+        .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2,
+        .log2_max_transform_skip_block_size_minus2 = pps->log2_max_transform_skip_block_size - 2,
+        .diff_cu_chroma_qp_offset_depth = pps->diff_cu_chroma_qp_offset_depth,
+        .chroma_qp_offset_list_len_minus1 = pps->chroma_qp_offset_list_len_minus1,
+        .log2_sao_offset_scale_luma = pps->log2_sao_offset_scale_luma,
+        .log2_sao_offset_scale_chroma = pps->log2_sao_offset_scale_chroma,
+        .pps_act_y_qp_offset_plus5 = pps->pps_act_y_qp_offset + 5,
+        .pps_act_cb_qp_offset_plus5 = pps->pps_act_cb_qp_offset + 5,
+        .pps_act_cr_qp_offset_plus3 = pps->pps_act_cr_qp_offset + 3,
+        .pps_num_palette_predictor_initializers = pps->pps_num_palette_predictor_initializers,
+        .luma_bit_depth_entry_minus8 = pps->luma_bit_depth_entry - 8,
+        .chroma_bit_depth_entry_minus8 = pps->chroma_bit_depth_entry - 8,
+        .num_tile_columns_minus1 = pps->num_tile_columns - 1,
+        .num_tile_rows_minus1 = pps->num_tile_rows - 1,
+        .pScalingLists = vkpps_scaling,
+        .pPredictorPaletteEntries = pal,
+    };
+
+    for (int i = 0; i < (pps->monochrome_palette_flag ? 1 : 3); i++) {
+        for (int j = 0; j < pps->pps_num_palette_predictor_initializers; j++)
+            pal->PredictorPaletteEntries[i][j] = pps->pps_palette_predictor_initializer[i][j];
+    }
+
+    for (int i = 0; i < pps->num_tile_columns - 1; i++)
+        vkpps->column_width_minus1[i] = pps->column_width[i] - 1;
+
+    for (int i = 0; i < pps->num_tile_rows - 1; i++)
+        vkpps->row_height_minus1[i] = pps->row_height[i] - 1;
+
+    for (int i = 0; i <= pps->chroma_qp_offset_list_len_minus1; i++) {
+        vkpps->cb_qp_offset_list[i] = pps->cb_qp_offset_list[i];
+        vkpps->cr_qp_offset_list[i] = pps->cr_qp_offset_list[i];
+    }
+}
+
+static void set_vps(const HEVCVPS *vps,
+                    StdVideoH265VideoParameterSet *vkvps,
+                    StdVideoH265ProfileTierLevel *ptl,
+                    StdVideoH265DecPicBufMgr *dpbm,
+                    StdVideoH265HrdParameters *sls_hdr,
+                    HEVCHeaderVPSSet sls[])
+{
+    for (int i = 0; i < vps->vps_num_hrd_parameters; i++) {
+        const HEVCHdrParams *src = &vps->hdr[i];
+
+        sls_hdr[i] = (StdVideoH265HrdParameters) {
+            .flags = (StdVideoH265HrdFlags) {
+                .nal_hrd_parameters_present_flag = src->nal_hrd_parameters_present_flag,
+                .vcl_hrd_parameters_present_flag = src->vcl_hrd_parameters_present_flag,
+                .sub_pic_hrd_params_present_flag = src->sub_pic_hrd_params_present_flag,
+                .sub_pic_cpb_params_in_pic_timing_sei_flag = src->sub_pic_cpb_params_in_pic_timing_sei_flag,
+                .fixed_pic_rate_general_flag = src->flags.fixed_pic_rate_general_flag,
+                .fixed_pic_rate_within_cvs_flag = src->flags.fixed_pic_rate_within_cvs_flag,
+                .low_delay_hrd_flag = src->flags.low_delay_hrd_flag,
+            },
+            .tick_divisor_minus2 = src->tick_divisor_minus2,
+            .du_cpb_removal_delay_increment_length_minus1 = src->du_cpb_removal_delay_increment_length_minus1,
+            .dpb_output_delay_du_length_minus1 = src->dpb_output_delay_du_length_minus1,
+            .bit_rate_scale = src->bit_rate_scale,
+            .cpb_size_scale = src->cpb_size_scale,
+            .cpb_size_du_scale = src->cpb_size_du_scale,
+            .initial_cpb_removal_delay_length_minus1 = src->initial_cpb_removal_delay_length_minus1,
+            .au_cpb_removal_delay_length_minus1 = src->au_cpb_removal_delay_length_minus1,
+            .dpb_output_delay_length_minus1 = src->dpb_output_delay_length_minus1,
+            /* Reserved - 3*16 bits */
+            .pSubLayerHrdParametersNal = sls[i].nal_hdr,
+            .pSubLayerHrdParametersVcl = sls[i].vcl_hdr,
+        };
+
+        memcpy(sls_hdr[i].cpb_cnt_minus1, src->cpb_cnt_minus1,
+               STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*sls_hdr[i].cpb_cnt_minus1));
+        memcpy(sls_hdr[i].elemental_duration_in_tc_minus1, src->elemental_duration_in_tc_minus1,
+               STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*sls_hdr[i].elemental_duration_in_tc_minus1));
+
+        memcpy(sls[i].nal_hdr, src->nal_params, HEVC_MAX_SUB_LAYERS*sizeof(*sls[i].nal_hdr));
+        memcpy(sls[i].vcl_hdr, src->vcl_params, HEVC_MAX_SUB_LAYERS*sizeof(*sls[i].vcl_hdr));
+    }
+
+    *ptl = (StdVideoH265ProfileTierLevel) {
+        .flags = (StdVideoH265ProfileTierLevelFlags) {
+            .general_tier_flag = vps->ptl.general_ptl.tier_flag,
+            .general_progressive_source_flag = vps->ptl.general_ptl.progressive_source_flag,
+            .general_interlaced_source_flag = vps->ptl.general_ptl.interlaced_source_flag,
+            .general_non_packed_constraint_flag = vps->ptl.general_ptl.non_packed_constraint_flag,
+            .general_frame_only_constraint_flag = vps->ptl.general_ptl.frame_only_constraint_flag,
+        },
+        .general_profile_idc = ff_vk_h265_profile_to_vk(vps->ptl.general_ptl.profile_idc),
+        .general_level_idc = ff_vk_h265_level_to_vk(vps->ptl.general_ptl.level_idc),
+    };
+
+    for (int i = 0; i < vps->vps_max_sub_layers; i++) {
+        dpbm->max_latency_increase_plus1[i] = vps->vps_max_latency_increase[i] + 1;
+        dpbm->max_dec_pic_buffering_minus1[i] = vps->vps_max_dec_pic_buffering[i] - 1;
+        dpbm->max_num_reorder_pics[i] = vps->vps_num_reorder_pics[i];
+    }
+
+    *vkvps = (StdVideoH265VideoParameterSet) {
+        .flags = (StdVideoH265VpsFlags) {
+            .vps_temporal_id_nesting_flag = vps->vps_temporal_id_nesting_flag,
+            .vps_sub_layer_ordering_info_present_flag = vps->vps_sub_layer_ordering_info_present_flag,
+            .vps_timing_info_present_flag = vps->vps_timing_info_present_flag,
+            .vps_poc_proportional_to_timing_flag = vps->vps_poc_proportional_to_timing_flag,
+        },
+        .vps_video_parameter_set_id = vps->vps_id,
+        .vps_max_sub_layers_minus1 = vps->vps_max_sub_layers - 1,
+        /* Reserved */
+        /* Reserved */
+        .vps_num_units_in_tick = vps->vps_num_units_in_tick,
+        .vps_time_scale = vps->vps_time_scale,
+        .vps_num_ticks_poc_diff_one_minus1 = vps->vps_num_ticks_poc_diff_one - 1,
+        /* Reserved */
+        .pDecPicBufMgr = dpbm,
+        .pHrdParameters = sls_hdr,
+        .pProfileTierLevel = ptl,
+    };
+}
+
+static int vk_hevc_create_params(AVCodecContext *avctx, AVBufferRef **buf)
+{
+    int err;
+    const HEVCContext *h = avctx->priv_data;
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+
+    VkVideoDecodeH265SessionParametersAddInfoKHR h265_params_info = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR,
+        .stdSPSCount = 0,
+        .stdPPSCount = 0,
+        .stdVPSCount = 0,
+    };
+    VkVideoDecodeH265SessionParametersCreateInfoKHR h265_params = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR,
+        .pParametersAddInfo = &h265_params_info,
+    };
+    VkVideoSessionParametersCreateInfoKHR session_params_create = {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
+        .pNext = &h265_params,
+        .videoSession = ctx->common.session,
+        .videoSessionParametersTemplate = VK_NULL_HANDLE,
+    };
+
+    HEVCHeaderSet *hdr;
+    int nb_vps = 0;
+    int vps_list_idx[HEVC_MAX_VPS_COUNT];
+
+    for (int i = 0; i < HEVC_MAX_VPS_COUNT; i++)
+        if (h->ps.vps_list[i])
+            vps_list_idx[nb_vps++] = i;
+
+    err = alloc_hevc_header_structs(dec, nb_vps, vps_list_idx, h->ps.vps_list);
+    if (err < 0)
+        return err;
+
+    hdr = dec->hevc_headers;
+
+    h265_params_info.pStdSPSs = hdr->sps;
+    h265_params_info.pStdPPSs = hdr->pps;
+    h265_params_info.pStdVPSs = hdr->vps;
+
+    /* SPS list */
+    for (int i = 0; i < HEVC_MAX_SPS_COUNT; i++) {
+        if (h->ps.sps_list[i]) {
+            const HEVCSPS *sps_l = h->ps.sps_list[i];
+            int idx = h265_params_info.stdSPSCount++;
+            set_sps(sps_l, i, &hdr->hsps[idx].scaling, &hdr->hsps[idx].vui_header,
+                    &hdr->hsps[idx].vui, &hdr->sps[idx], hdr->hsps[idx].nal_hdr,
+                    hdr->hsps[idx].vcl_hdr, &hdr->hsps[idx].ptl, &hdr->hsps[idx].dpbm,
+                    &hdr->hsps[idx].pal, hdr->hsps[idx].str, &hdr->hsps[idx].ltr);
+        }
+    }
+
+    /* PPS list */
+    for (int i = 0; i < HEVC_MAX_PPS_COUNT; i++) {
+        if (h->ps.pps_list[i]) {
+            const HEVCPPS *pps_l = h->ps.pps_list[i];
+            const HEVCSPS *sps_l = h->ps.sps_list[pps_l->sps_id];
+            int idx = h265_params_info.stdPPSCount++;
+            set_pps(pps_l, sps_l, &hdr->hpps[idx].scaling,
+                    &hdr->pps[idx], &hdr->hpps[idx].pal);
+        }
+    }
+
+    /* VPS list */
+    for (int i = 0; i < nb_vps; i++) {
+        const HEVCVPS *vps_l = h->ps.vps_list[vps_list_idx[i]];
+        set_vps(vps_l, &hdr->vps[i], &hdr->hvps[i].ptl, &hdr->hvps[i].dpbm,
+                hdr->hvps[i].hdr, hdr->hvps[i].sls);
+        h265_params_info.stdVPSCount++;
+    }
+
+    h265_params.maxStdSPSCount = h265_params_info.stdSPSCount;
+    h265_params.maxStdPPSCount = h265_params_info.stdPPSCount;
+    h265_params.maxStdVPSCount = h265_params_info.stdVPSCount;
+
+    err = ff_vk_decode_create_params(buf, avctx, ctx, &session_params_create);
+    if (err < 0)
+        return err;
+
+    av_log(avctx, AV_LOG_DEBUG, "Created frame parameters: %i SPS %i PPS %i VPS\n",
+           h265_params_info.stdSPSCount, h265_params_info.stdPPSCount,
+           h265_params_info.stdVPSCount);
+
+    return 0;
+}
+
+static int vk_hevc_start_frame(AVCodecContext          *avctx,
+                               av_unused const AVBufferRef *buffer_ref,
+                               av_unused const uint8_t *buffer,
+                               av_unused uint32_t       size)
+{
+    int err;
+    HEVCContext *h = avctx->priv_data;
+    HEVCLayerContext *l = &h->layers[h->cur_layer];
+
+    HEVCFrame *pic = h->cur_frame;
+    HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &hp->vp;
+    const HEVCPPS *pps = h->pps;
+    const HEVCSPS *sps = pps->sps;
+    int nb_refs = 0;
+
+    hp->h265pic = (StdVideoDecodeH265PictureInfo) {
+        .flags = (StdVideoDecodeH265PictureInfoFlags) {
+            .IrapPicFlag = IS_IRAP(h),
+            .IdrPicFlag = IS_IDR(h),
+            .IsReference = h->nal_unit_type < 16 ? h->nal_unit_type & 1 : 1,
+            .short_term_ref_pic_set_sps_flag = h->sh.short_term_ref_pic_set_sps_flag,
+        },
+        .sps_video_parameter_set_id = sps->vps_id,
+        .pps_seq_parameter_set_id = pps->sps_id,
+        .pps_pic_parameter_set_id = pps->pps_id,
+        .NumDeltaPocsOfRefRpsIdx = h->sh.short_term_rps ? h->sh.short_term_rps->rps_idx_num_delta_pocs : 0,
+        .PicOrderCntVal = h->poc,
+        .NumBitsForSTRefPicSetInSlice = !h->sh.short_term_ref_pic_set_sps_flag ?
+                                         h->sh.short_term_ref_pic_set_size : 0,
+    };
+
+    /* Fill in references */
+    for (int i = 0; i < FF_ARRAY_ELEMS(l->DPB); i++) {
+        const HEVCFrame *ref = &l->DPB[i];
+        int idx = nb_refs;
+
+        if (!(ref->flags & (HEVC_FRAME_FLAG_SHORT_REF | HEVC_FRAME_FLAG_LONG_REF)))
+            continue;
+
+        if (ref == pic) {
+            err = vk_hevc_fill_pict(avctx, NULL, &vp->ref_slot, &vp->ref,
+                                    &hp->vkh265_ref, &hp->h265_ref, pic, 1, i);
+            if (err < 0)
+                return err;
+
+            continue;
+        }
+
+        err = vk_hevc_fill_pict(avctx, &hp->ref_src[idx], &vp->ref_slots[idx],
+                                &vp->refs[idx], &hp->vkh265_refs[idx],
+                                &hp->h265_refs[idx], (HEVCFrame *)ref, 0, i);
+        if (err < 0)
+            return err;
+
+        nb_refs++;
+    }
+
+    memset(hp->h265pic.RefPicSetStCurrBefore, 0xff, 8);
+    for (int i = 0; i < h->rps[ST_CURR_BEF].nb_refs; i++) {
+        HEVCFrame *frame = h->rps[ST_CURR_BEF].ref[i];
+        for (int j = 0; j < FF_ARRAY_ELEMS(l->DPB); j++) {
+            const HEVCFrame *ref = &l->DPB[j];
+            if (ref == frame) {
+                hp->h265pic.RefPicSetStCurrBefore[i] = j;
+                break;
+            }
+        }
+    }
+    memset(hp->h265pic.RefPicSetStCurrAfter, 0xff, 8);
+    for (int i = 0; i < h->rps[ST_CURR_AFT].nb_refs; i++) {
+        HEVCFrame *frame = h->rps[ST_CURR_AFT].ref[i];
+        for (int j = 0; j < FF_ARRAY_ELEMS(l->DPB); j++) {
+            const HEVCFrame *ref = &l->DPB[j];
+            if (ref == frame) {
+                hp->h265pic.RefPicSetStCurrAfter[i] = j;
+                break;
+            }
+        }
+    }
+    memset(hp->h265pic.RefPicSetLtCurr, 0xff, 8);
+    for (int i = 0; i < h->rps[LT_CURR].nb_refs; i++) {
+        HEVCFrame *frame = h->rps[LT_CURR].ref[i];
+        for (int j = 0; j < FF_ARRAY_ELEMS(l->DPB); j++) {
+            const HEVCFrame *ref = &l->DPB[j];
+            if (ref == frame) {
+                hp->h265pic.RefPicSetLtCurr[i] = j;
+                break;
+            }
+        }
+    }
+
+    hp->h265_pic_info = (VkVideoDecodeH265PictureInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_KHR,
+        .pStdPictureInfo = &hp->h265pic,
+        .sliceSegmentCount = 0,
+    };
+
+    vp->decode_info = (VkVideoDecodeInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR,
+        .pNext = &hp->h265_pic_info,
+        .flags = 0x0,
+        .pSetupReferenceSlot = &vp->ref_slot,
+        .referenceSlotCount = nb_refs,
+        .pReferenceSlots = vp->ref_slots,
+        .dstPictureResource = (VkVideoPictureResourceInfoKHR) {
+            .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
+            .codedOffset = (VkOffset2D){ 0, 0 },
+            .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
+            .baseArrayLayer = 0,
+            .imageViewBinding = vp->view.out[0],
+        },
+    };
+
+    return 0;
+}
+
+static int vk_hevc_decode_slice(AVCodecContext *avctx,
+                                const uint8_t  *data,
+                                uint32_t        size)
+{
+    const HEVCContext *h = avctx->priv_data;
+    HEVCVulkanDecodePicture *hp = h->cur_frame->hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &hp->vp;
+
+    int err = ff_vk_decode_add_slice(avctx, vp, data, size, 1,
+                                     &hp->h265_pic_info.sliceSegmentCount,
+                                     &hp->h265_pic_info.pSliceSegmentOffsets);
+    if (err < 0)
+        return err;
+
+    return 0;
+}
+
+static int vk_hevc_end_frame(AVCodecContext *avctx)
+{
+    const HEVCContext *h = avctx->priv_data;
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+
+    HEVCFrame *pic = h->cur_frame;
+    HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &hp->vp;
+    FFVulkanDecodePicture *rvp[HEVC_MAX_REFS] = { 0 };
+    AVFrame *rav[HEVC_MAX_REFS] = { 0 };
+    int err;
+
+    const HEVCPPS *pps = h->pps;
+    const HEVCSPS *sps = pps->sps;
+
+#ifdef VK_KHR_video_maintenance2
+    HEVCHeaderPPS vkpps_p;
+    StdVideoH265PictureParameterSet vkpps;
+    HEVCHeaderSPS vksps_p;
+    StdVideoH265SequenceParameterSet vksps;
+    HEVCHeaderVPSSet vkvps_ps[HEVC_MAX_SUB_LAYERS];
+    HEVCHeaderVPS vkvps_p;
+    StdVideoH265VideoParameterSet vkvps;
+    VkVideoDecodeH265InlineSessionParametersInfoKHR h265_params;
+
+    if (ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2) {
+        set_pps(pps, sps, &vkpps_p.scaling, &vkpps, &vkpps_p.pal);
+        set_sps(sps, pps->sps_id, &vksps_p.scaling, &vksps_p.vui_header,
+                &vksps_p.vui, &vksps, vksps_p.nal_hdr,
+                vksps_p.vcl_hdr, &vksps_p.ptl, &vksps_p.dpbm,
+                &vksps_p.pal, vksps_p.str, &vksps_p.ltr);
+
+        vkvps_p.sls = vkvps_ps;
+        set_vps(sps->vps, &vkvps, &vkvps_p.ptl, &vkvps_p.dpbm,
+                vkvps_p.hdr, vkvps_p.sls);
+
+        h265_params = (VkVideoDecodeH265InlineSessionParametersInfoKHR) {
+            .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_INLINE_SESSION_PARAMETERS_INFO_KHR,
+            .pStdSPS = &vksps,
+            .pStdPPS = &vkpps,
+            .pStdVPS = &vkvps,
+        };
+        hp->h265_pic_info.pNext = &h265_params;
+    }
+#endif
+
+    if (!hp->h265_pic_info.sliceSegmentCount)
+        return 0;
+
+    if (!dec->session_params &&
+        !(ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)) {
+        if (!pps) {
+            unsigned int pps_id = h->sh.pps_id;
+            if (pps_id < HEVC_MAX_PPS_COUNT && h->ps.pps_list[pps_id] != NULL)
+                pps = h->ps.pps_list[pps_id];
+        }
+
+        if (!pps) {
+            av_log(avctx, AV_LOG_ERROR,
+                   "Encountered frame without a valid active PPS reference.\n");
+            return AVERROR_INVALIDDATA;
+        }
+
+        err = vk_hevc_create_params(avctx, &dec->session_params);
+        if (err < 0)
+            return err;
+
+        hp->h265pic.sps_video_parameter_set_id = sps->vps_id;
+        hp->h265pic.pps_seq_parameter_set_id = pps->sps_id;
+        hp->h265pic.pps_pic_parameter_set_id = pps->pps_id;
+    }
+
+    for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
+        HEVCVulkanDecodePicture *rfhp = hp->ref_src[i]->hwaccel_picture_private;
+        rav[i] = hp->ref_src[i]->f;
+        rvp[i] = &rfhp->vp;
+    }
+
+    av_log(avctx, AV_LOG_DEBUG, "Decoding frame, %"SIZE_SPECIFIER" bytes, %i slices\n",
+           vp->slices_size, hp->h265_pic_info.sliceSegmentCount);
+
+    return ff_vk_decode_frame(avctx, pic->f, vp, rav, rvp);
+}
+
+static void vk_hevc_free_frame_priv(AVRefStructOpaque _hwctx, void *data)
+{
+    AVHWDeviceContext *hwctx = _hwctx.nc;
+    HEVCVulkanDecodePicture *hp = data;
+
+    /* Free frame resources */
+    ff_vk_decode_free_frame(hwctx, &hp->vp);
+}
+
+const FFHWAccel ff_hevc_vulkan_hwaccel = {
+    .p.name                = "hevc_vulkan",
+    .p.type                = AVMEDIA_TYPE_VIDEO,
+    .p.id                  = AV_CODEC_ID_HEVC,
+    .p.pix_fmt             = AV_PIX_FMT_VULKAN,
+    .start_frame           = &vk_hevc_start_frame,
+    .decode_slice          = &vk_hevc_decode_slice,
+    .end_frame             = &vk_hevc_end_frame,
+    .free_frame_priv       = &vk_hevc_free_frame_priv,
+    .frame_priv_data_size  = sizeof(HEVCVulkanDecodePicture),
+    .init                  = &ff_vk_decode_init,
+    .update_thread_context = &ff_vk_update_thread_context,
+    .decode_params         = &ff_vk_params_invalidate,
+    .flush                 = &ff_vk_decode_flush,
+    .uninit                = &ff_vk_decode_uninit,
+    .frame_params          = &ff_vk_frame_params,
+    .priv_data_size        = sizeof(FFVulkanDecodeContext),
+    .caps_internal         = HWACCEL_CAP_ASYNC_SAFE,
+};
-- 
2.49.1


From f84b108065ff196a359bda238526a99fc938a967 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:39:16 +0000
Subject: [PATCH 085/118] Changing vulkan file directory

---
 libavcodec/vulkan_prores_raw.c | 503 ---------------------------------
 1 file changed, 503 deletions(-)
 delete mode 100644 libavcodec/vulkan_prores_raw.c

diff --git a/libavcodec/vulkan_prores_raw.c b/libavcodec/vulkan_prores_raw.c
deleted file mode 100644
index 7a1f97a640..0000000000
--- a/libavcodec/vulkan_prores_raw.c
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * Copyright (c) 2025 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "vulkan_decode.h"
-#include "hwaccel_internal.h"
-
-#include "prores_raw.h"
-#include "libavutil/vulkan_spirv.h"
-#include "libavutil/mem.h"
-
-extern const char *ff_source_common_comp;
-extern const char *ff_source_prores_raw_comp;
-
-const FFVulkanDecodeDescriptor ff_vk_dec_prores_raw_desc = {
-    .codec_id         = AV_CODEC_ID_PRORES_RAW,
-    .decode_extension = FF_VK_EXT_PUSH_DESCRIPTOR,
-    .queue_flags      = VK_QUEUE_COMPUTE_BIT,
-};
-
-typedef struct ProResRAWVulkanDecodePicture {
-    FFVulkanDecodePicture vp;
-
-    AVBufferRef *tile_data;
-    uint32_t nb_tiles;
-} ProResRAWVulkanDecodePicture;
-
-typedef struct ProResRAWVulkanDecodeContext {
-    FFVulkanShader decode[2];
-
-    AVBufferPool *tile_data_pool;
-
-    FFVkBuffer uniform_buf;
-} ProResRAWVulkanDecodeContext;
-
-typedef struct DecodePushData {
-    VkDeviceAddress tile_data;
-    VkDeviceAddress pkt_data;
-    uint32_t frame_size[2];
-    uint32_t tile_size[2];
-    uint8_t  qmat[64];
-} DecodePushData;
-
-typedef struct TileData {
-    int32_t pos[2];
-    uint32_t offset;
-    uint32_t size;
-} TileData;
-
-static int vk_prores_raw_start_frame(AVCodecContext          *avctx,
-                                     const AVBufferRef       *buffer_ref,
-                                     av_unused const uint8_t *buffer,
-                                     av_unused uint32_t       size)
-{
-    int err;
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-    ProResRAWVulkanDecodeContext *prv = ctx->sd_ctx;
-    ProResRAWContext *prr = avctx->priv_data;
-
-    ProResRAWVulkanDecodePicture *pp = prr->hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &pp->vp;
-
-    /* Host map the input tile data if supported */
-    if (ctx->s.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY)
-        ff_vk_host_map_buffer(&ctx->s, &vp->slices_buf, buffer_ref->data,
-                              buffer_ref,
-                              VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
-                              VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
-
-    /* Allocate tile data */
-    err = ff_vk_get_pooled_buffer(&ctx->s, &prv->tile_data_pool,
-                                  &pp->tile_data,
-                                  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
-                                  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
-                                  NULL, prr->nb_tiles*sizeof(TileData),
-                                  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
-                                  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
-    if (err < 0)
-        return err;
-
-    /* Prepare frame to be used */
-    err = ff_vk_decode_prepare_frame_sdr(dec, prr->frame, vp, 1,
-                                         FF_VK_REP_FLOAT, 0);
-    if (err < 0)
-        return err;
-
-    return 0;
-}
-
-static int vk_prores_raw_decode_slice(AVCodecContext *avctx,
-                                      const uint8_t  *data,
-                                      uint32_t        size)
-{
-    ProResRAWContext *prr = avctx->priv_data;
-
-    ProResRAWVulkanDecodePicture *pp = prr->hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &pp->vp;
-
-    FFVkBuffer *tile_data_buf = (FFVkBuffer *)pp->tile_data->data;
-    TileData *td = (TileData *)tile_data_buf->mapped_mem;
-    FFVkBuffer *slices_buf = vp->slices_buf ? (FFVkBuffer *)vp->slices_buf->data : NULL;
-
-    td[pp->nb_tiles].pos[0] = prr->tiles[pp->nb_tiles].x;
-    td[pp->nb_tiles].pos[1] = prr->tiles[pp->nb_tiles].y;
-    td[pp->nb_tiles].size = size;
-
-    if (vp->slices_buf && slices_buf->host_ref) {
-        td[pp->nb_tiles].offset = data - slices_buf->mapped_mem;
-        pp->nb_tiles++;
-    } else {
-        int err;
-        td[pp->nb_tiles].offset = vp->slices_size;
-        err = ff_vk_decode_add_slice(avctx, vp, data, size, 0,
-                                     &pp->nb_tiles, NULL);
-        if (err < 0)
-            return err;
-    }
-
-    return 0;
-}
-
-static int vk_prores_raw_end_frame(AVCodecContext *avctx)
-{
-    int err;
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-    FFVulkanFunctions *vk = &ctx->s.vkfn;
-
-    ProResRAWContext *prr = avctx->priv_data;
-    ProResRAWVulkanDecodeContext *prv = ctx->sd_ctx;
-
-    ProResRAWVulkanDecodePicture *pp = prr->hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &pp->vp;
-
-    FFVkBuffer *slices_buf = (FFVkBuffer *)vp->slices_buf->data;
-    FFVkBuffer *tile_data = (FFVkBuffer *)pp->tile_data->data;
-
-    VkImageMemoryBarrier2 img_bar[8];
-    int nb_img_bar = 0;
-
-    FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
-    ff_vk_exec_start(&ctx->s, exec);
-
-    /* Prepare deps */
-    RET(ff_vk_exec_add_dep_frame(&ctx->s, exec, prr->frame,
-                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
-
-    err = ff_vk_exec_mirror_sem_value(&ctx->s, exec, &vp->sem, &vp->sem_value,
-                                      prr->frame);
-    if (err < 0)
-        return err;
-
-    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &pp->tile_data, 1, 0));
-    pp->tile_data = NULL;
-    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0));
-    vp->slices_buf = NULL;
-
-    ff_vk_frame_barrier(&ctx->s, exec, prr->frame, img_bar, &nb_img_bar,
-                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
-                        VK_ACCESS_2_TRANSFER_WRITE_BIT,
-                        VK_IMAGE_LAYOUT_GENERAL,
-                        VK_QUEUE_FAMILY_IGNORED);
-
-    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
-        .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
-        .pImageMemoryBarriers = img_bar,
-        .imageMemoryBarrierCount = nb_img_bar,
-    });
-    nb_img_bar = 0;
-
-    FFVulkanShader *decode_shader = &prv->decode[prr->version];
-    ff_vk_shader_update_img_array(&ctx->s, exec, decode_shader,
-                                  prr->frame, vp->view.out,
-                                  0, 0,
-                                  VK_IMAGE_LAYOUT_GENERAL,
-                                  VK_NULL_HANDLE);
-
-    ff_vk_exec_bind_shader(&ctx->s, exec, decode_shader);
-
-    /* Update push data */
-    DecodePushData pd_decode = (DecodePushData) {
-        .tile_data = tile_data->address,
-        .pkt_data = slices_buf->address,
-        .frame_size[0] = avctx->width,
-        .frame_size[1] = avctx->height,
-        .tile_size[0] = prr->tw,
-        .tile_size[1] = prr->th,
-    };
-    memcpy(pd_decode.qmat, prr->qmat, 64);
-    ff_vk_shader_update_push_const(&ctx->s, exec, decode_shader,
-                                   VK_SHADER_STAGE_COMPUTE_BIT,
-                                   0, sizeof(pd_decode), &pd_decode);
-
-    vk->CmdDispatch(exec->buf, prr->nb_tw, prr->nb_th, 1);
-
-    err = ff_vk_exec_submit(&ctx->s, exec);
-    if (err < 0)
-        return err;
-
-fail:
-    return 0;
-}
-
-static int init_decode_shader(ProResRAWContext *prr, FFVulkanContext *s,
-                              FFVkExecPool *pool, FFVkSPIRVCompiler *spv,
-                              FFVulkanShader *shd, int version)
-{
-    int err;
-    FFVulkanDescriptorSetBinding *desc_set;
-    int parallel_rows = 1;
-
-    uint8_t *spv_data;
-    size_t spv_len;
-    void *spv_opaque = NULL;
-
-    if (s->props.properties.limits.maxComputeWorkGroupInvocations < 512 ||
-        s->props.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
-        parallel_rows = 0;
-
-    RET(ff_vk_shader_init(s, shd, "prores_raw",
-                          VK_SHADER_STAGE_COMPUTE_BIT,
-                          (const char *[]) { "GL_EXT_buffer_reference",
-                                             "GL_EXT_buffer_reference2",
-                                             "GL_EXT_null_initializer" }, 3,
-                          parallel_rows ? 8 : 1 /* 8x8 transforms, 8-point width */,
-                          version == 0 ? 8 : 16 /* Horizontal blocks */,
-                          4 /* Components */,
-                          0));
-
-    if (parallel_rows)
-        GLSLC(0, #define PARALLEL_ROWS                                               );
-
-    /* Common codec header */
-    GLSLD(ff_source_common_comp);
-
-    GLSLC(0, layout(buffer_reference, buffer_reference_align = 16) buffer TileData { );
-    GLSLC(1,    ivec2 pos;                                                           );
-    GLSLC(1,    uint offset;                                                         );
-    GLSLC(1,    uint size;                                                           );
-    GLSLC(0, };                                                                      );
-    GLSLC(0,                                                                         );
-    GLSLC(0, layout(push_constant, scalar) uniform pushConstants {                   );
-    GLSLC(1,    TileData tile_data;                                                  );
-    GLSLC(1,    u8buf pkt_data;                                                      );
-    GLSLC(1,    uvec2 frame_size;                                                    );
-    GLSLC(1,    uvec2 tile_size;                                                     );
-    GLSLC(1,    uint8_t qmat[64];                                                    );
-    GLSLC(0, };                                                                      );
-    GLSLC(0,                                                                         );
-    ff_vk_shader_add_push_const(shd, 0, sizeof(DecodePushData),
-                                VK_SHADER_STAGE_COMPUTE_BIT);
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name       = "dst",
-            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
-            .mem_layout = "r16",
-            .mem_quali  = "writeonly",
-            .dimensions = 2,
-            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
-        },
-    };
-    RET(ff_vk_shader_add_descriptor_set(s, shd, desc_set, 1, 0, 0));
-
-    desc_set = (FFVulkanDescriptorSetBinding []) {
-        {
-            .name        = "dct_scale_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "float idct_8x8_scales[64];",
-        },
-        {
-            .name        = "scan_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "uint8_t scan[64];",
-        },
-        {
-            .name        = "dc_cb_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "uint8_t dc_cb[13];",
-        },
-        {
-            .name        = "ac_cb_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "int16_t ac_cb[95];",
-        },
-        {
-            .name        = "rn_cb_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "int16_t rn_cb[28];",
-        },
-        {
-            .name        = "ln_cb_buf",
-            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
-            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
-            .mem_layout  = "scalar",
-            .buf_content = "int16_t ln_cb[15];",
-        },
-    };
-    RET(ff_vk_shader_add_descriptor_set(s, shd, desc_set, 6, 1, 0));
-
-    GLSLD(ff_source_prores_raw_comp);
-
-    RET(spv->compile_shader(s, spv, shd, &spv_data, &spv_len, "main",
-                            &spv_opaque));
-    RET(ff_vk_shader_link(s, shd, spv_data, spv_len, "main"));
-
-    RET(ff_vk_shader_register_exec(s, pool, shd));
-
-fail:
-    if (spv_opaque)
-        spv->free_shader(spv, &spv_opaque);
-
-    return err;
-}
-
-static void vk_decode_prores_raw_uninit(FFVulkanDecodeShared *ctx)
-{
-    ProResRAWVulkanDecodeContext *fv = ctx->sd_ctx;
-
-    ff_vk_shader_free(&ctx->s, &fv->decode[0]);
-    ff_vk_shader_free(&ctx->s, &fv->decode[1]);
-
-    ff_vk_free_buf(&ctx->s, &fv->uniform_buf);
-
-    av_buffer_pool_uninit(&fv->tile_data_pool);
-
-    av_freep(&fv);
-}
-
-static int vk_decode_prores_raw_init(AVCodecContext *avctx)
-{
-    int err;
-    ProResRAWContext *prr = avctx->priv_data;
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-
-    FFVkSPIRVCompiler *spv = ff_vk_spirv_init();
-    if (!spv) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
-        return AVERROR_EXTERNAL;
-    }
-
-    err = ff_vk_decode_init(avctx);
-    if (err < 0)
-        return err;
-
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-    ProResRAWVulkanDecodeContext *prv = ctx->sd_ctx = av_mallocz(sizeof(*prv));
-    if (!prv) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    ctx->sd_ctx_free = &vk_decode_prores_raw_uninit;
-
-    /* Setup decode shader */
-    RET(init_decode_shader(prr, &ctx->s, &ctx->exec_pool, spv, &prv->decode[0], 0));
-    RET(init_decode_shader(prr, &ctx->s, &ctx->exec_pool, spv, &prv->decode[1], 1));
-
-    /* Size in bytes of each codebook table */
-    size_t cb_size[5] = {
-        13*sizeof(uint8_t),
-        95*sizeof(int16_t),
-        28*sizeof(int16_t),
-        15*sizeof(int16_t),
-    };
-
-    /* Offset of each codebook table */
-    size_t cb_offset[5];
-    size_t ua = ctx->s.props.properties.limits.minUniformBufferOffsetAlignment;
-    cb_offset[0] = 64*sizeof(float) + 64*sizeof(uint8_t);
-    cb_offset[1] = cb_offset[0] + FFALIGN(cb_size[0], ua);
-    cb_offset[2] = cb_offset[1] + FFALIGN(cb_size[1], ua);
-    cb_offset[3] = cb_offset[2] + FFALIGN(cb_size[2], ua);
-    cb_offset[4] = cb_offset[3] + FFALIGN(cb_size[3], ua);
-
-    RET(ff_vk_create_buf(&ctx->s, &prv->uniform_buf,
-                         64*sizeof(float) + 64*sizeof(uint8_t) + cb_offset[4] + 256,
-                         NULL, NULL,
-                         VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
-                         VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
-                         VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
-                         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
-
-    uint8_t *uniform_buf;
-    RET(ff_vk_map_buffer(&ctx->s, &prv->uniform_buf, &uniform_buf, 0));
-
-    /* DCT scales */
-    float *dct_scale_buf = (float *)uniform_buf;
-    double idct_8_scales[8] = {
-        cos(4.0*M_PI/16.0) / 2.0,
-        cos(1.0*M_PI/16.0) / 2.0,
-        cos(2.0*M_PI/16.0) / 2.0,
-        cos(3.0*M_PI/16.0) / 2.0,
-        cos(4.0*M_PI/16.0) / 2.0,
-        cos(5.0*M_PI/16.0) / 2.0,
-        cos(6.0*M_PI/16.0) / 2.0,
-        cos(7.0*M_PI/16.0) / 2.0,
-    };
-    for (int i = 0; i < 64; i++)
-        dct_scale_buf[i] = (float)(idct_8_scales[i >> 3] *
-                                   idct_8_scales[i  & 7]);
-
-    /* Scan table */
-    uint8_t *scan_buf = uniform_buf + 64*sizeof(float);
-    for (int i = 0; i < 64; i++)
-        scan_buf[prr->scan[i]] = i;
-
-    /* Codebooks */
-    memcpy(uniform_buf + cb_offset[0], ff_prores_raw_dc_cb,
-           sizeof(ff_prores_raw_dc_cb));
-    memcpy(uniform_buf + cb_offset[1], ff_prores_raw_ac_cb,
-           sizeof(ff_prores_raw_ac_cb));
-    memcpy(uniform_buf + cb_offset[2], ff_prores_raw_rn_cb,
-           sizeof(ff_prores_raw_rn_cb));
-    memcpy(uniform_buf + cb_offset[3], ff_prores_raw_ln_cb,
-           sizeof(ff_prores_raw_ln_cb));
-
-    RET(ff_vk_unmap_buffer(&ctx->s, &prv->uniform_buf, 1));
-
-    /* Done; update descriptors */
-    for (int i = 0; i < 2; i++) {
-        RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
-                                            &prv->decode[i], 1, 0, 0,
-                                            &prv->uniform_buf,
-                                            0, 64*sizeof(float),
-                                            VK_FORMAT_UNDEFINED));
-        RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
-                                            &prv->decode[i], 1, 1, 0,
-                                            &prv->uniform_buf,
-                                            64*sizeof(float), 64*sizeof(uint8_t),
-                                            VK_FORMAT_UNDEFINED));
-        for (int j = 0; j < 4; j++)
-            RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
-                                                &prv->decode[i], 1, 2 + j, 0,
-                                                &prv->uniform_buf,
-                                                cb_offset[j], cb_size[j],
-                                                VK_FORMAT_UNDEFINED));
-    }
-
-fail:
-    spv->uninit(&spv);
-
-    return err;
-}
-
-static void vk_prores_raw_free_frame_priv(AVRefStructOpaque _hwctx, void *data)
-{
-    AVHWDeviceContext *dev_ctx = _hwctx.nc;
-
-    ProResRAWVulkanDecodePicture *pp = data;
-    FFVulkanDecodePicture *vp = &pp->vp;
-
-    ff_vk_decode_free_frame(dev_ctx, vp);
-}
-
-const FFHWAccel ff_prores_raw_vulkan_hwaccel = {
-    .p.name                = "prores_raw_vulkan",
-    .p.type                = AVMEDIA_TYPE_VIDEO,
-    .p.id                  = AV_CODEC_ID_PRORES_RAW,
-    .p.pix_fmt             = AV_PIX_FMT_VULKAN,
-    .start_frame           = &vk_prores_raw_start_frame,
-    .decode_slice          = &vk_prores_raw_decode_slice,
-    .end_frame             = &vk_prores_raw_end_frame,
-    .free_frame_priv       = &vk_prores_raw_free_frame_priv,
-    .frame_priv_data_size  = sizeof(ProResRAWVulkanDecodePicture),
-    .init                  = &vk_decode_prores_raw_init,
-    .update_thread_context = &ff_vk_update_thread_context,
-    .decode_params         = &ff_vk_params_invalidate,
-    .flush                 = &ff_vk_decode_flush,
-    .uninit                = &ff_vk_decode_uninit,
-    .frame_params          = &ff_vk_frame_params,
-    .priv_data_size        = sizeof(FFVulkanDecodeContext),
-    .caps_internal         = HWACCEL_CAP_ASYNC_SAFE | HWACCEL_CAP_THREAD_SAFE,
-};
-- 
2.49.1


From 9ce26edc967bf1b27ad0469840ac4280aa068d9a Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:39:44 +0000
Subject: [PATCH 086/118] Changing vulkan file directory

---
 libavcodec/vulkan/vulkan_prores_raw.c | 503 ++++++++++++++++++++++++++
 1 file changed, 503 insertions(+)
 create mode 100644 libavcodec/vulkan/vulkan_prores_raw.c

diff --git a/libavcodec/vulkan/vulkan_prores_raw.c b/libavcodec/vulkan/vulkan_prores_raw.c
new file mode 100644
index 0000000000..a38835efcc
--- /dev/null
+++ b/libavcodec/vulkan/vulkan_prores_raw.c
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 2025 Lynne <dev@lynne.ee>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "vulkan_decode.h"
+#include "libavcodec/hwaccel_internal.h"
+
+#include "libavcodec/prores_raw.h"
+#include "../../libavutil/vulkan/vulkan_spirv.h"
+#include "libavutil/mem.h"
+
+extern const char *ff_source_common_comp;
+extern const char *ff_source_prores_raw_comp;
+
+const FFVulkanDecodeDescriptor ff_vk_dec_prores_raw_desc = {
+    .codec_id         = AV_CODEC_ID_PRORES_RAW,
+    .decode_extension = FF_VK_EXT_PUSH_DESCRIPTOR,
+    .queue_flags      = VK_QUEUE_COMPUTE_BIT,
+};
+
+typedef struct ProResRAWVulkanDecodePicture {
+    FFVulkanDecodePicture vp;
+
+    AVBufferRef *tile_data;
+    uint32_t nb_tiles;
+} ProResRAWVulkanDecodePicture;
+
+typedef struct ProResRAWVulkanDecodeContext {
+    FFVulkanShader decode[2];
+
+    AVBufferPool *tile_data_pool;
+
+    FFVkBuffer uniform_buf;
+} ProResRAWVulkanDecodeContext;
+
+typedef struct DecodePushData {
+    VkDeviceAddress tile_data;
+    VkDeviceAddress pkt_data;
+    uint32_t frame_size[2];
+    uint32_t tile_size[2];
+    uint8_t  qmat[64];
+} DecodePushData;
+
+typedef struct TileData {
+    int32_t pos[2];
+    uint32_t offset;
+    uint32_t size;
+} TileData;
+
+static int vk_prores_raw_start_frame(AVCodecContext          *avctx,
+                                     const AVBufferRef       *buffer_ref,
+                                     av_unused const uint8_t *buffer,
+                                     av_unused uint32_t       size)
+{
+    int err;
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+    ProResRAWVulkanDecodeContext *prv = ctx->sd_ctx;
+    ProResRAWContext *prr = avctx->priv_data;
+
+    ProResRAWVulkanDecodePicture *pp = prr->hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &pp->vp;
+
+    /* Host map the input tile data if supported */
+    if (ctx->s.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY)
+        ff_vk_host_map_buffer(&ctx->s, &vp->slices_buf, buffer_ref->data,
+                              buffer_ref,
+                              VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
+                              VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
+
+    /* Allocate tile data */
+    err = ff_vk_get_pooled_buffer(&ctx->s, &prv->tile_data_pool,
+                                  &pp->tile_data,
+                                  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
+                                  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
+                                  NULL, prr->nb_tiles*sizeof(TileData),
+                                  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+                                  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
+    if (err < 0)
+        return err;
+
+    /* Prepare frame to be used */
+    err = ff_vk_decode_prepare_frame_sdr(dec, prr->frame, vp, 1,
+                                         FF_VK_REP_FLOAT, 0);
+    if (err < 0)
+        return err;
+
+    return 0;
+}
+
+static int vk_prores_raw_decode_slice(AVCodecContext *avctx,
+                                      const uint8_t  *data,
+                                      uint32_t        size)
+{
+    ProResRAWContext *prr = avctx->priv_data;
+
+    ProResRAWVulkanDecodePicture *pp = prr->hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &pp->vp;
+
+    FFVkBuffer *tile_data_buf = (FFVkBuffer *)pp->tile_data->data;
+    TileData *td = (TileData *)tile_data_buf->mapped_mem;
+    FFVkBuffer *slices_buf = vp->slices_buf ? (FFVkBuffer *)vp->slices_buf->data : NULL;
+
+    td[pp->nb_tiles].pos[0] = prr->tiles[pp->nb_tiles].x;
+    td[pp->nb_tiles].pos[1] = prr->tiles[pp->nb_tiles].y;
+    td[pp->nb_tiles].size = size;
+
+    if (vp->slices_buf && slices_buf->host_ref) {
+        td[pp->nb_tiles].offset = data - slices_buf->mapped_mem;
+        pp->nb_tiles++;
+    } else {
+        int err;
+        td[pp->nb_tiles].offset = vp->slices_size;
+        err = ff_vk_decode_add_slice(avctx, vp, data, size, 0,
+                                     &pp->nb_tiles, NULL);
+        if (err < 0)
+            return err;
+    }
+
+    return 0;
+}
+
+static int vk_prores_raw_end_frame(AVCodecContext *avctx)
+{
+    int err;
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+    FFVulkanFunctions *vk = &ctx->s.vkfn;
+
+    ProResRAWContext *prr = avctx->priv_data;
+    ProResRAWVulkanDecodeContext *prv = ctx->sd_ctx;
+
+    ProResRAWVulkanDecodePicture *pp = prr->hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &pp->vp;
+
+    FFVkBuffer *slices_buf = (FFVkBuffer *)vp->slices_buf->data;
+    FFVkBuffer *tile_data = (FFVkBuffer *)pp->tile_data->data;
+
+    VkImageMemoryBarrier2 img_bar[8];
+    int nb_img_bar = 0;
+
+    FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
+    ff_vk_exec_start(&ctx->s, exec);
+
+    /* Prepare deps */
+    RET(ff_vk_exec_add_dep_frame(&ctx->s, exec, prr->frame,
+                                 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                                 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
+
+    err = ff_vk_exec_mirror_sem_value(&ctx->s, exec, &vp->sem, &vp->sem_value,
+                                      prr->frame);
+    if (err < 0)
+        return err;
+
+    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &pp->tile_data, 1, 0));
+    pp->tile_data = NULL;
+    RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0));
+    vp->slices_buf = NULL;
+
+    ff_vk_frame_barrier(&ctx->s, exec, prr->frame, img_bar, &nb_img_bar,
+                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                        VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+                        VK_ACCESS_2_TRANSFER_WRITE_BIT,
+                        VK_IMAGE_LAYOUT_GENERAL,
+                        VK_QUEUE_FAMILY_IGNORED);
+
+    vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+        .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+        .pImageMemoryBarriers = img_bar,
+        .imageMemoryBarrierCount = nb_img_bar,
+    });
+    nb_img_bar = 0;
+
+    FFVulkanShader *decode_shader = &prv->decode[prr->version];
+    ff_vk_shader_update_img_array(&ctx->s, exec, decode_shader,
+                                  prr->frame, vp->view.out,
+                                  0, 0,
+                                  VK_IMAGE_LAYOUT_GENERAL,
+                                  VK_NULL_HANDLE);
+
+    ff_vk_exec_bind_shader(&ctx->s, exec, decode_shader);
+
+    /* Update push data */
+    DecodePushData pd_decode = (DecodePushData) {
+        .tile_data = tile_data->address,
+        .pkt_data = slices_buf->address,
+        .frame_size[0] = avctx->width,
+        .frame_size[1] = avctx->height,
+        .tile_size[0] = prr->tw,
+        .tile_size[1] = prr->th,
+    };
+    memcpy(pd_decode.qmat, prr->qmat, 64);
+    ff_vk_shader_update_push_const(&ctx->s, exec, decode_shader,
+                                   VK_SHADER_STAGE_COMPUTE_BIT,
+                                   0, sizeof(pd_decode), &pd_decode);
+
+    vk->CmdDispatch(exec->buf, prr->nb_tw, prr->nb_th, 1);
+
+    err = ff_vk_exec_submit(&ctx->s, exec);
+    if (err < 0)
+        return err;
+
+fail:
+    return 0;
+}
+
+static int init_decode_shader(ProResRAWContext *prr, FFVulkanContext *s,
+                              FFVkExecPool *pool, FFVkSPIRVCompiler *spv,
+                              FFVulkanShader *shd, int version)
+{
+    int err;
+    FFVulkanDescriptorSetBinding *desc_set;
+    int parallel_rows = 1;
+
+    uint8_t *spv_data;
+    size_t spv_len;
+    void *spv_opaque = NULL;
+
+    if (s->props.properties.limits.maxComputeWorkGroupInvocations < 512 ||
+        s->props.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
+        parallel_rows = 0;
+
+    RET(ff_vk_shader_init(s, shd, "prores_raw",
+                          VK_SHADER_STAGE_COMPUTE_BIT,
+                          (const char *[]) { "GL_EXT_buffer_reference",
+                                             "GL_EXT_buffer_reference2",
+                                             "GL_EXT_null_initializer" }, 3,
+                          parallel_rows ? 8 : 1 /* 8x8 transforms, 8-point width */,
+                          version == 0 ? 8 : 16 /* Horizontal blocks */,
+                          4 /* Components */,
+                          0));
+
+    if (parallel_rows)
+        GLSLC(0, #define PARALLEL_ROWS                                               );
+
+    /* Common codec header */
+    GLSLD(ff_source_common_comp);
+
+    GLSLC(0, layout(buffer_reference, buffer_reference_align = 16) buffer TileData { );
+    GLSLC(1,    ivec2 pos;                                                           );
+    GLSLC(1,    uint offset;                                                         );
+    GLSLC(1,    uint size;                                                           );
+    GLSLC(0, };                                                                      );
+    GLSLC(0,                                                                         );
+    GLSLC(0, layout(push_constant, scalar) uniform pushConstants {                   );
+    GLSLC(1,    TileData tile_data;                                                  );
+    GLSLC(1,    u8buf pkt_data;                                                      );
+    GLSLC(1,    uvec2 frame_size;                                                    );
+    GLSLC(1,    uvec2 tile_size;                                                     );
+    GLSLC(1,    uint8_t qmat[64];                                                    );
+    GLSLC(0, };                                                                      );
+    GLSLC(0,                                                                         );
+    ff_vk_shader_add_push_const(shd, 0, sizeof(DecodePushData),
+                                VK_SHADER_STAGE_COMPUTE_BIT);
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name       = "dst",
+            .type       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+            .mem_layout = "r16",
+            .mem_quali  = "writeonly",
+            .dimensions = 2,
+            .stages     = VK_SHADER_STAGE_COMPUTE_BIT,
+        },
+    };
+    RET(ff_vk_shader_add_descriptor_set(s, shd, desc_set, 1, 0, 0));
+
+    desc_set = (FFVulkanDescriptorSetBinding []) {
+        {
+            .name        = "dct_scale_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "float idct_8x8_scales[64];",
+        },
+        {
+            .name        = "scan_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "uint8_t scan[64];",
+        },
+        {
+            .name        = "dc_cb_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "uint8_t dc_cb[13];",
+        },
+        {
+            .name        = "ac_cb_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "int16_t ac_cb[95];",
+        },
+        {
+            .name        = "rn_cb_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "int16_t rn_cb[28];",
+        },
+        {
+            .name        = "ln_cb_buf",
+            .type        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+            .stages      = VK_SHADER_STAGE_COMPUTE_BIT,
+            .mem_layout  = "scalar",
+            .buf_content = "int16_t ln_cb[15];",
+        },
+    };
+    RET(ff_vk_shader_add_descriptor_set(s, shd, desc_set, 6, 1, 0));
+
+    GLSLD(ff_source_prores_raw_comp);
+
+    RET(spv->compile_shader(s, spv, shd, &spv_data, &spv_len, "main",
+                            &spv_opaque));
+    RET(ff_vk_shader_link(s, shd, spv_data, spv_len, "main"));
+
+    RET(ff_vk_shader_register_exec(s, pool, shd));
+
+fail:
+    if (spv_opaque)
+        spv->free_shader(spv, &spv_opaque);
+
+    return err;
+}
+
+static void vk_decode_prores_raw_uninit(FFVulkanDecodeShared *ctx)
+{
+    ProResRAWVulkanDecodeContext *fv = ctx->sd_ctx;
+
+    ff_vk_shader_free(&ctx->s, &fv->decode[0]);
+    ff_vk_shader_free(&ctx->s, &fv->decode[1]);
+
+    ff_vk_free_buf(&ctx->s, &fv->uniform_buf);
+
+    av_buffer_pool_uninit(&fv->tile_data_pool);
+
+    av_freep(&fv);
+}
+
+static int vk_decode_prores_raw_init(AVCodecContext *avctx)
+{
+    int err;
+    ProResRAWContext *prr = avctx->priv_data;
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+
+    FFVkSPIRVCompiler *spv = ff_vk_spirv_init();
+    if (!spv) {
+        av_log(avctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    err = ff_vk_decode_init(avctx);
+    if (err < 0)
+        return err;
+
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+    ProResRAWVulkanDecodeContext *prv = ctx->sd_ctx = av_mallocz(sizeof(*prv));
+    if (!prv) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    ctx->sd_ctx_free = &vk_decode_prores_raw_uninit;
+
+    /* Setup decode shader */
+    RET(init_decode_shader(prr, &ctx->s, &ctx->exec_pool, spv, &prv->decode[0], 0));
+    RET(init_decode_shader(prr, &ctx->s, &ctx->exec_pool, spv, &prv->decode[1], 1));
+
+    /* Size in bytes of each codebook table */
+    size_t cb_size[5] = {
+        13*sizeof(uint8_t),
+        95*sizeof(int16_t),
+        28*sizeof(int16_t),
+        15*sizeof(int16_t),
+    };
+
+    /* Offset of each codebook table */
+    size_t cb_offset[5];
+    size_t ua = ctx->s.props.properties.limits.minUniformBufferOffsetAlignment;
+    cb_offset[0] = 64*sizeof(float) + 64*sizeof(uint8_t);
+    cb_offset[1] = cb_offset[0] + FFALIGN(cb_size[0], ua);
+    cb_offset[2] = cb_offset[1] + FFALIGN(cb_size[1], ua);
+    cb_offset[3] = cb_offset[2] + FFALIGN(cb_size[2], ua);
+    cb_offset[4] = cb_offset[3] + FFALIGN(cb_size[3], ua);
+
+    RET(ff_vk_create_buf(&ctx->s, &prv->uniform_buf,
+                         64*sizeof(float) + 64*sizeof(uint8_t) + cb_offset[4] + 256,
+                         NULL, NULL,
+                         VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
+                         VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+                         VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+                         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
+
+    uint8_t *uniform_buf;
+    RET(ff_vk_map_buffer(&ctx->s, &prv->uniform_buf, &uniform_buf, 0));
+
+    /* DCT scales */
+    float *dct_scale_buf = (float *)uniform_buf;
+    double idct_8_scales[8] = {
+        cos(4.0*M_PI/16.0) / 2.0,
+        cos(1.0*M_PI/16.0) / 2.0,
+        cos(2.0*M_PI/16.0) / 2.0,
+        cos(3.0*M_PI/16.0) / 2.0,
+        cos(4.0*M_PI/16.0) / 2.0,
+        cos(5.0*M_PI/16.0) / 2.0,
+        cos(6.0*M_PI/16.0) / 2.0,
+        cos(7.0*M_PI/16.0) / 2.0,
+    };
+    for (int i = 0; i < 64; i++)
+        dct_scale_buf[i] = (float)(idct_8_scales[i >> 3] *
+                                   idct_8_scales[i  & 7]);
+
+    /* Scan table */
+    uint8_t *scan_buf = uniform_buf + 64*sizeof(float);
+    for (int i = 0; i < 64; i++)
+        scan_buf[prr->scan[i]] = i;
+
+    /* Codebooks */
+    memcpy(uniform_buf + cb_offset[0], ff_prores_raw_dc_cb,
+           sizeof(ff_prores_raw_dc_cb));
+    memcpy(uniform_buf + cb_offset[1], ff_prores_raw_ac_cb,
+           sizeof(ff_prores_raw_ac_cb));
+    memcpy(uniform_buf + cb_offset[2], ff_prores_raw_rn_cb,
+           sizeof(ff_prores_raw_rn_cb));
+    memcpy(uniform_buf + cb_offset[3], ff_prores_raw_ln_cb,
+           sizeof(ff_prores_raw_ln_cb));
+
+    RET(ff_vk_unmap_buffer(&ctx->s, &prv->uniform_buf, 1));
+
+    /* Done; update descriptors */
+    for (int i = 0; i < 2; i++) {
+        RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
+                                            &prv->decode[i], 1, 0, 0,
+                                            &prv->uniform_buf,
+                                            0, 64*sizeof(float),
+                                            VK_FORMAT_UNDEFINED));
+        RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
+                                            &prv->decode[i], 1, 1, 0,
+                                            &prv->uniform_buf,
+                                            64*sizeof(float), 64*sizeof(uint8_t),
+                                            VK_FORMAT_UNDEFINED));
+        for (int j = 0; j < 4; j++)
+            RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
+                                                &prv->decode[i], 1, 2 + j, 0,
+                                                &prv->uniform_buf,
+                                                cb_offset[j], cb_size[j],
+                                                VK_FORMAT_UNDEFINED));
+    }
+
+fail:
+    spv->uninit(&spv);
+
+    return err;
+}
+
+static void vk_prores_raw_free_frame_priv(AVRefStructOpaque _hwctx, void *data)
+{
+    AVHWDeviceContext *dev_ctx = _hwctx.nc;
+
+    ProResRAWVulkanDecodePicture *pp = data;
+    FFVulkanDecodePicture *vp = &pp->vp;
+
+    ff_vk_decode_free_frame(dev_ctx, vp);
+}
+
+const FFHWAccel ff_prores_raw_vulkan_hwaccel = {
+    .p.name                = "prores_raw_vulkan",
+    .p.type                = AVMEDIA_TYPE_VIDEO,
+    .p.id                  = AV_CODEC_ID_PRORES_RAW,
+    .p.pix_fmt             = AV_PIX_FMT_VULKAN,
+    .start_frame           = &vk_prores_raw_start_frame,
+    .decode_slice          = &vk_prores_raw_decode_slice,
+    .end_frame             = &vk_prores_raw_end_frame,
+    .free_frame_priv       = &vk_prores_raw_free_frame_priv,
+    .frame_priv_data_size  = sizeof(ProResRAWVulkanDecodePicture),
+    .init                  = &vk_decode_prores_raw_init,
+    .update_thread_context = &ff_vk_update_thread_context,
+    .decode_params         = &ff_vk_params_invalidate,
+    .flush                 = &ff_vk_decode_flush,
+    .uninit                = &ff_vk_decode_uninit,
+    .frame_params          = &ff_vk_frame_params,
+    .priv_data_size        = sizeof(FFVulkanDecodeContext),
+    .caps_internal         = HWACCEL_CAP_ASYNC_SAFE | HWACCEL_CAP_THREAD_SAFE,
+};
-- 
2.49.1


From 6497f35b2ba497b088d1766e95dd0de61a01835a Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:40:21 +0000
Subject: [PATCH 087/118] Changing vulkan file directory

---
 libavcodec/vulkan/vulkan_source.c | 2242 +++++++++++++++++++++++++++++
 1 file changed, 2242 insertions(+)
 create mode 100644 libavcodec/vulkan/vulkan_source.c

diff --git a/libavcodec/vulkan/vulkan_source.c b/libavcodec/vulkan/vulkan_source.c
new file mode 100644
index 0000000000..17a60e4b0f
--- /dev/null
+++ b/libavcodec/vulkan/vulkan_source.c
@@ -0,0 +1,2242 @@
+#include <stddef.h>
+#include "vulkan_source.h"
+
+const char *ff_source_common_comp = "\
+layout(buffer_reference, buffer_reference_align = 1) buffer u8buf {\n\
+    uint8_t v;\n\
+};\n\
+\n\
+layout(buffer_reference, buffer_reference_align = 1) buffer u8vec2buf {\n\
+    u8vec2 v;\n\
+};\n\
+\n\
+layout(buffer_reference, buffer_reference_align = 1) buffer u8vec4buf {\n\
+    u8vec4 v;\n\
+};\n\
+\n\
+layout(buffer_reference, buffer_reference_align = 2) buffer u16buf {\n\
+    uint16_t v;\n\
+};\n\
+\n\
+layout(buffer_reference, buffer_reference_align = 4) buffer u32buf {\n\
+    uint32_t v;\n\
+};\n\
+\n\
+layout(buffer_reference, buffer_reference_align = 4) buffer u32vec2buf {\n\
+    u32vec2 v;\n\
+};\n\
+\n\
+layout(buffer_reference, buffer_reference_align = 8) buffer u64buf {\n\
+    uint64_t v;\n\
+};\n\
+\n\
+#define OFFBUF(type, b, l) \\\n\
+    type(uint64_t(b) + uint64_t(l))\n\
+\n\
+#define zero_extend(a, p) \\\n\
+    ((a) & ((1 << (p)) - 1))\n\
+\n\
+#define sign_extend(val, bits) \\\n\
+    bitfieldExtract(val, 0, bits)\n\
+\n\
+#define fold(diff, bits) \\\n\
+    sign_extend(diff, bits)\n\
+\n\
+#define mid_pred(a, b, c) \\\n\
+    max(min((a), (b)), min(max((a), (b)), (c)))\n\
+\n\
+/* TODO: optimize */\n\
+uint align(uint src, uint a)\n\
+{\n\
+    uint res = src % a;\n\
+    if (res == 0)\n\
+        return src;\n\
+    return src + a - res;\n\
+}\n\
+\n\
+/* TODO: optimize */\n\
+uint64_t align64(uint64_t src, uint64_t a)\n\
+{\n\
+    uint64_t res = src % a;\n\
+    if (res == 0)\n\
+        return src;\n\
+    return src + a - res;\n\
+}\n\
+\n\
+#define reverse4(src) \\\n\
+    (pack32(unpack8(uint32_t(src)).wzyx))\n\
+\n\
+u32vec2 reverse8(uint64_t src)\n\
+{\n\
+    u32vec2 tmp = unpack32(src);\n\
+    tmp.x = reverse4(tmp.x);\n\
+    tmp.y = reverse4(tmp.y);\n\
+    return tmp.yx;\n\
+}\n\
+\n\
+#ifdef PB_32\n\
+#define BIT_BUF_TYPE uint32_t\n\
+#define BUF_TYPE u32buf\n\
+#define BUF_REVERSE(src) reverse4(src)\n\
+#define BUF_BITS uint8_t(32)\n\
+#define BUF_BYTES uint8_t(4)\n\
+#define BYTE_EXTRACT(src, byte_off) \\\n\
+    (uint8_t(bitfieldExtract((src), ((byte_off) << 3), 8)))\n\
+#else\n\
+#define BIT_BUF_TYPE uint64_t\n\
+#define BUF_TYPE u32vec2buf\n\
+#define BUF_REVERSE(src) reverse8(src)\n\
+#define BUF_BITS uint8_t(64)\n\
+#define BUF_BYTES uint8_t(8)\n\
+#define BYTE_EXTRACT(src, byte_off) \\\n\
+    (uint8_t(((src) >> ((byte_off) << 3)) & 0xFF))\n\
+#endif\n\
+\n\
+struct PutBitContext {\n\
+    uint64_t buf_start;\n\
+    uint64_t buf;\n\
+\n\
+    BIT_BUF_TYPE bit_buf;\n\
+    uint8_t bit_left;\n\
+};\n\
+\n\
+void put_bits(inout PutBitContext pb, const uint32_t n, uint32_t value)\n\
+{\n\
+    if (n < pb.bit_left) {\n\
+        pb.bit_buf = (pb.bit_buf << n) | value;\n\
+        pb.bit_left -= uint8_t(n);\n\
+    } else {\n\
+        pb.bit_buf <<= pb.bit_left;\n\
+        pb.bit_buf |= (value >> (n - pb.bit_left));\n\
+\n\
+#ifdef PB_UNALIGNED\n\
+        u8buf bs = u8buf(pb.buf);\n\
+        [[unroll]]\n\
+        for (uint8_t i = uint8_t(0); i < BUF_BYTES; i++)\n\
+            bs[i].v = BYTE_EXTRACT(pb.bit_buf, BUF_BYTES - uint8_t(1) - i);\n\
+#else\n\
+#ifdef DEBUG\n\
+        if ((pb.buf % BUF_BYTES) != 0)\n\
+            debugPrintfEXT(\"put_bits buffer is not aligned!\");\n\
+#endif\n\
+\n\
+        BUF_TYPE bs = BUF_TYPE(pb.buf);\n\
+        bs.v = BUF_REVERSE(pb.bit_buf);\n\
+#endif\n\
+        pb.buf = uint64_t(bs) + BUF_BYTES;\n\
+\n\
+        pb.bit_left += BUF_BITS - uint8_t(n);\n\
+        pb.bit_buf = value;\n\
+    }\n\
+}\n\
+\n\
+uint32_t flush_put_bits(inout PutBitContext pb)\n\
+{\n\
+    /* Align bits to MSBs */\n\
+    if (pb.bit_left < BUF_BITS)\n\
+        pb.bit_buf <<= pb.bit_left;\n\
+\n\
+    if (pb.bit_left < BUF_BITS) {\n\
+        uint to_write = ((BUF_BITS - pb.bit_left - 1) >> 3) + 1;\n\
+\n\
+        u8buf bs = u8buf(pb.buf);\n\
+        for (int i = 0; i < to_write; i++)\n\
+            bs[i].v = BYTE_EXTRACT(pb.bit_buf, BUF_BYTES - uint8_t(1) - i);\n\
+        pb.buf = uint64_t(bs) + to_write;\n\
+    }\n\
+\n\
+    pb.bit_left = BUF_BITS;\n\
+    pb.bit_buf = 0x0;\n\
+\n\
+    return uint32_t(pb.buf - pb.buf_start);\n\
+}\n\
+\n\
+void init_put_bits(out PutBitContext pb, u8buf data, uint64_t len)\n\
+{\n\
+    pb.buf_start = uint64_t(data);\n\
+    pb.buf = uint64_t(data);\n\
+\n\
+    pb.bit_buf = 0;\n\
+    pb.bit_left = BUF_BITS;\n\
+}\n\
+\n\
+uint64_t put_bits_count(in PutBitContext pb)\n\
+{\n\
+    return (pb.buf - pb.buf_start)*8 + BUF_BITS - pb.bit_left;\n\
+}\n\
+\n\
+uint32_t put_bytes_count(in PutBitContext pb)\n\
+{\n\
+    uint64_t num_bytes = (pb.buf - pb.buf_start) + ((BUF_BITS - pb.bit_left) >> 3);\n\
+    return uint32_t(num_bytes);\n\
+}\n\
+\n\
+struct GetBitContext {\n\
+    uint64_t buf_start;\n\
+    uint64_t buf;\n\
+    uint64_t buf_end;\n\
+\n\
+    uint64_t bits;\n\
+    int bits_valid;\n\
+    int size_in_bits;\n\
+};\n\
+\n\
+#define LOAD64()                                       \\\n\
+    {                                                  \\\n\
+        u8vec4buf ptr = u8vec4buf(gb.buf);             \\\n\
+        uint32_t rf1 = pack32((ptr[0].v).wzyx);        \\\n\
+        uint32_t rf2 = pack32((ptr[1].v).wzyx);        \\\n\
+        gb.buf += 8;                                   \\\n\
+        gb.bits = uint64_t(rf1) << 32 | uint64_t(rf2); \\\n\
+        gb.bits_valid = 64;                            \\\n\
+    }\n\
+\n\
+#define RELOAD32()                                                \\\n\
+    {                                                             \\\n\
+        u8vec4buf ptr = u8vec4buf(gb.buf);                        \\\n\
+        uint32_t rf = pack32((ptr[0].v).wzyx);                    \\\n\
+        gb.buf += 4;                                              \\\n\
+        gb.bits = uint64_t(rf) << (32 - gb.bits_valid) | gb.bits; \\\n\
+        gb.bits_valid += 32;                                      \\\n\
+    }\n\
+\n\
+void init_get_bits(inout GetBitContext gb, u8buf data, int len)\n\
+{\n\
+    gb.buf = gb.buf_start = uint64_t(data);\n\
+    gb.buf_end = uint64_t(data) + len;\n\
+    gb.size_in_bits = len * 8;\n\
+\n\
+    /* Preload */\n\
+    LOAD64()\n\
+}\n\
+\n\
+bool get_bit(inout GetBitContext gb)\n\
+{\n\
+    if (gb.bits_valid == 0)\n\
+        LOAD64()\n\
+\n\
+    bool val = bool(gb.bits >> (64 - 1));\n\
+    gb.bits <<= 1;\n\
+    gb.bits_valid--;\n\
+    return val;\n\
+}\n\
+\n\
+uint get_bits(inout GetBitContext gb, int n)\n\
+{\n\
+    if (n == 0)\n\
+        return 0;\n\
+\n\
+    if (n > gb.bits_valid)\n\
+        RELOAD32()\n\
+\n\
+    uint val = uint(gb.bits >> (64 - n));\n\
+    gb.bits <<= n;\n\
+    gb.bits_valid -= n;\n\
+    return val;\n\
+}\n\
+\n\
+uint show_bits(inout GetBitContext gb, int n)\n\
+{\n\
+    if (n > gb.bits_valid)\n\
+        RELOAD32()\n\
+\n\
+    return uint(gb.bits >> (64 - n));\n\
+}\n\
+\n\
+void skip_bits(inout GetBitContext gb, int n)\n\
+{\n\
+    if (n > gb.bits_valid)\n\
+        RELOAD32()\n\
+\n\
+    gb.bits <<= n;\n\
+    gb.bits_valid -= n;\n\
+}\n\
+\n\
+int tell_bits(in GetBitContext gb)\n\
+{\n\
+    return int(gb.buf - gb.buf_start) * 8 - gb.bits_valid;\n\
+}\n\
+\n\
+int left_bits(in GetBitContext gb)\n\
+{\n\
+    return gb.size_in_bits - int(gb.buf - gb.buf_start) * 8 + gb.bits_valid;\n\
+}";
+
+const char *ff_source_rangecoder_comp = "\
+struct RangeCoder {\n\
+    uint64_t bytestream_start;\n\
+    uint64_t bytestream;\n\
+    uint64_t bytestream_end;\n\
+\n\
+    int low;\n\
+    int range;\n\
+    uint16_t outstanding_count;\n\
+    uint8_t outstanding_byte;\n\
+};\n\
+\n\
+#ifdef FULL_RENORM\n\
+/* Full renorm version that can handle outstanding_byte == 0xFF */\n\
+void renorm_encoder(inout RangeCoder c)\n\
+{\n\
+    int bs_cnt = 0;\n\
+    u8buf bytestream = u8buf(c.bytestream);\n\
+\n\
+    if (c.outstanding_byte == 0xFF) {\n\
+        c.outstanding_byte = uint8_t(c.low >> 8);\n\
+    } else if (c.low <= 0xFF00) {\n\
+        bytestream[bs_cnt++].v = c.outstanding_byte;\n\
+        uint16_t cnt = c.outstanding_count;\n\
+        for (; cnt > 0; cnt--)\n\
+            bytestream[bs_cnt++].v = uint8_t(0xFF);\n\
+        c.outstanding_count = uint16_t(0);\n\
+        c.outstanding_byte = uint8_t(c.low >> 8);\n\
+    } else if (c.low >= 0x10000) {\n\
+        bytestream[bs_cnt++].v = c.outstanding_byte + uint8_t(1);\n\
+        uint16_t cnt = c.outstanding_count;\n\
+        for (; cnt > 0; cnt--)\n\
+            bytestream[bs_cnt++].v = uint8_t(0x00);\n\
+        c.outstanding_count = uint16_t(0);\n\
+        c.outstanding_byte = uint8_t(bitfieldExtract(c.low, 8, 8));\n\
+    } else {\n\
+        c.outstanding_count++;\n\
+    }\n\
+\n\
+    c.bytestream += bs_cnt;\n\
+    c.range <<= 8;\n\
+    c.low = bitfieldInsert(0, c.low, 8, 8);\n\
+}\n\
+\n\
+#else\n\
+\n\
+/* Cannot deal with outstanding_byte == -1 in the name of speed */\n\
+void renorm_encoder(inout RangeCoder c)\n\
+{\n\
+    uint16_t oc = c.outstanding_count + uint16_t(1);\n\
+    int low = c.low;\n\
+\n\
+    c.range <<= 8;\n\
+    c.low = bitfieldInsert(0, low, 8, 8);\n\
+\n\
+    if (low > 0xFF00 && low < 0x10000) {\n\
+        c.outstanding_count = oc;\n\
+        return;\n\
+    }\n\
+\n\
+    u8buf bs = u8buf(c.bytestream);\n\
+    uint8_t outstanding_byte = c.outstanding_byte;\n\
+\n\
+    c.bytestream        = uint64_t(bs) + oc;\n\
+    c.outstanding_count = uint16_t(0);\n\
+    c.outstanding_byte  = uint8_t(low >> 8);\n\
+\n\
+    uint8_t obs = uint8_t(low > 0xFF00);\n\
+    uint8_t fill = obs - uint8_t(1); /* unsigned underflow */\n\
+\n\
+    bs[0].v = outstanding_byte + obs;\n\
+    for (int i = 1; i < oc; i++)\n\
+        bs[i].v = fill;\n\
+}\n\
+#endif\n\
+\n\
+void put_rac_internal(inout RangeCoder c, const int range1, bool bit)\n\
+{\n\
+#ifdef DEBUG\n\
+    if (range1 >= c.range)\n\
+        debugPrintfEXT(\"Error: range1 >= c.range\");\n\
+    if (range1 <= 0)\n\
+        debugPrintfEXT(\"Error: range1 <= 0\");\n\
+#endif\n\
+\n\
+    int ranged = c.range - range1;\n\
+    c.low += bit ? ranged : 0;\n\
+    c.range = bit ? range1 : ranged;\n\
+\n\
+    if (expectEXT(c.range < 0x100, false))\n\
+        renorm_encoder(c);\n\
+}\n\
+\n\
+void put_rac_direct(inout RangeCoder c, inout uint8_t state, bool bit)\n\
+{\n\
+    put_rac_internal(c, (c.range * state) >> 8, bit);\n\
+    state = zero_one_state[(uint(bit) << 8) + state];\n\
+}\n\
+\n\
+void put_rac(inout RangeCoder c, uint64_t state, bool bit)\n\
+{\n\
+    put_rac_direct(c, u8buf(state).v, bit);\n\
+}\n\
+\n\
+/* Equiprobable bit */\n\
+void put_rac_equi(inout RangeCoder c, bool bit)\n\
+{\n\
+    put_rac_internal(c, c.range >> 1, bit);\n\
+}\n\
+\n\
+void put_rac_terminate(inout RangeCoder c)\n\
+{\n\
+    int range1 = (c.range * 129) >> 8;\n\
+\n\
+#ifdef DEBUG\n\
+    if (range1 >= c.range)\n\
+        debugPrintfEXT(\"Error: range1 >= c.range\");\n\
+    if (range1 <= 0)\n\
+        debugPrintfEXT(\"Error: range1 <= 0\");\n\
+#endif\n\
+\n\
+    c.range -= range1;\n\
+    if (expectEXT(c.range < 0x100, false))\n\
+        renorm_encoder(c);\n\
+}\n\
+\n\
+/* Return the number of bytes written. */\n\
+uint32_t rac_terminate(inout RangeCoder c)\n\
+{\n\
+    put_rac_terminate(c);\n\
+    c.range = uint16_t(0xFF);\n\
+    c.low  += 0xFF;\n\
+    renorm_encoder(c);\n\
+    c.range = uint16_t(0xFF);\n\
+    renorm_encoder(c);\n\
+\n\
+#ifdef DEBUG\n\
+    if (c.low != 0)\n\
+        debugPrintfEXT(\"Error: c.low != 0\");\n\
+    if (c.range < 0x100)\n\
+        debugPrintfEXT(\"Error: range < 0x100\");\n\
+#endif\n\
+\n\
+    return uint32_t(uint64_t(c.bytestream) - uint64_t(c.bytestream_start));\n\
+}\n\
+\n\
+void rac_init(out RangeCoder r, u8buf data, uint buf_size)\n\
+{\n\
+    r.bytestream_start = uint64_t(data);\n\
+    r.bytestream = uint64_t(data);\n\
+    r.bytestream_end = uint64_t(data) + buf_size;\n\
+    r.low = 0;\n\
+    r.range = 0xFF00;\n\
+    r.outstanding_count = uint16_t(0);\n\
+    r.outstanding_byte = uint8_t(0xFF);\n\
+}\n\
+\n\
+/* Decoder */\n\
+uint overread = 0;\n\
+bool corrupt = false;\n\
+\n\
+void rac_init_dec(out RangeCoder r, u8buf data, uint buf_size)\n\
+{\n\
+    overread = 0;\n\
+    corrupt = false;\n\
+\n\
+    /* Skip priming bytes */\n\
+    rac_init(r, OFFBUF(u8buf, data, 2), buf_size - 2);\n\
+\n\
+    u8vec2 prime = u8vec2buf(data).v;\n\
+    /* Switch endianness of the priming bytes */\n\
+    r.low = pack16(prime.yx);\n\
+\n\
+    if (r.low >= 0xFF00) {\n\
+        r.low = 0xFF00;\n\
+        r.bytestream_end = uint64_t(data) + 2;\n\
+    }\n\
+}\n\
+\n\
+void refill(inout RangeCoder c)\n\
+{\n\
+    c.range <<= 8;\n\
+    c.low   <<= 8;\n\
+    if (expectEXT(c.bytestream < c.bytestream_end, false)) {\n\
+        c.low |= u8buf(c.bytestream).v;\n\
+        c.bytestream++;\n\
+    } else {\n\
+        overread++;\n\
+    }\n\
+}\n\
+\n\
+bool get_rac_internal(inout RangeCoder c, const int range1)\n\
+{\n\
+    int ranged = c.range - range1;\n\
+    bool bit = c.low >= ranged;\n\
+    c.low -= bit ? ranged : 0;\n\
+    c.range = (bit ? 0 : ranged) + (bit ? range1 : 0);\n\
+\n\
+    if (expectEXT(c.range < 0x100, false))\n\
+        refill(c);\n\
+\n\
+    return bit;\n\
+}\n\
+\n\
+bool get_rac_direct(inout RangeCoder c, inout uint8_t state)\n\
+{\n\
+    bool bit = get_rac_internal(c, c.range * state >> 8);\n\
+    state = zero_one_state[state + (bit ? 256 : 0)];\n\
+    return bit;\n\
+}\n\
+\n\
+bool get_rac(inout RangeCoder c, uint64_t state)\n\
+{\n\
+    return get_rac_direct(c, u8buf(state).v);\n\
+}\n\
+\n\
+bool get_rac_equi(inout RangeCoder c)\n\
+{\n\
+    return get_rac_internal(c, c.range >> 1);\n\
+}";
+
+const char *ff_source_ffv1_vlc_comp = "\
+#define VLC_STATE_SIZE 8\n\
+layout(buffer_reference, buffer_reference_align = VLC_STATE_SIZE) buffer VlcState {\n\
+    uint32_t error_sum;\n\
+    int16_t  drift;\n\
+    int8_t   bias;\n\
+    uint8_t  count;\n\
+};\n\
+\n\
+void update_vlc_state(inout VlcState state, const int v)\n\
+{\n\
+    int drift = state.drift;\n\
+    int count = state.count;\n\
+    int bias = state.bias;\n\
+    state.error_sum += uint16_t(abs(v));\n\
+    drift           += v;\n\
+\n\
+    if (count == 128) { // FIXME: variable\n\
+        count           >>= 1;\n\
+        drift           >>= 1;\n\
+        state.error_sum >>= 1;\n\
+    }\n\
+    count++;\n\
+\n\
+    if (drift <= -count) {\n\
+        bias = max(bias - 1, -128);\n\
+        drift = max(drift + count, -count + 1);\n\
+    } else if (drift > 0) {\n\
+        bias = min(bias + 1, 127);\n\
+        drift = min(drift - count, 0);\n\
+    }\n\
+\n\
+    state.bias = int8_t(bias);\n\
+    state.drift = int16_t(drift);\n\
+    state.count = uint8_t(count);\n\
+}\n\
+\n\
+struct Symbol {\n\
+    uint32_t bits;\n\
+    uint32_t val;\n\
+};\n\
+\n\
+Symbol set_ur_golomb(int i, int k, int limit, int esc_len)\n\
+{\n\
+    int e;\n\
+    Symbol sym;\n\
+\n\
+#ifdef DEBUG\n\
+    if (i < 0)\n\
+        debugPrintfEXT(\"Error: i is zero!\");\n\
+#endif\n\
+\n\
+    e = i >> k;\n\
+    if (e < limit) {\n\
+        sym.bits = e + k + 1;\n\
+        sym.val = (1 << k) + zero_extend(i, k);\n\
+    } else {\n\
+        sym.bits = limit + esc_len;\n\
+        sym.val = i - limit + 1;\n\
+    }\n\
+\n\
+    return sym;\n\
+}\n\
+\n\
+/**\n\
+ * write signed golomb rice code (ffv1).\n\
+ */\n\
+Symbol set_sr_golomb(int i, int k, int limit, int esc_len)\n\
+{\n\
+    int v;\n\
+\n\
+    v  = -2 * i - 1;\n\
+    v ^= (v >> 31);\n\
+\n\
+    return set_ur_golomb(v, k, limit, esc_len);\n\
+}\n\
+\n\
+Symbol get_vlc_symbol(inout VlcState state, int v, int bits)\n\
+{\n\
+    int i, k, code;\n\
+    Symbol sym;\n\
+    v = fold(v - int(state.bias), bits);\n\
+\n\
+    i = state.count;\n\
+    k = 0;\n\
+    while (i < state.error_sum) { // FIXME: optimize\n\
+        k++;\n\
+        i += i;\n\
+    }\n\
+\n\
+#ifdef DEBUG\n\
+    if (k > 16)\n\
+        debugPrintfEXT(\"Error: k > 16!\");\n\
+#endif\n\
+\n\
+    code = v ^ ((2 * state.drift + state.count) >> 31);\n\
+\n\
+    update_vlc_state(state, v);\n\
+\n\
+    return set_sr_golomb(code, k, 12, bits);\n\
+}\n\
+\n\
+uint get_ur_golomb(inout GetBitContext gb, int k, int limit, int esc_len)\n\
+{\n\
+    for (uint i = 0; i < 12; i++)\n\
+        if (get_bit(gb))\n\
+            return get_bits(gb, k) + (i << k);\n\
+\n\
+    return get_bits(gb, esc_len) + 11;\n\
+}\n\
+\n\
+int get_sr_golomb(inout GetBitContext gb, int k, int limit, int esc_len)\n\
+{\n\
+    int v = int(get_ur_golomb(gb, k, limit, esc_len));\n\
+    return (v >> 1) ^ -(v & 1);\n\
+}\n\
+\n\
+int read_vlc_symbol(inout GetBitContext gb, inout VlcState state, int bits)\n\
+{\n\
+    int k, i, v, ret;\n\
+\n\
+    i = state.count;\n\
+    k = 0;\n\
+    while (i < state.error_sum) { // FIXME: optimize\n\
+        k++;\n\
+        i += i;\n\
+    }\n\
+\n\
+    v = get_sr_golomb(gb, k, 12, bits);\n\
+\n\
+    v ^= ((2 * state.drift + state.count) >> 31);\n\
+\n\
+    ret = fold(v + state.bias, bits);\n\
+\n\
+    update_vlc_state(state, v);\n\
+\n\
+    return ret;\n\
+}";
+
+const char *ff_source_ffv1_common_comp = "\
+struct SliceContext {\n\
+    RangeCoder c;\n\
+\n\
+#if !defined(DECODE)\n\
+    PutBitContext pb; /* 8*8 bytes */\n\
+#else\n\
+    GetBitContext gb;\n\
+#endif\n\
+\n\
+    ivec2 slice_dim;\n\
+    ivec2 slice_pos;\n\
+    ivec2 slice_rct_coef;\n\
+    u8vec3 quant_table_idx;\n\
+\n\
+    uint hdr_len; // only used for golomb\n\
+\n\
+    uint slice_coding_mode;\n\
+    bool slice_reset_contexts;\n\
+};\n\
+\n\
+/* -1, { -1, 0 } */\n\
+int predict(int L, ivec2 top)\n\
+{\n\
+    return mid_pred(L, L + top[1] - top[0], top[1]);\n\
+}\n\
+\n\
+/* { -2, -1 }, { -1, 0, 1 }, 0 */\n\
+int get_context(VTYPE2 cur_l, VTYPE3 top_l, TYPE top2, uint8_t quant_table_idx)\n\
+{\n\
+    const int LT = top_l[0]; /* -1 */\n\
+    const int T  = top_l[1]; /*  0 */\n\
+    const int RT = top_l[2]; /*  1 */\n\
+    const int L  = cur_l[1]; /* -1 */\n\
+\n\
+    int base = quant_table[quant_table_idx][0][(L - LT) & MAX_QUANT_TABLE_MASK] +\n\
+               quant_table[quant_table_idx][1][(LT - T) & MAX_QUANT_TABLE_MASK] +\n\
+               quant_table[quant_table_idx][2][(T - RT) & MAX_QUANT_TABLE_MASK];\n\
+\n\
+    if ((quant_table[quant_table_idx][3][127] == 0) &&\n\
+        (quant_table[quant_table_idx][4][127] == 0))\n\
+        return base;\n\
+\n\
+    const int TT = top2;     /* -2 */\n\
+    const int LL = cur_l[0]; /* -2 */\n\
+    return base +\n\
+           quant_table[quant_table_idx][3][(LL - L) & MAX_QUANT_TABLE_MASK] +\n\
+           quant_table[quant_table_idx][4][(TT - T) & MAX_QUANT_TABLE_MASK];\n\
+}\n\
+\n\
+const uint32_t log2_run[41] = {\n\
+     0,  0,  0,  0,  1,  1,  1,  1,\n\
+     2,  2,  2,  2,  3,  3,  3,  3,\n\
+     4,  4,  5,  5,  6,  6,  7,  7,\n\
+     8,  9, 10, 11, 12, 13, 14, 15,\n\
+    16, 17, 18, 19, 20, 21, 22, 23,\n\
+    24,\n\
+};\n\
+\n\
+uint slice_coord(uint width, uint sx, uint num_h_slices, uint chroma_shift)\n\
+{\n\
+    uint mpw = 1 << chroma_shift;\n\
+    uint awidth = align(width, mpw);\n\
+\n\
+    if ((version < 4) || ((version == 4) && (micro_version < 3)))\n\
+        return width * sx / num_h_slices;\n\
+\n\
+    sx = (2 * awidth * sx + num_h_slices * mpw) / (2 * num_h_slices * mpw) * mpw;\n\
+    if (sx == awidth)\n\
+        sx = width;\n\
+\n\
+    return sx;\n\
+}\n\
+\n\
+#ifdef RGB\n\
+#define RGB_LBUF (RGB_LINECACHE - 1)\n\
+#define LADDR(p) (ivec2((p).x, ((p).y & RGB_LBUF)))\n\
+\n\
+ivec2 get_pred(readonly uimage2D pred, ivec2 sp, ivec2 off,\n\
+               int comp, int sw, uint8_t quant_table_idx, bool extend_lookup)\n\
+{\n\
+    const ivec2 yoff_border1 = expectEXT(off.x == 0, false) ? off + ivec2(1, -1) : off;\n\
+\n\
+    /* Thanks to the same coincidence as below, we can skip checking if off == 0, 1 */\n\
+    VTYPE3 top  = VTYPE3(TYPE(imageLoad(pred, sp + LADDR(yoff_border1 + ivec2(-1, -1)))[comp]),\n\
+                         TYPE(imageLoad(pred, sp + LADDR(off + ivec2(0, -1)))[comp]),\n\
+                         TYPE(imageLoad(pred, sp + LADDR(off + ivec2(min(1, sw - off.x - 1), -1)))[comp]));\n\
+\n\
+    /* Normally, we'd need to check if off != ivec2(0, 0) here, since otherwise, we must\n\
+     * return zero. However, ivec2(-1,  0) + ivec2(1, -1) == ivec2(0, -1), e.g. previous\n\
+     * row, 0 offset, same slice, which is zero since we zero out the buffer for RGB */\n\
+    TYPE cur = TYPE(imageLoad(pred, sp + LADDR(yoff_border1 + ivec2(-1,  0)))[comp]);\n\
+\n\
+    int base = quant_table[quant_table_idx][0][(cur    - top[0]) & MAX_QUANT_TABLE_MASK] +\n\
+               quant_table[quant_table_idx][1][(top[0] - top[1]) & MAX_QUANT_TABLE_MASK] +\n\
+               quant_table[quant_table_idx][2][(top[1] - top[2]) & MAX_QUANT_TABLE_MASK];\n\
+\n\
+    if (expectEXT(extend_lookup, false)) {\n\
+        TYPE cur2 = TYPE(0);\n\
+        if (expectEXT(off.x > 0, true)) {\n\
+            const ivec2 yoff_border2 = expectEXT(off.x == 1, false) ? ivec2(-1, -1) : ivec2(-2, 0);\n\
+            cur2 = TYPE(imageLoad(pred, sp + LADDR(off + yoff_border2))[comp]);\n\
+        }\n\
+        base += quant_table[quant_table_idx][3][(cur2 - cur) & MAX_QUANT_TABLE_MASK];\n\
+\n\
+        /* top-2 became current upon swap */\n\
+        TYPE top2 = TYPE(imageLoad(pred, sp + LADDR(off))[comp]);\n\
+        base += quant_table[quant_table_idx][4][(top2 - top[1]) & MAX_QUANT_TABLE_MASK];\n\
+    }\n\
+\n\
+    /* context, prediction */\n\
+    return ivec2(base, predict(cur, VTYPE2(top)));\n\
+}\n\
+\n\
+#else /* RGB */\n\
+\n\
+#define LADDR(p) (p)\n\
+\n\
+ivec2 get_pred(readonly uimage2D pred, ivec2 sp, ivec2 off,\n\
+               int comp, int sw, uint8_t quant_table_idx, bool extend_lookup)\n\
+{\n\
+    const ivec2 yoff_border1 = off.x == 0 ? ivec2(1, -1) : ivec2(0, 0);\n\
+    sp += off;\n\
+\n\
+    VTYPE3 top  = VTYPE3(TYPE(0),\n\
+                         TYPE(0),\n\
+                         TYPE(0));\n\
+    if (off.y > 0 && off != ivec2(0, 1))\n\
+        top[0] = TYPE(imageLoad(pred, sp + ivec2(-1, -1) + yoff_border1)[comp]);\n\
+    if (off.y > 0) {\n\
+        top[1] = TYPE(imageLoad(pred, sp + ivec2(0, -1))[comp]);\n\
+        top[2] = TYPE(imageLoad(pred, sp + ivec2(min(1, sw - off.x - 1), -1))[comp]);\n\
+    }\n\
+\n\
+    TYPE cur = TYPE(0);\n\
+    if (off != ivec2(0, 0))\n\
+        cur = TYPE(imageLoad(pred, sp + ivec2(-1,  0) + yoff_border1)[comp]);\n\
+\n\
+    int base = quant_table[quant_table_idx][0][(cur - top[0]) & MAX_QUANT_TABLE_MASK] +\n\
+               quant_table[quant_table_idx][1][(top[0] - top[1]) & MAX_QUANT_TABLE_MASK] +\n\
+               quant_table[quant_table_idx][2][(top[1] - top[2]) & MAX_QUANT_TABLE_MASK];\n\
+\n\
+    if (expectEXT(extend_lookup, false)) {\n\
+        TYPE cur2 = TYPE(0);\n\
+        if (off.x > 0 && off != ivec2(1, 0)) {\n\
+            const ivec2 yoff_border2 = off.x == 1 ? ivec2(1, -1) : ivec2(0, 0);\n\
+            cur2 = TYPE(imageLoad(pred, sp + ivec2(-2,  0) + yoff_border2)[comp]);\n\
+        }\n\
+        base += quant_table[quant_table_idx][3][(cur2 - cur) & MAX_QUANT_TABLE_MASK];\n\
+\n\
+        TYPE top2 = TYPE(0);\n\
+        if (off.y > 1)\n\
+            top2 = TYPE(imageLoad(pred, sp + ivec2(0, -2))[comp]);\n\
+        base += quant_table[quant_table_idx][4][(top2 - top[1]) & MAX_QUANT_TABLE_MASK];\n\
+    }\n\
+\n\
+    /* context, prediction */\n\
+    return ivec2(base, predict(cur, VTYPE2(top)));\n\
+}\n\
+#endif";
+
+const char *ff_source_ffv1_reset_comp = "\
+void main(void)\n\
+{\n\
+    const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;\n\
+\n\
+    if (key_frame == 0 &&\n\
+        slice_ctx[slice_idx].slice_reset_contexts == false)\n\
+        return;\n\
+\n\
+    const uint8_t qidx = slice_ctx[slice_idx].quant_table_idx[gl_WorkGroupID.z];\n\
+    uint contexts = context_count[qidx];\n\
+    uint64_t slice_state_off = uint64_t(slice_state) +\n\
+                               slice_idx*plane_state_size*codec_planes;\n\
+\n\
+#ifdef GOLOMB\n\
+    uint64_t start = slice_state_off +\n\
+                     (gl_WorkGroupID.z*(plane_state_size/VLC_STATE_SIZE) + gl_LocalInvocationID.x)*VLC_STATE_SIZE;\n\
+    for (uint x = gl_LocalInvocationID.x; x < contexts; x += gl_WorkGroupSize.x) {\n\
+        VlcState sb = VlcState(start);\n\
+        sb.drift     =  int16_t(0);\n\
+        sb.error_sum = uint16_t(4);\n\
+        sb.bias      =   int8_t(0);\n\
+        sb.count     =  uint8_t(1);\n\
+        start += gl_WorkGroupSize.x*VLC_STATE_SIZE;\n\
+    }\n\
+#else\n\
+    uint64_t start = slice_state_off +\n\
+                     gl_WorkGroupID.z*plane_state_size +\n\
+                     (gl_LocalInvocationID.x << 2 /* dwords */); /* Bytes */\n\
+    uint count_total = contexts*(CONTEXT_SIZE /* bytes */ >> 2 /* dwords */);\n\
+    for (uint x = gl_LocalInvocationID.x; x < count_total; x += gl_WorkGroupSize.x) {\n\
+        u32buf(start).v = 0x80808080;\n\
+        start += gl_WorkGroupSize.x*(CONTEXT_SIZE >> 3 /* 1/8th of context */);\n\
+    }\n\
+#endif\n\
+}";
+
+const char *ff_source_ffv1_rct_search_comp = "\
+ivec3 load_components(ivec2 pos)\n\
+{\n\
+    ivec3 pix = ivec3(imageLoad(src[0], pos));\n\
+    if (planar_rgb != 0) {\n\
+        for (int i = 1; i < 3; i++)\n\
+            pix[i] = int(imageLoad(src[i], pos)[0]);\n\
+    }\n\
+\n\
+    return ivec3(pix[fmt_lut[0]], pix[fmt_lut[1]], pix[fmt_lut[2]]);\n\
+}\n\
+\n\
+#define NUM_CHECKS 15\n\
+const ivec2 rct_y_coeff[NUM_CHECKS] = {\n\
+    ivec2(0, 0), //      4G\n\
+\n\
+    ivec2(0, 1), //      3G +  B\n\
+    ivec2(1, 0), //  R + 3G\n\
+    ivec2(1, 1), //  R + 2G + B\n\
+\n\
+    ivec2(0, 2), //      2G + 2B\n\
+    ivec2(2, 0), // 2R + 2G\n\
+    ivec2(2, 2), // 2R      + 2B\n\
+\n\
+    ivec2(0, 3), //      1G + 3B\n\
+    ivec2(3, 0), // 3R + 1G\n\
+\n\
+    ivec2(0, 4), //           4B\n\
+    ivec2(4, 0), // 4R\n\
+\n\
+    ivec2(1, 2), //  R +  G + 2B\n\
+    ivec2(2, 1), // 2R +  G +  B\n\
+\n\
+    ivec2(3, 1), // 3R      +  B\n\
+    ivec2(1, 3), //  R      + 3B\n\
+};\n\
+\n\
+shared ivec3 pix_buf[gl_WorkGroupSize.x + 1][gl_WorkGroupSize.y + 1] = { };\n\
+\n\
+ivec3 transform_sample(ivec3 pix, ivec2 rct_coef)\n\
+{\n\
+    pix.b -= pix.g;\n\
+    pix.r -= pix.g;\n\
+    pix.g += (pix.r*rct_coef.x + pix.b*rct_coef.y) >> 2;\n\
+    pix.b += rct_offset;\n\
+    pix.r += rct_offset;\n\
+    return pix;\n\
+}\n\
+\n\
+uint get_dist(ivec3 cur)\n\
+{\n\
+    ivec3 LL = pix_buf[gl_LocalInvocationID.x + 0][gl_LocalInvocationID.y + 1];\n\
+    ivec3 TL = pix_buf[gl_LocalInvocationID.x + 0][gl_LocalInvocationID.y + 0];\n\
+    ivec3 TT = pix_buf[gl_LocalInvocationID.x + 1][gl_LocalInvocationID.y + 0];\n\
+\n\
+    ivec3 pred = ivec3(predict(LL.r, ivec2(TL.r, TT.r)),\n\
+                       predict(LL.g, ivec2(TL.g, TT.g)),\n\
+                       predict(LL.b, ivec2(TL.b, TT.b)));\n\
+\n\
+    uvec3 c = abs(pred - cur);\n\
+    return mid_pred(c.r, c.g, c.b);\n\
+}\n\
+\n\
+shared uint score_cols[gl_WorkGroupSize.y] = { };\n\
+shared uint score_mode[16] = { };\n\
+\n\
+void process(ivec2 pos)\n\
+{\n\
+    ivec3 pix = load_components(pos);\n\
+\n\
+    for (int i = 0; i < NUM_CHECKS; i++) {\n\
+        ivec3 tx_pix = transform_sample(pix, rct_y_coeff[i]);\n\
+        pix_buf[gl_LocalInvocationID.x + 1][gl_LocalInvocationID.y + 1] = tx_pix;\n\
+        memoryBarrierShared();\n\
+\n\
+        uint dist = get_dist(tx_pix);\n\
+        atomicAdd(score_mode[i], dist);\n\
+    }\n\
+}\n\
+\n\
+void coeff_search(inout SliceContext sc)\n\
+{\n\
+    uvec2 img_size = imageSize(src[0]);\n\
+    uint sxs = slice_coord(img_size.x, gl_WorkGroupID.x + 0,\n\
+                           gl_NumWorkGroups.x, 0);\n\
+    uint sxe = slice_coord(img_size.x, gl_WorkGroupID.x + 1,\n\
+                           gl_NumWorkGroups.x, 0);\n\
+    uint sys = slice_coord(img_size.y, gl_WorkGroupID.y + 0,\n\
+                           gl_NumWorkGroups.y, 0);\n\
+    uint sye = slice_coord(img_size.y, gl_WorkGroupID.y + 1,\n\
+                           gl_NumWorkGroups.y, 0);\n\
+\n\
+    for (uint y = sys + gl_LocalInvocationID.y; y < sye; y += gl_WorkGroupSize.y) {\n\
+        for (uint x = sxs + gl_LocalInvocationID.x; x < sxe; x += gl_WorkGroupSize.x) {\n\
+            process(ivec2(x, y));\n\
+        }\n\
+    }\n\
+\n\
+    if (gl_LocalInvocationID.x == 0 && gl_LocalInvocationID.y == 0) {\n\
+        uint min_score = 0xFFFFFFFF;\n\
+        uint min_idx = 3;\n\
+        for (int i = 0; i < NUM_CHECKS; i++) {\n\
+            if (score_mode[i] < min_score) {\n\
+                min_score = score_mode[i];\n\
+                min_idx = i;\n\
+            }\n\
+        }\n\
+        sc.slice_rct_coef = rct_y_coeff[min_idx];\n\
+    }\n\
+}\n\
+\n\
+void main(void)\n\
+{\n\
+    if (force_pcm == 1)\n\
+        return;\n\
+    const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;\n\
+    coeff_search(slice_ctx[slice_idx]);\n\
+}";
+
+const char *ff_source_ffv1_enc_setup_comp = "\
+uint8_t state[CONTEXT_SIZE];\n\
+\n\
+void init_slice(inout SliceContext sc, const uint slice_idx)\n\
+{\n\
+    /* Set coordinates */\n\
+    uvec2 img_size = imageSize(src[0]);\n\
+    uint sxs = slice_coord(img_size.x, gl_WorkGroupID.x + 0,\n\
+                           gl_NumWorkGroups.x, chroma_shift.x);\n\
+    uint sxe = slice_coord(img_size.x, gl_WorkGroupID.x + 1,\n\
+                           gl_NumWorkGroups.x, chroma_shift.x);\n\
+    uint sys = slice_coord(img_size.y, gl_WorkGroupID.y + 0,\n\
+                           gl_NumWorkGroups.y, chroma_shift.y);\n\
+    uint sye = slice_coord(img_size.y, gl_WorkGroupID.y + 1,\n\
+                           gl_NumWorkGroups.y, chroma_shift.y);\n\
+\n\
+    sc.slice_pos = ivec2(sxs, sys);\n\
+    sc.slice_dim = ivec2(sxe - sxs, sye - sys);\n\
+    sc.slice_coding_mode = int(force_pcm == 1);\n\
+    sc.slice_reset_contexts = sc.slice_coding_mode == 1;\n\
+    sc.quant_table_idx = u8vec3(context_model);\n\
+\n\
+    if ((rct_search == 0) || (sc.slice_coding_mode == 1))\n\
+        sc.slice_rct_coef = ivec2(1, 1);\n\
+\n\
+    rac_init(sc.c,\n\
+             OFFBUF(u8buf, out_data, slice_idx * slice_size_max),\n\
+             slice_size_max);\n\
+}\n\
+\n\
+void put_usymbol(inout RangeCoder c, uint v)\n\
+{\n\
+    bool is_nil = (v == 0);\n\
+    put_rac_direct(c, state[0], is_nil);\n\
+    if (is_nil)\n\
+        return;\n\
+\n\
+    const int e = findMSB(v);\n\
+\n\
+    for (int i = 0; i < e; i++)\n\
+        put_rac_direct(c, state[1 + min(i, 9)], true);\n\
+    put_rac_direct(c, state[1 + min(e, 9)], false);\n\
+\n\
+    for (int i = e - 1; i >= 0; i--)\n\
+        put_rac_direct(c, state[22 + min(i, 9)], bool(bitfieldExtract(v, i, 1)));\n\
+}\n\
+\n\
+void write_slice_header(inout SliceContext sc)\n\
+{\n\
+    [[unroll]]\n\
+    for (int i = 0; i < CONTEXT_SIZE; i++)\n\
+        state[i] = uint8_t(128);\n\
+\n\
+    put_usymbol(sc.c, gl_WorkGroupID.x);\n\
+    put_usymbol(sc.c, gl_WorkGroupID.y);\n\
+    put_usymbol(sc.c, 0);\n\
+    put_usymbol(sc.c, 0);\n\
+\n\
+    for (int i = 0; i < codec_planes; i++)\n\
+        put_usymbol(sc.c, sc.quant_table_idx[i]);\n\
+\n\
+    put_usymbol(sc.c, pic_mode);\n\
+    put_usymbol(sc.c, sar.x);\n\
+    put_usymbol(sc.c, sar.y);\n\
+\n\
+    if (version >= 4) {\n\
+        put_rac_direct(sc.c, state[0], sc.slice_reset_contexts);\n\
+        put_usymbol(sc.c, sc.slice_coding_mode);\n\
+        if (sc.slice_coding_mode != 1 && colorspace == 1) {\n\
+            put_usymbol(sc.c, sc.slice_rct_coef.y);\n\
+            put_usymbol(sc.c, sc.slice_rct_coef.x);\n\
+        }\n\
+    }\n\
+}\n\
+\n\
+void write_frame_header(inout SliceContext sc)\n\
+{\n\
+    put_rac_equi(sc.c, bool(key_frame));\n\
+}\n\
+\n\
+#ifdef GOLOMB\n\
+void init_golomb(inout SliceContext sc)\n\
+{\n\
+    sc.hdr_len = rac_terminate(sc.c);\n\
+    init_put_bits(sc.pb,\n\
+                  OFFBUF(u8buf, sc.c.bytestream_start, sc.hdr_len),\n\
+                  slice_size_max - sc.hdr_len);\n\
+}\n\
+#endif\n\
+\n\
+void main(void)\n\
+{\n\
+    const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;\n\
+\n\
+    init_slice(slice_ctx[slice_idx], slice_idx);\n\
+\n\
+    if (slice_idx == 0)\n\
+        write_frame_header(slice_ctx[slice_idx]);\n\
+\n\
+    write_slice_header(slice_ctx[slice_idx]);\n\
+\n\
+#ifdef GOLOMB\n\
+    init_golomb(slice_ctx[slice_idx]);\n\
+#endif\n\
+}";
+
+const char *ff_source_ffv1_enc_comp = "\
+#ifndef GOLOMB\n\
+#ifdef CACHED_SYMBOL_READER\n\
+shared uint8_t state[CONTEXT_SIZE];\n\
+#define WRITE(c, off, val) put_rac_direct(c, state[off], val)\n\
+#else\n\
+#define WRITE(c, off, val) put_rac(c, uint64_t(slice_state) + (state_off + off), val)\n\
+#endif\n\
+\n\
+/* Note - only handles signed values */\n\
+void put_symbol(inout RangeCoder c, uint state_off, int v)\n\
+{\n\
+    bool is_nil = (v == 0);\n\
+    WRITE(c, 0, is_nil);\n\
+    if (is_nil)\n\
+        return;\n\
+\n\
+    const int a = abs(v);\n\
+    const int e = findMSB(a);\n\
+\n\
+    for (int i = 0; i < e; i++)\n\
+        WRITE(c, 1 + min(i, 9), true);\n\
+    WRITE(c, 1 + min(e, 9), false);\n\
+\n\
+    for (int i = e - 1; i >= 0; i--)\n\
+        WRITE(c, 22 + min(i, 9), bool(bitfieldExtract(a, i, 1)));\n\
+\n\
+    WRITE(c, 22 - 11 + min(e, 10), v < 0);\n\
+}\n\
+\n\
+void encode_line_pcm(inout SliceContext sc, readonly uimage2D img,\n\
+                     ivec2 sp, int y, int p, int comp, int bits)\n\
+{\n\
+    int w = sc.slice_dim.x;\n\
+\n\
+#ifdef CACHED_SYMBOL_READER\n\
+    if (gl_LocalInvocationID.x > 0)\n\
+        return;\n\
+#endif\n\
+\n\
+#ifndef RGB\n\
+    if (p > 0 && p < 3) {\n\
+        w >>= chroma_shift.x;\n\
+        sp >>= chroma_shift;\n\
+    }\n\
+#endif\n\
+\n\
+    for (int x = 0; x < w; x++) {\n\
+        uint v = imageLoad(img, sp + LADDR(ivec2(x, y)))[comp];\n\
+        for (int i = (bits - 1); i >= 0; i--)\n\
+            put_rac_equi(sc.c, bool(bitfieldExtract(v, i, 1)));\n\
+    }\n\
+}\n\
+\n\
+void encode_line(inout SliceContext sc, readonly uimage2D img, uint state_off,\n\
+                 ivec2 sp, int y, int p, int comp, int bits,\n\
+                 uint8_t quant_table_idx, const int run_index)\n\
+{\n\
+    int w = sc.slice_dim.x;\n\
+\n\
+#ifndef RGB\n\
+    if (p > 0 && p < 3) {\n\
+        w >>= chroma_shift.x;\n\
+        sp >>= chroma_shift;\n\
+    }\n\
+#endif\n\
+\n\
+    for (int x = 0; x < w; x++) {\n\
+        ivec2 d = get_pred(img, sp, ivec2(x, y), comp, w,\n\
+                           quant_table_idx, extend_lookup[quant_table_idx] > 0);\n\
+        d[1] = int(imageLoad(img, sp + LADDR(ivec2(x, y)))[comp]) - d[1];\n\
+\n\
+        if (d[0] < 0)\n\
+            d = -d;\n\
+\n\
+        d[1] = fold(d[1], bits);\n\
+\n\
+        uint context_off = state_off + CONTEXT_SIZE*d[0];\n\
+#ifdef CACHED_SYMBOL_READER\n\
+        u8buf sb = u8buf(uint64_t(slice_state) + context_off + gl_LocalInvocationID.x);\n\
+        state[gl_LocalInvocationID.x] = sb.v;\n\
+        barrier();\n\
+        if (gl_LocalInvocationID.x == 0)\n\
+#endif\n\
+\n\
+            put_symbol(sc.c, context_off, d[1]);\n\
+\n\
+#ifdef CACHED_SYMBOL_READER\n\
+        barrier();\n\
+        sb.v = state[gl_LocalInvocationID.x];\n\
+#endif\n\
+    }\n\
+}\n\
+\n\
+#else /* GOLOMB */\n\
+\n\
+void encode_line(inout SliceContext sc, readonly uimage2D img, uint state_off,\n\
+                 ivec2 sp, int y, int p, int comp, int bits,\n\
+                 uint8_t quant_table_idx, inout int run_index)\n\
+{\n\
+    int w = sc.slice_dim.x;\n\
+\n\
+#ifndef RGB\n\
+    if (p > 0 && p < 3) {\n\
+        w >>= chroma_shift.x;\n\
+        sp >>= chroma_shift;\n\
+    }\n\
+#endif\n\
+\n\
+    int run_count = 0;\n\
+    bool run_mode = false;\n\
+\n\
+    for (int x = 0; x < w; x++) {\n\
+        ivec2 d = get_pred(img, sp, ivec2(x, y), comp, w,\n\
+                           quant_table_idx, extend_lookup[quant_table_idx] > 0);\n\
+        d[1] = int(imageLoad(img, sp + LADDR(ivec2(x, y)))[comp]) - d[1];\n\
+\n\
+        if (d[0] < 0)\n\
+            d = -d;\n\
+\n\
+        d[1] = fold(d[1], bits);\n\
+\n\
+        if (d[0] == 0)\n\
+            run_mode = true;\n\
+\n\
+        if (run_mode) {\n\
+            if (d[1] != 0) {\n\
+                /* A very unlikely loop */\n\
+                while (run_count >= 1 << log2_run[run_index]) {\n\
+                    run_count -= 1 << log2_run[run_index];\n\
+                    run_index++;\n\
+                    put_bits(sc.pb, 1, 1);\n\
+                }\n\
+\n\
+                put_bits(sc.pb, 1 + log2_run[run_index], run_count);\n\
+                if (run_index != 0)\n\
+                    run_index--;\n\
+                run_count = 0;\n\
+                run_mode  = false;\n\
+                if (d[1] > 0)\n\
+                    d[1]--;\n\
+            } else {\n\
+                run_count++;\n\
+            }\n\
+        }\n\
+\n\
+        if (!run_mode) {\n\
+            VlcState sb = VlcState(uint64_t(slice_state) + state_off + VLC_STATE_SIZE*d[0]);\n\
+            Symbol sym = get_vlc_symbol(sb, d[1], bits);\n\
+            put_bits(sc.pb, sym.bits, sym.val);\n\
+        }\n\
+    }\n\
+\n\
+    if (run_mode) {\n\
+        while (run_count >= (1 << log2_run[run_index])) {\n\
+            run_count -= 1 << log2_run[run_index];\n\
+            run_index++;\n\
+            put_bits(sc.pb, 1, 1);\n\
+        }\n\
+\n\
+        if (run_count > 0)\n\
+            put_bits(sc.pb, 1, 1);\n\
+    }\n\
+}\n\
+#endif\n\
+\n\
+#ifdef RGB\n\
+ivec4 load_components(ivec2 pos)\n\
+{\n\
+    ivec4 pix = ivec4(imageLoad(src[0], pos));\n\
+    if (planar_rgb != 0) {\n\
+        for (int i = 1; i < (3 + transparency); i++)\n\
+            pix[i] = int(imageLoad(src[i], pos)[0]);\n\
+    }\n\
+\n\
+    return ivec4(pix[fmt_lut[0]], pix[fmt_lut[1]],\n\
+                 pix[fmt_lut[2]], pix[fmt_lut[3]]);\n\
+}\n\
+\n\
+void transform_sample(inout ivec4 pix, ivec2 rct_coef)\n\
+{\n\
+    pix.b -= pix.g;\n\
+    pix.r -= pix.g;\n\
+    pix.g += (pix.r*rct_coef.x + pix.b*rct_coef.y) >> 2;\n\
+    pix.b += rct_offset;\n\
+    pix.r += rct_offset;\n\
+}\n\
+\n\
+void preload_rgb(in SliceContext sc, ivec2 sp, int w, int y, bool apply_rct)\n\
+{\n\
+    for (uint x = gl_LocalInvocationID.x; x < w; x += gl_WorkGroupSize.x) {\n\
+        ivec2 lpos = sp + LADDR(ivec2(x, y));\n\
+        ivec2 pos = sc.slice_pos + ivec2(x, y);\n\
+\n\
+        ivec4 pix = load_components(pos);\n\
+\n\
+        if (expectEXT(apply_rct, true))\n\
+            transform_sample(pix, sc.slice_rct_coef);\n\
+\n\
+        imageStore(tmp, lpos, pix);\n\
+    }\n\
+}\n\
+#endif\n\
+\n\
+void encode_slice(inout SliceContext sc, const uint slice_idx)\n\
+{\n\
+    ivec2 sp = sc.slice_pos;\n\
+\n\
+#ifndef RGB\n\
+    int bits = bits_per_raw_sample;\n\
+#else\n\
+    int bits = 9;\n\
+    if (bits != 8 || sc.slice_coding_mode != 0)\n\
+        bits = bits_per_raw_sample + int(sc.slice_coding_mode != 1);\n\
+\n\
+    sp.y = int(gl_WorkGroupID.y)*RGB_LINECACHE;\n\
+#endif\n\
+\n\
+#ifndef GOLOMB\n\
+    if (sc.slice_coding_mode == 1) {\n\
+#ifndef RGB\n\
+        for (int c = 0; c < components; c++) {\n\
+\n\
+            int h = sc.slice_dim.y;\n\
+            if (c > 0 && c < 3)\n\
+                h >>= chroma_shift.y;\n\
+\n\
+            /* Takes into account dual-plane YUV formats */\n\
+            int p = min(c, planes - 1);\n\
+            int comp = c - p;\n\
+\n\
+            for (int y = 0; y < h; y++)\n\
+                encode_line_pcm(sc, src[p], sp, y, p, comp, bits);\n\
+        }\n\
+#else\n\
+        for (int y = 0; y < sc.slice_dim.y; y++) {\n\
+            preload_rgb(sc, sp, sc.slice_dim.x, y, false);\n\
+\n\
+            encode_line_pcm(sc, tmp, sp, y, 0, 1, bits);\n\
+            encode_line_pcm(sc, tmp, sp, y, 0, 2, bits);\n\
+            encode_line_pcm(sc, tmp, sp, y, 0, 0, bits);\n\
+            if (transparency == 1)\n\
+                encode_line_pcm(sc, tmp, sp, y, 0, 3, bits);\n\
+        }\n\
+#endif\n\
+    } else\n\
+#endif\n\
+    {\n\
+        u8vec4 quant_table_idx = sc.quant_table_idx.xyyz;\n\
+        u32vec4 slice_state_off = (slice_idx*codec_planes + uvec4(0, 1, 1, 2))*plane_state_size;\n\
+\n\
+#ifndef RGB\n\
+        for (int c = 0; c < components; c++) {\n\
+            int run_index = 0;\n\
+\n\
+            int h = sc.slice_dim.y;\n\
+            if (c > 0 && c < 3)\n\
+                h >>= chroma_shift.y;\n\
+\n\
+            int p = min(c, planes - 1);\n\
+            int comp = c - p;\n\
+\n\
+            for (int y = 0; y < h; y++)\n\
+                encode_line(sc, src[p], slice_state_off[c], sp, y, p,\n\
+                            comp, bits, quant_table_idx[c], run_index);\n\
+        }\n\
+#else\n\
+        int run_index = 0;\n\
+        for (int y = 0; y < sc.slice_dim.y; y++) {\n\
+            preload_rgb(sc, sp, sc.slice_dim.x, y, true);\n\
+\n\
+            encode_line(sc, tmp, slice_state_off[0],\n\
+                        sp, y, 0, 1, bits, quant_table_idx[0], run_index);\n\
+            encode_line(sc, tmp, slice_state_off[1],\n\
+                        sp, y, 0, 2, bits, quant_table_idx[1], run_index);\n\
+            encode_line(sc, tmp, slice_state_off[2],\n\
+                        sp, y, 0, 0, bits, quant_table_idx[2], run_index);\n\
+            if (transparency == 1)\n\
+                encode_line(sc, tmp, slice_state_off[3],\n\
+                            sp, y, 0, 3, bits, quant_table_idx[3], run_index);\n\
+        }\n\
+#endif\n\
+    }\n\
+}\n\
+\n\
+void finalize_slice(inout SliceContext sc, const uint slice_idx)\n\
+{\n\
+#ifdef CACHED_SYMBOL_READER\n\
+    if (gl_LocalInvocationID.x > 0)\n\
+        return;\n\
+#endif\n\
+\n\
+#ifdef GOLOMB\n\
+    uint32_t enc_len = sc.hdr_len + flush_put_bits(sc.pb);\n\
+#else\n\
+    uint32_t enc_len = rac_terminate(sc.c);\n\
+#endif\n\
+\n\
+    u8buf bs = u8buf(sc.c.bytestream_start);\n\
+\n\
+    /* Append slice length */\n\
+    u8vec4 enc_len_p = unpack8(enc_len);\n\
+    bs[enc_len + 0].v = enc_len_p.z;\n\
+    bs[enc_len + 1].v = enc_len_p.y;\n\
+    bs[enc_len + 2].v = enc_len_p.x;\n\
+    enc_len += 3;\n\
+\n\
+    /* Calculate and write CRC */\n\
+    if (ec != 0) {\n\
+        bs[enc_len].v = uint8_t(0);\n\
+        enc_len++;\n\
+\n\
+        uint32_t crc = crcref;\n\
+        for (int i = 0; i < enc_len; i++)\n\
+            crc = crc_ieee[(crc & 0xFF) ^ uint32_t(bs[i].v)] ^ (crc >> 8);\n\
+\n\
+        if (crcref != 0x00000000)\n\
+            crc ^= 0x8CD88196;\n\
+\n\
+        u8vec4 crc_p = unpack8(crc);\n\
+        bs[enc_len + 0].v = crc_p.x;\n\
+        bs[enc_len + 1].v = crc_p.y;\n\
+        bs[enc_len + 2].v = crc_p.z;\n\
+        bs[enc_len + 3].v = crc_p.w;\n\
+        enc_len += 4;\n\
+    }\n\
+\n\
+    slice_results[slice_idx*2 + 0] = enc_len;\n\
+    slice_results[slice_idx*2 + 1] = uint64_t(bs) - uint64_t(out_data);\n\
+}\n\
+\n\
+void main(void)\n\
+{\n\
+    const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;\n\
+    encode_slice(slice_ctx[slice_idx], slice_idx);\n\
+    finalize_slice(slice_ctx[slice_idx], slice_idx);\n\
+}";
+
+const char *ff_source_ffv1_rct_comp = "\
+ivec4 load_components(ivec2 pos)\n\
+{\n\
+    ivec4 pix = ivec4(imageLoad(src[0], pos));\n\
+    if (planar_rgb != 0) {\n\
+        for (int i = 1; i < (3 + transparency); i++)\n\
+            pix[i] = int(imageLoad(src[i], pos)[0]);\n\
+    }\n\
+\n\
+    return ivec4(pix[fmt_lut[0]], pix[fmt_lut[1]],\n\
+                 pix[fmt_lut[2]], pix[fmt_lut[3]]);\n\
+}\n\
+\n\
+void bypass_sample(ivec2 pos)\n\
+{\n\
+    imageStore(dst[0], pos, load_components(pos));\n\
+}\n\
+\n\
+void bypass_block(in SliceContext sc)\n\
+{\n\
+    ivec2 start = ivec2(gl_LocalInvocationID) + sc.slice_pos;\n\
+    ivec2 end = sc.slice_pos + sc.slice_dim;\n\
+    for (uint y = start.y; y < end.y; y += gl_WorkGroupSize.y)\n\
+        for (uint x = start.x; x < end.x; x += gl_WorkGroupSize.x)\n\
+            bypass_sample(ivec2(x, y));\n\
+}\n\
+\n\
+void transform_sample(ivec2 pos, ivec2 rct_coef)\n\
+{\n\
+    ivec4 pix = load_components(pos);\n\
+    pix.b -= offset;\n\
+    pix.r -= offset;\n\
+    pix.g -= (pix.r*rct_coef.x + pix.b*rct_coef.y) >> 2;\n\
+    pix.b += pix.g;\n\
+    pix.r += pix.g;\n\
+    imageStore(dst[0], pos, pix);\n\
+}\n\
+\n\
+void transform_sample(ivec2 pos, ivec2 rct_coef)\n\
+{\n\
+    ivec4 pix = load_components(pos);\n\
+    pix.b -= pix.g;\n\
+    pix.r -= pix.g;\n\
+    pix.g += (pix.r*rct_coef.x + pix.b*rct_coef.y) >> 2;\n\
+    pix.b += offset;\n\
+    pix.r += offset;\n\
+    imageStore(dst[0], pos, pix);\n\
+}\n\
+\n\
+void transform_block(in SliceContext sc)\n\
+{\n\
+    const ivec2 rct_coef = sc.slice_rct_coef;\n\
+    const ivec2 start = ivec2(gl_LocalInvocationID) + sc.slice_pos;\n\
+    const ivec2 end = sc.slice_pos + sc.slice_dim;\n\
+\n\
+    for (uint y = start.y; y < end.y; y += gl_WorkGroupSize.y)\n\
+        for (uint x = start.x; x < end.x; x += gl_WorkGroupSize.x)\n\
+            transform_sample(ivec2(x, y), rct_coef);\n\
+}\n\
+\n\
+void main()\n\
+{\n\
+    const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;\n\
+\n\
+    if (slice_ctx[slice_idx].slice_coding_mode == 1)\n\
+        bypass_block(slice_ctx[slice_idx]);\n\
+    else\n\
+        transform_block(slice_ctx[slice_idx]);\n\
+}";
+
+const char *ff_source_ffv1_enc_rct_comp = "\
+ivec4 load_components(ivec2 pos)\n\
+{\n\
+    ivec4 pix = ivec4(imageLoad(src[0], pos));\n\
+    if (planar_rgb != 0) {\n\
+        for (int i = 1; i < (3 + transparency); i++)\n\
+            pix[i] = int(imageLoad(src[i], pos)[0]);\n\
+    }\n\
+\n\
+    return ivec4(pix[fmt_lut[0]], pix[fmt_lut[1]],\n\
+                 pix[fmt_lut[2]], pix[fmt_lut[3]]);\n\
+}\n\
+\n\
+void bypass_sample(ivec2 pos)\n\
+{\n\
+    imageStore(dst[0], pos, load_components(pos));\n\
+}\n\
+\n\
+void bypass_block(in SliceContext sc)\n\
+{\n\
+    ivec2 start = ivec2(gl_LocalInvocationID) + sc.slice_pos;\n\
+    ivec2 end = sc.slice_pos + sc.slice_dim;\n\
+    for (uint y = start.y; y < end.y; y += gl_WorkGroupSize.y)\n\
+        for (uint x = start.x; x < end.x; x += gl_WorkGroupSize.x)\n\
+            bypass_sample(ivec2(x, y));\n\
+}\n\
+\n\
+void transform_sample(ivec2 pos, ivec2 rct_coef)\n\
+{\n\
+    ivec4 pix = load_components(pos);\n\
+    pix.b -= pix.g;\n\
+    pix.r -= pix.g;\n\
+    pix.g += (pix.r*rct_coef.x + pix.b*rct_coef.y) >> 2;\n\
+    pix.b += offset;\n\
+    pix.r += offset;\n\
+    imageStore(dst[0], pos, pix);\n\
+}\n\
+\n\
+void transform_block(in SliceContext sc)\n\
+{\n\
+    const ivec2 rct_coef = sc.slice_rct_coef;\n\
+    const ivec2 start = ivec2(gl_LocalInvocationID) + sc.slice_pos;\n\
+    const ivec2 end = sc.slice_pos + sc.slice_dim;\n\
+\n\
+    for (uint y = start.y; y < end.y; y += gl_WorkGroupSize.y)\n\
+        for (uint x = start.x; x < end.x; x += gl_WorkGroupSize.x)\n\
+            transform_sample(ivec2(x, y), rct_coef);\n\
+}\n\
+\n\
+void main()\n\
+{\n\
+    const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;\n\
+\n\
+    if (slice_ctx[slice_idx].slice_coding_mode == 1)\n\
+        bypass_block(slice_ctx[slice_idx]);\n\
+    else\n\
+        transform_block(slice_ctx[slice_idx]);\n\
+}";
+
+const char *ff_source_ffv1_dec_setup_comp = "\
+uint8_t setup_state[CONTEXT_SIZE];\n\
+\n\
+uint get_usymbol(inout RangeCoder c)\n\
+{\n\
+    if (get_rac_direct(c, setup_state[0]))\n\
+        return 0;\n\
+\n\
+    int e = 0;\n\
+    while (get_rac_direct(c, setup_state[1 + min(e, 9)])) { // 1..10\n\
+        e++;\n\
+        if (e > 31) {\n\
+            corrupt = true;\n\
+            return 0;\n\
+        }\n\
+    }\n\
+\n\
+    uint a = 1;\n\
+    for (int i = e - 1; i >= 0; i--) {\n\
+        a <<= 1;\n\
+        a |= uint(get_rac_direct(c, setup_state[22 + min(i, 9)]));  // 22..31\n\
+    }\n\
+\n\
+    return a;\n\
+}\n\
+\n\
+bool decode_slice_header(inout SliceContext sc)\n\
+{\n\
+    [[unroll]]\n\
+    for (int i = 0; i < CONTEXT_SIZE; i++)\n\
+        setup_state[i] = uint8_t(128);\n\
+\n\
+    uint sx = get_usymbol(sc.c);\n\
+    uint sy = get_usymbol(sc.c);\n\
+    uint sw = get_usymbol(sc.c) + 1;\n\
+    uint sh = get_usymbol(sc.c) + 1;\n\
+\n\
+    if (sx < 0 || sy < 0 || sw <= 0 || sh <= 0 ||\n\
+        sx > (gl_NumWorkGroups.x - sw) || sy > (gl_NumWorkGroups.y - sh) ||\n\
+        corrupt) {\n\
+        return true;\n\
+    }\n\
+\n\
+    /* Set coordinates */\n\
+    uint sxs = slice_coord(img_size.x, sx     , gl_NumWorkGroups.x, chroma_shift.x);\n\
+    uint sxe = slice_coord(img_size.x, sx + sw, gl_NumWorkGroups.x, chroma_shift.x);\n\
+    uint sys = slice_coord(img_size.y, sy     , gl_NumWorkGroups.y, chroma_shift.y);\n\
+    uint sye = slice_coord(img_size.y, sy + sh, gl_NumWorkGroups.y, chroma_shift.y);\n\
+\n\
+    sc.slice_pos = ivec2(sxs, sys);\n\
+    sc.slice_dim = ivec2(sxe - sxs, sye - sys);\n\
+    sc.slice_rct_coef = ivec2(1, 1);\n\
+    sc.slice_coding_mode = int(0);\n\
+\n\
+    for (uint i = 0; i < codec_planes; i++) {\n\
+        uint idx = get_usymbol(sc.c);\n\
+        if (idx >= quant_table_count)\n\
+            return true;\n\
+        sc.quant_table_idx[i] = uint8_t(idx);\n\
+    }\n\
+\n\
+    get_usymbol(sc.c);\n\
+    get_usymbol(sc.c);\n\
+    get_usymbol(sc.c);\n\
+\n\
+    if (version >= 4) {\n\
+        sc.slice_reset_contexts = get_rac_direct(sc.c, setup_state[0]);\n\
+        sc.slice_coding_mode = get_usymbol(sc.c);\n\
+        if (sc.slice_coding_mode != 1 && colorspace == 1) {\n\
+            sc.slice_rct_coef.x = int(get_usymbol(sc.c));\n\
+            sc.slice_rct_coef.y = int(get_usymbol(sc.c));\n\
+            if (sc.slice_rct_coef.x + sc.slice_rct_coef.y > 4)\n\
+                return true;\n\
+        }\n\
+    }\n\
+\n\
+    return false;\n\
+}\n\
+\n\
+void golomb_init(inout SliceContext sc)\n\
+{\n\
+    if (version == 3 && micro_version > 1 || version > 3) {\n\
+        setup_state[0] = uint8_t(129);\n\
+        get_rac_direct(sc.c, setup_state[0]);\n\
+    }\n\
+\n\
+    uint64_t ac_byte_count = sc.c.bytestream - sc.c.bytestream_start - 1;\n\
+    init_get_bits(sc.gb, u8buf(sc.c.bytestream_start + ac_byte_count),\n\
+                  int(sc.c.bytestream_end - sc.c.bytestream_start - ac_byte_count));\n\
+}\n\
+\n\
+void main(void)\n\
+{\n\
+    const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;\n\
+\n\
+    u8buf bs = u8buf(slice_data + slice_offsets[2*slice_idx + 0]);\n\
+    uint32_t slice_size = slice_offsets[2*slice_idx + 1];\n\
+\n\
+    rac_init_dec(slice_ctx[slice_idx].c,\n\
+                 bs, slice_size);\n\
+\n\
+    if (slice_idx == (gl_NumWorkGroups.x*gl_NumWorkGroups.y - 1))\n\
+        get_rac_equi(slice_ctx[slice_idx].c);\n\
+\n\
+    decode_slice_header(slice_ctx[slice_idx]);\n\
+\n\
+    if (golomb == 1)\n\
+        golomb_init(slice_ctx[slice_idx]);\n\
+\n\
+    if (ec != 0 && check_crc != 0) {\n\
+        uint32_t crc = crcref;\n\
+        for (int i = 0; i < slice_size; i++)\n\
+            crc = crc_ieee[(crc & 0xFF) ^ uint32_t(bs[i].v)] ^ (crc >> 8);\n\
+\n\
+        slice_status[2*slice_idx + 0] = crc;\n\
+    }\n\
+\n\
+    slice_status[2*slice_idx + 1] = corrupt ? uint32_t(corrupt) : overread;\n\
+}";
+
+const char *ff_source_ffv1_dec_comp = "\
+#ifndef GOLOMB\n\
+#ifdef CACHED_SYMBOL_READER\n\
+shared uint8_t state[CONTEXT_SIZE];\n\
+#define READ(c, off) get_rac_direct(c, state[off])\n\
+#else\n\
+#define READ(c, off) get_rac(c, uint64_t(slice_state) + (state_off + off))\n\
+#endif\n\
+\n\
+int get_isymbol(inout RangeCoder c, uint state_off)\n\
+{\n\
+    if (READ(c, 0))\n\
+        return 0;\n\
+\n\
+    uint e = 1;\n\
+    for (; e < 33; e++)\n\
+        if (!READ(c, min(e, 10)))\n\
+            break;\n\
+\n\
+    if (expectEXT(e == 1, false)) {\n\
+        return READ(c, 11) ? -1 : 1;\n\
+    } else if (expectEXT(e == 33, false)) {\n\
+        corrupt = true;\n\
+        return 0;\n\
+    }\n\
+\n\
+    int a = 1;\n\
+    for (uint i = e + 20; i >= 22; i--) {\n\
+        a <<= 1;\n\
+        a |= int(READ(c, min(i, 31)));\n\
+    }\n\
+\n\
+    return READ(c, min(e + 10, 21)) ? -a : a;\n\
+}\n\
+\n\
+void decode_line_pcm(inout SliceContext sc, ivec2 sp, int w, int y, int p, int bits)\n\
+{\n\
+#ifdef CACHED_SYMBOL_READER\n\
+    if (gl_LocalInvocationID.x > 0)\n\
+        return;\n\
+#endif\n\
+\n\
+#ifndef RGB\n\
+    if (p > 0 && p < 3) {\n\
+        w >>= chroma_shift.x;\n\
+        sp >>= chroma_shift;\n\
+    }\n\
+#endif\n\
+\n\
+    for (int x = 0; x < w; x++) {\n\
+        uint v = 0;\n\
+        for (int i = (bits - 1); i >= 0; i--)\n\
+            v |= uint(get_rac_equi(sc.c)) << i;\n\
+\n\
+        imageStore(dec[p], sp + LADDR(ivec2(x, y)), uvec4(v));\n\
+    }\n\
+}\n\
+\n\
+void decode_line(inout SliceContext sc, ivec2 sp, int w,\n\
+                 int y, int p, int bits, uint state_off,\n\
+                 uint8_t quant_table_idx, const int run_index)\n\
+{\n\
+#ifndef RGB\n\
+    if (p > 0 && p < 3) {\n\
+        w >>= chroma_shift.x;\n\
+        sp >>= chroma_shift;\n\
+    }\n\
+#endif\n\
+\n\
+    for (int x = 0; x < w; x++) {\n\
+        ivec2 pr = get_pred(dec[p], sp, ivec2(x, y), 0, w,\n\
+                            quant_table_idx, extend_lookup[quant_table_idx] > 0);\n\
+\n\
+        uint context_off = state_off + CONTEXT_SIZE*abs(pr[0]);\n\
+#ifdef CACHED_SYMBOL_READER\n\
+        u8buf sb = u8buf(uint64_t(slice_state) + context_off + gl_LocalInvocationID.x);\n\
+        state[gl_LocalInvocationID.x] = sb.v;\n\
+        barrier();\n\
+        if (gl_LocalInvocationID.x == 0) {\n\
+\n\
+#endif\n\
+\n\
+            int diff = get_isymbol(sc.c, context_off);\n\
+            if (pr[0] < 0)\n\
+                diff = -diff;\n\
+\n\
+            uint v = zero_extend(pr[1] + diff, bits);\n\
+            imageStore(dec[p], sp + LADDR(ivec2(x, y)), uvec4(v));\n\
+\n\
+#ifdef CACHED_SYMBOL_READER\n\
+        }\n\
+\n\
+        barrier();\n\
+        sb.v = state[gl_LocalInvocationID.x];\n\
+#endif\n\
+    }\n\
+}\n\
+\n\
+#else /* GOLOMB */\n\
+\n\
+void decode_line(inout SliceContext sc, ivec2 sp, int w,\n\
+                 int y, int p, int bits, uint state_off,\n\
+                 uint8_t quant_table_idx, inout int run_index)\n\
+{\n\
+#ifndef RGB\n\
+    if (p > 0 && p < 3) {\n\
+        w >>= chroma_shift.x;\n\
+        sp >>= chroma_shift;\n\
+    }\n\
+#endif\n\
+\n\
+    int run_count = 0;\n\
+    int run_mode  = 0;\n\
+\n\
+    for (int x = 0; x < w; x++) {\n\
+        ivec2 pos = sp + ivec2(x, y);\n\
+        int diff;\n\
+        ivec2 pr = get_pred(dec[p], sp, ivec2(x, y), 0, w,\n\
+                            quant_table_idx, extend_lookup[quant_table_idx] > 0);\n\
+\n\
+        uint context_off = state_off + VLC_STATE_SIZE*abs(pr[0]);\n\
+        VlcState sb = VlcState(uint64_t(slice_state) + context_off);\n\
+\n\
+        if (pr[0] == 0 && run_mode == 0)\n\
+            run_mode = 1;\n\
+\n\
+        if (run_mode != 0) {\n\
+            if (run_count == 0 && run_mode == 1) {\n\
+                int tmp_idx = int(log2_run[run_index]);\n\
+                if (get_bit(sc.gb)) {\n\
+                    run_count = 1 << tmp_idx;\n\
+                    if (x + run_count <= w)\n\
+                        run_index++;\n\
+                } else {\n\
+                    if (tmp_idx != 0) {\n\
+                        run_count = int(get_bits(sc.gb, tmp_idx));\n\
+                    } else\n\
+                        run_count = 0;\n\
+\n\
+                    if (run_index != 0)\n\
+                        run_index--;\n\
+                    run_mode = 2;\n\
+                }\n\
+            }\n\
+\n\
+            run_count--;\n\
+            if (run_count < 0) {\n\
+                run_mode  = 0;\n\
+                run_count = 0;\n\
+                diff = read_vlc_symbol(sc.gb, sb, bits);\n\
+                if (diff >= 0)\n\
+                    diff++;\n\
+            } else {\n\
+                diff = 0;\n\
+            }\n\
+        } else {\n\
+            diff = read_vlc_symbol(sc.gb, sb, bits);\n\
+        }\n\
+\n\
+        if (pr[0] < 0)\n\
+            diff = -diff;\n\
+\n\
+        uint v = zero_extend(pr[1] + diff, bits);\n\
+        imageStore(dec[p], sp + LADDR(ivec2(x, y)), uvec4(v));\n\
+    }\n\
+}\n\
+#endif\n\
+\n\
+#ifdef RGB\n\
+ivec4 transform_sample(ivec4 pix, ivec2 rct_coef)\n\
+{\n\
+    pix.b -= rct_offset;\n\
+    pix.r -= rct_offset;\n\
+    pix.g -= (pix.b*rct_coef.y + pix.r*rct_coef.x) >> 2;\n\
+    pix.b += pix.g;\n\
+    pix.r += pix.g;\n\
+    return ivec4(pix[fmt_lut[0]], pix[fmt_lut[1]],\n\
+                 pix[fmt_lut[2]], pix[fmt_lut[3]]);\n\
+}\n\
+\n\
+void writeout_rgb(in SliceContext sc, ivec2 sp, int w, int y, bool apply_rct)\n\
+{\n\
+    for (uint x = gl_LocalInvocationID.x; x < w; x += gl_WorkGroupSize.x) {\n\
+        ivec2 lpos = sp + LADDR(ivec2(x, y));\n\
+        ivec2 pos = sc.slice_pos + ivec2(x, y);\n\
+\n\
+        ivec4 pix;\n\
+        pix.r = int(imageLoad(dec[2], lpos)[0]);\n\
+        pix.g = int(imageLoad(dec[0], lpos)[0]);\n\
+        pix.b = int(imageLoad(dec[1], lpos)[0]);\n\
+        if (transparency != 0)\n\
+            pix.a = int(imageLoad(dec[3], lpos)[0]);\n\
+\n\
+        if (expectEXT(apply_rct, true))\n\
+            pix = transform_sample(pix, sc.slice_rct_coef);\n\
+\n\
+        imageStore(dst[0], pos, pix);\n\
+        if (planar_rgb != 0) {\n\
+            for (int i = 1; i < color_planes; i++)\n\
+                imageStore(dst[i], pos, ivec4(pix[i]));\n\
+        }\n\
+    }\n\
+}\n\
+#endif\n\
+\n\
+void decode_slice(inout SliceContext sc, const uint slice_idx)\n\
+{\n\
+    int w = sc.slice_dim.x;\n\
+    ivec2 sp = sc.slice_pos;\n\
+\n\
+#ifndef RGB\n\
+    int bits = bits_per_raw_sample;\n\
+#else\n\
+    int bits = 9;\n\
+    if (bits != 8 || sc.slice_coding_mode != 0)\n\
+        bits = bits_per_raw_sample + int(sc.slice_coding_mode != 1);\n\
+\n\
+    sp.y = int(gl_WorkGroupID.y)*RGB_LINECACHE;\n\
+#endif\n\
+\n\
+    /* PCM coding */\n\
+#ifndef GOLOMB\n\
+    if (sc.slice_coding_mode == 1) {\n\
+#ifndef RGB\n\
+        for (int p = 0; p < planes; p++) {\n\
+            int h = sc.slice_dim.y;\n\
+            if (p > 0 && p < 3)\n\
+                h >>= chroma_shift.y;\n\
+\n\
+            for (int y = 0; y < h; y++)\n\
+                decode_line_pcm(sc, sp, w, y, p, bits);\n\
+        }\n\
+#else\n\
+        for (int y = 0; y < sc.slice_dim.y; y++) {\n\
+            for (int p = 0; p < color_planes; p++)\n\
+                decode_line_pcm(sc, sp, w, y, p, bits);\n\
+\n\
+            writeout_rgb(sc, sp, w, y, false);\n\
+        }\n\
+#endif\n\
+    } else\n\
+\n\
+    /* Arithmetic coding */\n\
+#endif\n\
+    {\n\
+        u8vec4 quant_table_idx = sc.quant_table_idx.xyyz;\n\
+        u32vec4 slice_state_off = (slice_idx*codec_planes + uvec4(0, 1, 1, 2))*plane_state_size;\n\
+\n\
+#ifndef RGB\n\
+        for (int p = 0; p < planes; p++) {\n\
+            int h = sc.slice_dim.y;\n\
+            if (p > 0 && p < 3)\n\
+                h >>= chroma_shift.y;\n\
+\n\
+            int run_index = 0;\n\
+            for (int y = 0; y < h; y++)\n\
+                decode_line(sc, sp, w, y, p, bits,\n\
+                            slice_state_off[p], quant_table_idx[p], run_index);\n\
+        }\n\
+#else\n\
+        int run_index = 0;\n\
+        for (int y = 0; y < sc.slice_dim.y; y++) {\n\
+            for (int p = 0; p < color_planes; p++)\n\
+                decode_line(sc, sp, w, y, p, bits,\n\
+                            slice_state_off[p], quant_table_idx[p], run_index);\n\
+\n\
+            writeout_rgb(sc, sp, w, y, true);\n\
+        }\n\
+#endif\n\
+    }\n\
+}\n\
+\n\
+void main(void)\n\
+{\n\
+    const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;\n\
+    decode_slice(slice_ctx[slice_idx], slice_idx);\n\
+\n\
+    uint32_t status = corrupt ? uint32_t(corrupt) : overread;\n\
+    if (status != 0)\n\
+        slice_status[2*slice_idx + 1] = status;\n\
+}";
+
+const char *ff_source_prores_raw_comp  = "\
+#define I16(x) (int16_t(x))\n\
+\n\
+#define COMP_ID (gl_LocalInvocationID.z)\n\
+#define BLOCK_ID (gl_LocalInvocationID.y)\n\
+#define ROW_ID (gl_LocalInvocationID.x)\n\
+\n\
+GetBitContext gb;\n\
+shared float btemp[gl_WorkGroupSize.z][16][64] = { };\n\
+shared float block[gl_WorkGroupSize.z][16][64];\n\
+\n\
+void idct8_horiz(const uint row_id)\n\
+{\n\
+    float t0, t1, t2, t3, t4, t5, t6, t7, u8;\n\
+    float u0, u1, u2, u3, u4, u5, u6, u7;\n\
+\n\
+    /* Input */\n\
+    t0 = block[COMP_ID][BLOCK_ID][8*row_id + 0];\n\
+    u4 = block[COMP_ID][BLOCK_ID][8*row_id + 1];\n\
+    t2 = block[COMP_ID][BLOCK_ID][8*row_id + 2];\n\
+    u6 = block[COMP_ID][BLOCK_ID][8*row_id + 3];\n\
+    t1 = block[COMP_ID][BLOCK_ID][8*row_id + 4];\n\
+    u5 = block[COMP_ID][BLOCK_ID][8*row_id + 5];\n\
+    t3 = block[COMP_ID][BLOCK_ID][8*row_id + 6];\n\
+    u7 = block[COMP_ID][BLOCK_ID][8*row_id + 7];\n\
+\n\
+    /* Embedded scaled inverse 4-point Type-II DCT */\n\
+    u0 = t0 + t1;\n\
+    u1 = t0 - t1;\n\
+    u3 = t2 + t3;\n\
+    u2 = (t2 - t3)*(1.4142135623730950488016887242097f) - u3;\n\
+    t0 = u0 + u3;\n\
+    t3 = u0 - u3;\n\
+    t1 = u1 + u2;\n\
+    t2 = u1 - u2;\n\
+\n\
+    /* Embedded scaled inverse 4-point Type-IV DST */\n\
+    t5 = u5 + u6;\n\
+    t6 = u5 - u6;\n\
+    t7 = u4 + u7;\n\
+    t4 = u4 - u7;\n\
+    u7 = t7 + t5;\n\
+    u5 = (t7 - t5)*(1.4142135623730950488016887242097f);\n\
+    u8 = (t4 + t6)*(1.8477590650225735122563663787936f);\n\
+    u4 = u8 - t4*(1.0823922002923939687994464107328f);\n\
+    u6 = u8 - t6*(2.6131259297527530557132863468544f);\n\
+    t7 = u7;\n\
+    t6 = t7 - u6;\n\
+    t5 = t6 + u5;\n\
+    t4 = t5 - u4;\n\
+\n\
+    /* Butterflies */\n\
+    u0 = t0 + t7;\n\
+    u7 = t0 - t7;\n\
+    u6 = t1 + t6;\n\
+    u1 = t1 - t6;\n\
+    u2 = t2 + t5;\n\
+    u5 = t2 - t5;\n\
+    u4 = t3 + t4;\n\
+    u3 = t3 - t4;\n\
+\n\
+    /* Output */\n\
+    btemp[COMP_ID][BLOCK_ID][0*8 + row_id] = u0;\n\
+    btemp[COMP_ID][BLOCK_ID][1*8 + row_id] = u1;\n\
+    btemp[COMP_ID][BLOCK_ID][2*8 + row_id] = u2;\n\
+    btemp[COMP_ID][BLOCK_ID][3*8 + row_id] = u3;\n\
+    btemp[COMP_ID][BLOCK_ID][4*8 + row_id] = u4;\n\
+    btemp[COMP_ID][BLOCK_ID][5*8 + row_id] = u5;\n\
+    btemp[COMP_ID][BLOCK_ID][6*8 + row_id] = u6;\n\
+    btemp[COMP_ID][BLOCK_ID][7*8 + row_id] = u7;\n\
+}\n\
+\n\
+void idct8_vert(const uint row_id)\n\
+{\n\
+    float t0, t1, t2, t3, t4, t5, t6, t7, u8;\n\
+    float u0, u1, u2, u3, u4, u5, u6, u7;\n\
+\n\
+    /* Input */\n\
+    t0 = btemp[COMP_ID][BLOCK_ID][8*row_id + 0] + 0.5f; // NOTE\n\
+    u4 = btemp[COMP_ID][BLOCK_ID][8*row_id + 1];\n\
+    t2 = btemp[COMP_ID][BLOCK_ID][8*row_id + 2];\n\
+    u6 = btemp[COMP_ID][BLOCK_ID][8*row_id + 3];\n\
+    t1 = btemp[COMP_ID][BLOCK_ID][8*row_id + 4];\n\
+    u5 = btemp[COMP_ID][BLOCK_ID][8*row_id + 5];\n\
+    t3 = btemp[COMP_ID][BLOCK_ID][8*row_id + 6];\n\
+    u7 = btemp[COMP_ID][BLOCK_ID][8*row_id + 7];\n\
+\n\
+    /* Embedded scaled inverse 4-point Type-II DCT */\n\
+    u0 = t0 + t1;\n\
+    u1 = t0 - t1;\n\
+    u3 = t2 + t3;\n\
+    u2 = (t2 - t3)*(1.4142135623730950488016887242097f) - u3;\n\
+    t0 = u0 + u3;\n\
+    t3 = u0 - u3;\n\
+    t1 = u1 + u2;\n\
+    t2 = u1 - u2;\n\
+\n\
+    /* Embedded scaled inverse 4-point Type-IV DST */\n\
+    t5 = u5 + u6;\n\
+    t6 = u5 - u6;\n\
+    t7 = u4 + u7;\n\
+    t4 = u4 - u7;\n\
+    u7 = t7 + t5;\n\
+    u5 = (t7 - t5)*(1.4142135623730950488016887242097f);\n\
+    u8 = (t4 + t6)*(1.8477590650225735122563663787936f);\n\
+    u4 = u8 - t4*(1.0823922002923939687994464107328f);\n\
+    u6 = u8 - t6*(2.6131259297527530557132863468544f);\n\
+    t7 = u7;\n\
+    t6 = t7 - u6;\n\
+    t5 = t6 + u5;\n\
+    t4 = t5 - u4;\n\
+\n\
+    /* Butterflies */\n\
+    u0 = t0 + t7;\n\
+    u7 = t0 - t7;\n\
+    u6 = t1 + t6;\n\
+    u1 = t1 - t6;\n\
+    u2 = t2 + t5;\n\
+    u5 = t2 - t5;\n\
+    u4 = t3 + t4;\n\
+    u3 = t3 - t4;\n\
+\n\
+    /* Output */\n\
+    block[COMP_ID][BLOCK_ID][0*8 + row_id] = u0;\n\
+    block[COMP_ID][BLOCK_ID][1*8 + row_id] = u1;\n\
+    block[COMP_ID][BLOCK_ID][2*8 + row_id] = u2;\n\
+    block[COMP_ID][BLOCK_ID][3*8 + row_id] = u3;\n\
+    block[COMP_ID][BLOCK_ID][4*8 + row_id] = u4;\n\
+    block[COMP_ID][BLOCK_ID][5*8 + row_id] = u5;\n\
+    block[COMP_ID][BLOCK_ID][6*8 + row_id] = u6;\n\
+    block[COMP_ID][BLOCK_ID][7*8 + row_id] = u7;\n\
+}\n\
+\n\
+int16_t get_value(int16_t codebook)\n\
+{\n\
+    const int16_t switch_bits = codebook >> 8;\n\
+    const int16_t rice_order  = codebook & I16(0xf);\n\
+    const int16_t exp_order   = (codebook >> 4) & I16(0xf);\n\
+\n\
+    uint32_t b = show_bits(gb, 32);\n\
+    if (expectEXT(b == 0, false))\n\
+        return I16(0);\n\
+    int16_t q = I16(31) - I16(findMSB(b));\n\
+\n\
+    if ((b & 0x80000000) != 0) {\n\
+        skip_bits(gb, 1 + rice_order);\n\
+        return I16((b & 0x7FFFFFFF) >> (31 - rice_order));\n\
+    }\n\
+\n\
+    if (q <= switch_bits) {\n\
+        skip_bits(gb, q + rice_order + 1);\n\
+        return I16((q << rice_order) +\n\
+                   (((b << (q + 1)) >> 1) >> (31 - rice_order)));\n\
+    }\n\
+\n\
+    int16_t bits = exp_order + (q << 1) - switch_bits;\n\
+    skip_bits(gb, bits);\n\
+    return I16((b >> (32 - bits)) +\n\
+               ((switch_bits + 1) << rice_order) -\n\
+               (1 << exp_order));\n\
+}\n\
+\n\
+#define TODCCODEBOOK(x) ((x + 1) >> 1)\n\
+\n\
+void read_dc_vals(const uint nb_blocks)\n\
+{\n\
+    int16_t dc, dc_add;\n\
+    int16_t prev_dc = I16(0), sign = I16(0);\n\
+\n\
+    /* Special handling for first block */\n\
+    dc = get_value(I16(700));\n\
+    prev_dc = (dc >> 1) ^ -(dc & I16(1));\n\
+    btemp[COMP_ID][0][0] = prev_dc;\n\
+\n\
+    for (uint n = 1; n < nb_blocks; n++) {\n\
+        if (expectEXT(left_bits(gb) <= 0, false))\n\
+            break;\n\
+\n\
+        uint8_t dc_codebook;\n\
+        if ((n & 15) == 1)\n\
+            dc_codebook = uint8_t(100);\n\
+        else\n\
+            dc_codebook = dc_cb[min(TODCCODEBOOK(dc), 13 - 1)];\n\
+\n\
+        dc = get_value(dc_codebook);\n\
+\n\
+        sign = sign ^ dc & int16_t(1);\n\
+        dc_add = (-sign ^ I16(TODCCODEBOOK(dc))) + sign;\n\
+        sign = I16(dc_add < 0);\n\
+        prev_dc += dc_add;\n\
+\n\
+        btemp[COMP_ID][n][0] = prev_dc;\n\
+    }\n\
+}\n\
+\n\
+void read_ac_vals(const uint nb_blocks)\n\
+{\n\
+    const uint nb_codes = nb_blocks << 6;\n\
+    const uint log2_nb_blocks = findMSB(nb_blocks);\n\
+    const uint block_mask = (1 << log2_nb_blocks) - 1;\n\
+\n\
+    int16_t ac, rn, ln;\n\
+    int16_t ac_codebook = I16(49);\n\
+    int16_t rn_codebook = I16( 0);\n\
+    int16_t ln_codebook = I16(66);\n\
+    int16_t sign;\n\
+    int16_t val;\n\
+\n\
+    for (uint n = nb_blocks; n <= nb_codes;) {\n\
+        if (expectEXT(left_bits(gb) <= 0, false))\n\
+            break;\n\
+\n\
+        ln = get_value(ln_codebook);\n\
+        for (uint i = 0; i < ln; i++) {\n\
+            if (expectEXT(left_bits(gb) <= 0, false))\n\
+                break;\n\
+\n\
+            if (expectEXT(n >= nb_codes, false))\n\
+                break;\n\
+\n\
+            ac = get_value(ac_codebook);\n\
+            ac_codebook = ac_cb[min(ac, 95 - 1)];\n\
+            sign = -int16_t(get_bit(gb));\n\
+\n\
+            val = ((ac + I16(1)) ^ sign) - sign;\n\
+            btemp[COMP_ID][n & block_mask][n >> log2_nb_blocks] = val;\n\
+\n\
+            n++;\n\
+        }\n\
+\n\
+        if (expectEXT(n >= nb_codes, false))\n\
+            break;\n\
+\n\
+        rn = get_value(rn_codebook);\n\
+        rn_codebook = rn_cb[min(rn, 28 - 1)];\n\
+\n\
+        n += rn + 1;\n\
+        if (expectEXT(n >= nb_codes, false))\n\
+            break;\n\
+\n\
+        if (expectEXT(left_bits(gb) <= 0, false))\n\
+            break;\n\
+\n\
+        ac = get_value(ac_codebook);\n\
+        sign = -int16_t(get_bit(gb));\n\
+\n\
+        val = ((ac + I16(1)) ^ sign) - sign;\n\
+        btemp[COMP_ID][n & block_mask][n >> log2_nb_blocks] = val;\n\
+\n\
+        ac_codebook = ac_cb[min(ac, 95 - 1)];\n\
+        ln_codebook = ln_cb[min(ac, 15 - 1)];\n\
+\n\
+        n++;\n\
+    }\n\
+}\n\
+\n\
+void main(void)\n\
+{\n\
+    const uint tile_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;\n\
+    TileData td = tile_data[tile_idx];\n\
+\n\
+    if (expectEXT(td.pos.x >= frame_size.x, false))\n\
+        return;\n\
+\n\
+    uint64_t pkt_offset = uint64_t(pkt_data) + td.offset;\n\
+    u8vec2buf hdr_data = u8vec2buf(pkt_offset);\n\
+    float qscale = float(pack16(hdr_data[0].v.yx)) / 2.0f;\n\
+\n\
+    ivec4 size = ivec4(td.size,\n\
+                       pack16(hdr_data[2].v.yx),\n\
+                       pack16(hdr_data[1].v.yx),\n\
+                       pack16(hdr_data[3].v.yx));\n\
+    size[0] = size[0] - size[1] - size[2] - size[3] - 8;\n\
+    if (expectEXT(size[0] < 0, false))\n\
+        return;\n\
+\n\
+    const ivec2 offs = td.pos + ivec2(COMP_ID & 1, COMP_ID >> 1);\n\
+    const uint w = min(tile_size.x, frame_size.x - td.pos.x) / 2;\n\
+    const uint nb_blocks = w / 8;\n\
+\n\
+    const ivec4 comp_offset = ivec4(size[2] + size[1] + size[3],\n\
+                                    size[2],\n\
+                                    0,\n\
+                                    size[2] + size[1]);\n\
+\n\
+    if (BLOCK_ID == 0 && ROW_ID == 0) {\n\
+        init_get_bits(gb, u8buf(pkt_offset + 8 + comp_offset[COMP_ID]),\n\
+                      size[COMP_ID]);\n\
+        read_dc_vals(nb_blocks);\n\
+        read_ac_vals(nb_blocks);\n\
+    }\n\
+\n\
+    barrier();\n\
+\n\
+    [[unroll]]\n\
+    for (uint i = gl_LocalInvocationID.x; i < 64; i += gl_WorkGroupSize.x)\n\
+        block[COMP_ID][BLOCK_ID][i] = (btemp[COMP_ID][BLOCK_ID][scan[i]] / 16384.0) *\n\
+                                      (float(qmat[i]) / 295.0) *\n\
+                                      idct_8x8_scales[i] * qscale;\n\
+\n\
+    barrier();\n\
+\n\
+#ifdef PARALLEL_ROWS\n\
+    idct8_horiz(ROW_ID);\n\
+\n\
+    barrier();\n\
+\n\
+    idct8_vert(ROW_ID);\n\
+#else\n\
+    for (uint j = 0; j < 8; j++)\n\
+        idct8_horiz(j);\n\
+\n\
+    barrier();\n\
+\n\
+    for (uint j = 0; j < 8; j++)\n\
+        idct8_vert(j);\n\
+#endif\n\
+\n\
+    barrier();\n\
+\n\
+    [[unroll]]\n\
+    for (uint i = gl_LocalInvocationID.x; i < 64; i += gl_WorkGroupSize.x)\n\
+         imageStore(dst,\n\
+                    offs + 2*ivec2(BLOCK_ID*8 + (i & 7), i >> 3),\n\
+                    vec4(block[COMP_ID][BLOCK_ID][i]));\n\
+}";
-- 
2.49.1


From c4a23dca6cba9996ef0be2146bf866822e0a3a6f Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:40:51 +0000
Subject: [PATCH 088/118] Changing vulkan file directory

---
 libavcodec/vulkan/vulkan_source.h | 35 +++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 libavcodec/vulkan/vulkan_source.h

diff --git a/libavcodec/vulkan/vulkan_source.h b/libavcodec/vulkan/vulkan_source.h
new file mode 100644
index 0000000000..35543b6d62
--- /dev/null
+++ b/libavcodec/vulkan/vulkan_source.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_VULKAN_SOURCE_H
+#define AVCODEC_VULKAN_SOURCE_H
+
+extern const char *ff_source_common_comp;
+extern const char *ff_source_ffv1_common_comp;
+extern const char *ff_source_ffv1_dec_comp;
+extern const char *ff_source_ffv1_dec_setup_comp;
+extern const char *ff_source_ffv1_enc_comp;
+extern const char *ff_source_ffv1_enc_rct_comp;
+extern const char *ff_source_ffv1_enc_setup_comp;
+extern const char *ff_source_ffv1_rct_comp;
+extern const char *ff_source_ffv1_rct_search_comp;
+extern const char *ff_source_ffv1_reset_comp;
+extern const char *ff_source_ffv1_vlc_comp;
+extern const char *ff_source_rangecoder_comp;
+
+#endif /* AVCODEC_VULKAN_SOURCE_H */
-- 
2.49.1


From 3c50d01c71836754d4f862ff9bd0af2445175705 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:41:33 +0000
Subject: [PATCH 089/118] Changing vulkan file directory

---
 libavcodec/vulkan_video.c | 482 --------------------------------------
 1 file changed, 482 deletions(-)
 delete mode 100644 libavcodec/vulkan_video.c

diff --git a/libavcodec/vulkan_video.c b/libavcodec/vulkan_video.c
deleted file mode 100644
index 819940460f..0000000000
--- a/libavcodec/vulkan_video.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/mem.h"
-#include "vulkan_video.h"
-
-#define ASPECT_2PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT)
-#define ASPECT_3PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT)
-
-static const struct FFVkFormatMapEntry {
-    VkFormat vkf;
-    enum AVPixelFormat pixfmt;
-    VkImageAspectFlags aspect;
-} vk_format_map[] = {
-    /* Gray formats */
-    { VK_FORMAT_R8_UNORM,   AV_PIX_FMT_GRAY8,   VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GRAY16,  VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GRAYF32, VK_IMAGE_ASPECT_COLOR_BIT },
-
-    /* RGB formats */
-    { VK_FORMAT_B8G8R8A8_UNORM,           AV_PIX_FMT_BGRA,    VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_R8G8B8A8_UNORM,           AV_PIX_FMT_RGBA,    VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_R8G8B8_UNORM,             AV_PIX_FMT_RGB24,   VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_B8G8R8_UNORM,             AV_PIX_FMT_BGR24,   VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_R16G16B16_UNORM,          AV_PIX_FMT_RGB48,   VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_R16G16B16A16_UNORM,       AV_PIX_FMT_RGBA64,  VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_R5G6B5_UNORM_PACK16,      AV_PIX_FMT_RGB565,  VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_B5G6R5_UNORM_PACK16,      AV_PIX_FMT_BGR565,  VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_B8G8R8A8_UNORM,           AV_PIX_FMT_BGR0,    VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_R8G8B8A8_UNORM,           AV_PIX_FMT_RGB0,    VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_A2R10G10B10_UNORM_PACK32, AV_PIX_FMT_X2RGB10, VK_IMAGE_ASPECT_COLOR_BIT },
-
-    /* Planar RGB */
-    { VK_FORMAT_R8_UNORM,   AV_PIX_FMT_GBRAP,    VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRAP16,  VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GBRPF32,  VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GBRAPF32, VK_IMAGE_ASPECT_COLOR_BIT },
-
-    /* Two-plane 420 YUV at 8, 10, 12 and 16 bits */
-    { VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,                  AV_PIX_FMT_NV12, ASPECT_2PLANE },
-    { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, AV_PIX_FMT_P010, ASPECT_2PLANE },
-    { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, AV_PIX_FMT_P012, ASPECT_2PLANE },
-    { VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,               AV_PIX_FMT_P016, ASPECT_2PLANE },
-
-    /* Two-plane 422 YUV at 8, 10 and 16 bits */
-    { VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,                  AV_PIX_FMT_NV16, ASPECT_2PLANE },
-    { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, AV_PIX_FMT_P210, ASPECT_2PLANE },
-    { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, AV_PIX_FMT_P212, ASPECT_2PLANE },
-    { VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,               AV_PIX_FMT_P216, ASPECT_2PLANE },
-
-    /* Two-plane 444 YUV at 8, 10 and 16 bits */
-    { VK_FORMAT_G8_B8R8_2PLANE_444_UNORM,                  AV_PIX_FMT_NV24, ASPECT_2PLANE },
-    { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16, AV_PIX_FMT_P410, ASPECT_2PLANE },
-    { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16, AV_PIX_FMT_P412, ASPECT_2PLANE },
-    { VK_FORMAT_G16_B16R16_2PLANE_444_UNORM,               AV_PIX_FMT_P416, ASPECT_2PLANE },
-
-    /* Three-plane 420, 422, 444 at 8, 10, 12 and 16 bits */
-    { VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,    AV_PIX_FMT_YUV420P,   ASPECT_3PLANE },
-    { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P10, ASPECT_3PLANE },
-    { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P12, ASPECT_3PLANE },
-    { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P16, ASPECT_3PLANE },
-    { VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,    AV_PIX_FMT_YUV422P,   ASPECT_3PLANE },
-    { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P10, ASPECT_3PLANE },
-    { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P12, ASPECT_3PLANE },
-    { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P16, ASPECT_3PLANE },
-    { VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,    AV_PIX_FMT_YUV444P,   ASPECT_3PLANE },
-    { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P10, ASPECT_3PLANE },
-    { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P12, ASPECT_3PLANE },
-    { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P16, ASPECT_3PLANE },
-
-    /* Single plane 422 at 8, 10, 12 and 16 bits */
-    { VK_FORMAT_G8B8G8R8_422_UNORM,                     AV_PIX_FMT_YUYV422, VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_B8G8R8G8_422_UNORM,                     AV_PIX_FMT_UYVY422, VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, AV_PIX_FMT_Y210,    VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, AV_PIX_FMT_Y212,    VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_G16B16G16R16_422_UNORM,                 AV_PIX_FMT_Y216,    VK_IMAGE_ASPECT_COLOR_BIT },
-
-    /* Single plane 444 at 10 and 12 bits */
-    { VK_FORMAT_A2R10G10B10_UNORM_PACK32,               AV_PIX_FMT_XV30,    VK_IMAGE_ASPECT_COLOR_BIT },
-    { VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,     AV_PIX_FMT_XV36,    VK_IMAGE_ASPECT_COLOR_BIT },
-};
-static const int nb_vk_format_map = FF_ARRAY_ELEMS(vk_format_map);
-
-enum AVPixelFormat ff_vk_pix_fmt_from_vkfmt(VkFormat vkf)
-{
-    for (int i = 0; i < nb_vk_format_map; i++)
-        if (vk_format_map[i].vkf == vkf)
-            return vk_format_map[i].pixfmt;
-    return AV_PIX_FMT_NONE;
-}
-
-VkImageAspectFlags ff_vk_aspect_bits_from_vkfmt(VkFormat vkf)
-{
-    for (int i = 0; i < nb_vk_format_map; i++)
-        if (vk_format_map[i].vkf == vkf)
-            return vk_format_map[i].aspect;
-    return VK_IMAGE_ASPECT_NONE;
-}
-
-VkVideoChromaSubsamplingFlagBitsKHR ff_vk_subsampling_from_av_desc(const AVPixFmtDescriptor *desc)
-{
-    if (desc->nb_components == 1)
-        return VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR;
-    else if (!desc->log2_chroma_w && !desc->log2_chroma_h)
-        return VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR;
-    else if (!desc->log2_chroma_w && desc->log2_chroma_h == 1)
-        return VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR;
-    else if (desc->log2_chroma_w == 1 && desc->log2_chroma_h == 1)
-        return VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR;
-    return VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_KHR;
-}
-
-VkVideoComponentBitDepthFlagBitsKHR ff_vk_depth_from_av_depth(int depth)
-{
-    switch (depth) {
-    case  8: return VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR;
-    case 10: return VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR;
-    case 12: return VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR;
-    default: break;
-    }
-    return VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR;
-}
-
-int ff_vk_h264_level_to_av(StdVideoH264LevelIdc level)
-{
-    switch (level) {
-    case STD_VIDEO_H264_LEVEL_IDC_1_0: return 10;
-    case STD_VIDEO_H264_LEVEL_IDC_1_1: return 11;
-    case STD_VIDEO_H264_LEVEL_IDC_1_2: return 12;
-    case STD_VIDEO_H264_LEVEL_IDC_1_3: return 13;
-    case STD_VIDEO_H264_LEVEL_IDC_2_0: return 20;
-    case STD_VIDEO_H264_LEVEL_IDC_2_1: return 21;
-    case STD_VIDEO_H264_LEVEL_IDC_2_2: return 22;
-    case STD_VIDEO_H264_LEVEL_IDC_3_0: return 30;
-    case STD_VIDEO_H264_LEVEL_IDC_3_1: return 31;
-    case STD_VIDEO_H264_LEVEL_IDC_3_2: return 32;
-    case STD_VIDEO_H264_LEVEL_IDC_4_0: return 40;
-    case STD_VIDEO_H264_LEVEL_IDC_4_1: return 41;
-    case STD_VIDEO_H264_LEVEL_IDC_4_2: return 42;
-    case STD_VIDEO_H264_LEVEL_IDC_5_0: return 50;
-    case STD_VIDEO_H264_LEVEL_IDC_5_1: return 51;
-    case STD_VIDEO_H264_LEVEL_IDC_5_2: return 52;
-    case STD_VIDEO_H264_LEVEL_IDC_6_0: return 60;
-    case STD_VIDEO_H264_LEVEL_IDC_6_1: return 61;
-    default:
-    case STD_VIDEO_H264_LEVEL_IDC_6_2: return 62;
-    }
-}
-
-StdVideoH264LevelIdc ff_vk_h264_level_to_vk(int level_idc)
-{
-    switch (level_idc) {
-    case 10: return STD_VIDEO_H264_LEVEL_IDC_1_0;
-    case 11: return STD_VIDEO_H264_LEVEL_IDC_1_1;
-    case 12: return STD_VIDEO_H264_LEVEL_IDC_1_2;
-    case 13: return STD_VIDEO_H264_LEVEL_IDC_1_3;
-    case 20: return STD_VIDEO_H264_LEVEL_IDC_2_0;
-    case 21: return STD_VIDEO_H264_LEVEL_IDC_2_1;
-    case 22: return STD_VIDEO_H264_LEVEL_IDC_2_2;
-    case 30: return STD_VIDEO_H264_LEVEL_IDC_3_0;
-    case 31: return STD_VIDEO_H264_LEVEL_IDC_3_1;
-    case 32: return STD_VIDEO_H264_LEVEL_IDC_3_2;
-    case 40: return STD_VIDEO_H264_LEVEL_IDC_4_0;
-    case 41: return STD_VIDEO_H264_LEVEL_IDC_4_1;
-    case 42: return STD_VIDEO_H264_LEVEL_IDC_4_2;
-    case 50: return STD_VIDEO_H264_LEVEL_IDC_5_0;
-    case 51: return STD_VIDEO_H264_LEVEL_IDC_5_1;
-    case 52: return STD_VIDEO_H264_LEVEL_IDC_5_2;
-    case 60: return STD_VIDEO_H264_LEVEL_IDC_6_0;
-    case 61: return STD_VIDEO_H264_LEVEL_IDC_6_1;
-    default:
-    case 62: return STD_VIDEO_H264_LEVEL_IDC_6_2;
-    }
-}
-
-int ff_vk_h265_level_to_av(StdVideoH265LevelIdc level)
-{
-    switch (level) {
-    case STD_VIDEO_H265_LEVEL_IDC_1_0: return 10;
-    case STD_VIDEO_H265_LEVEL_IDC_2_0: return 20;
-    case STD_VIDEO_H265_LEVEL_IDC_2_1: return 21;
-    case STD_VIDEO_H265_LEVEL_IDC_3_0: return 30;
-    case STD_VIDEO_H265_LEVEL_IDC_3_1: return 31;
-    case STD_VIDEO_H265_LEVEL_IDC_4_0: return 40;
-    case STD_VIDEO_H265_LEVEL_IDC_4_1: return 41;
-    case STD_VIDEO_H265_LEVEL_IDC_5_0: return 50;
-    case STD_VIDEO_H265_LEVEL_IDC_5_1: return 51;
-    case STD_VIDEO_H265_LEVEL_IDC_6_0: return 60;
-    case STD_VIDEO_H265_LEVEL_IDC_6_1: return 61;
-    default:
-    case STD_VIDEO_H265_LEVEL_IDC_6_2: return 62;
-    }
-}
-
-StdVideoH265LevelIdc ff_vk_h265_level_to_vk(int level_idc)
-{
-    switch (level_idc) {
-    case 10: return STD_VIDEO_H265_LEVEL_IDC_1_0;
-    case 20: return STD_VIDEO_H265_LEVEL_IDC_2_0;
-    case 21: return STD_VIDEO_H265_LEVEL_IDC_2_1;
-    case 30: return STD_VIDEO_H265_LEVEL_IDC_3_0;
-    case 31: return STD_VIDEO_H265_LEVEL_IDC_3_1;
-    case 40: return STD_VIDEO_H265_LEVEL_IDC_4_0;
-    case 41: return STD_VIDEO_H265_LEVEL_IDC_4_1;
-    case 50: return STD_VIDEO_H265_LEVEL_IDC_5_0;
-    case 51: return STD_VIDEO_H265_LEVEL_IDC_5_1;
-    case 60: return STD_VIDEO_H265_LEVEL_IDC_6_0;
-    case 61: return STD_VIDEO_H265_LEVEL_IDC_6_1;
-    default:
-    case 62: return STD_VIDEO_H265_LEVEL_IDC_6_2;
-    }
-}
-
-StdVideoAV1Level ff_vk_av1_level_to_vk(int level)
-{
-    switch (level) {
-    case 20: return STD_VIDEO_AV1_LEVEL_2_0;
-    case 21: return STD_VIDEO_AV1_LEVEL_2_1;
-    case 22: return STD_VIDEO_AV1_LEVEL_2_2;
-    case 23: return STD_VIDEO_AV1_LEVEL_2_3;
-    case 30: return STD_VIDEO_AV1_LEVEL_3_0;
-    case 31: return STD_VIDEO_AV1_LEVEL_3_1;
-    case 32: return STD_VIDEO_AV1_LEVEL_3_2;
-    case 33: return STD_VIDEO_AV1_LEVEL_3_3;
-    case 40: return STD_VIDEO_AV1_LEVEL_4_0;
-    case 41: return STD_VIDEO_AV1_LEVEL_4_1;
-    case 42: return STD_VIDEO_AV1_LEVEL_4_2;
-    case 43: return STD_VIDEO_AV1_LEVEL_4_3;
-    case 50: return STD_VIDEO_AV1_LEVEL_5_0;
-    case 51: return STD_VIDEO_AV1_LEVEL_5_1;
-    case 52: return STD_VIDEO_AV1_LEVEL_5_2;
-    case 53: return STD_VIDEO_AV1_LEVEL_5_3;
-    case 60: return STD_VIDEO_AV1_LEVEL_6_0;
-    case 61: return STD_VIDEO_AV1_LEVEL_6_1;
-    case 62: return STD_VIDEO_AV1_LEVEL_6_2;
-    case 63: return STD_VIDEO_AV1_LEVEL_6_3;
-    case 70: return STD_VIDEO_AV1_LEVEL_7_0;
-    case 71: return STD_VIDEO_AV1_LEVEL_7_1;
-    case 72: return STD_VIDEO_AV1_LEVEL_7_2;
-    default:
-    case 73: return STD_VIDEO_AV1_LEVEL_7_3;
-    }
-}
-
-StdVideoH264ProfileIdc ff_vk_h264_profile_to_vk(int profile)
-{
-    switch (profile) {
-    case AV_PROFILE_H264_CONSTRAINED_BASELINE: return STD_VIDEO_H264_PROFILE_IDC_BASELINE;
-    case AV_PROFILE_H264_MAIN: return STD_VIDEO_H264_PROFILE_IDC_MAIN;
-    case AV_PROFILE_H264_HIGH: return STD_VIDEO_H264_PROFILE_IDC_HIGH;
-    case AV_PROFILE_H264_HIGH_444_PREDICTIVE: return STD_VIDEO_H264_PROFILE_IDC_HIGH_444_PREDICTIVE;
-    default: return STD_VIDEO_H264_PROFILE_IDC_INVALID;
-    }
-}
-
-StdVideoH265ProfileIdc ff_vk_h265_profile_to_vk(int profile)
-{
-    switch (profile) {
-    case AV_PROFILE_HEVC_MAIN:    return STD_VIDEO_H265_PROFILE_IDC_MAIN;
-    case AV_PROFILE_HEVC_MAIN_10: return STD_VIDEO_H265_PROFILE_IDC_MAIN_10;
-    case AV_PROFILE_HEVC_REXT:    return STD_VIDEO_H265_PROFILE_IDC_FORMAT_RANGE_EXTENSIONS;
-    default: return STD_VIDEO_H265_PROFILE_IDC_INVALID;
-    }
-}
-
-StdVideoAV1Profile ff_vk_av1_profile_to_vk(int profile)
-{
-    switch (profile) {
-    case AV_PROFILE_AV1_MAIN: return STD_VIDEO_AV1_PROFILE_MAIN;
-    case AV_PROFILE_AV1_HIGH: return STD_VIDEO_AV1_PROFILE_HIGH;
-    case AV_PROFILE_AV1_PROFESSIONAL: return STD_VIDEO_AV1_PROFILE_PROFESSIONAL;
-    default: return STD_VIDEO_AV1_PROFILE_INVALID;
-    }
-}
-
-int ff_vk_create_view(FFVulkanContext *s, FFVkVideoCommon *common,
-                      VkImageView *view, VkImageAspectFlags *aspect,
-                      AVVkFrame *src, VkFormat vkf, int is_dpb)
-{
-    VkResult ret;
-    FFVulkanFunctions *vk = &s->vkfn;
-    VkImageAspectFlags aspect_mask = ff_vk_aspect_bits_from_vkfmt(vkf);
-
-    VkSamplerYcbcrConversionInfo yuv_sampler_info = {
-        .sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
-        .conversion = common->yuv_sampler,
-    };
-    VkImageViewCreateInfo img_view_create_info = {
-        .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
-        .pNext = &yuv_sampler_info,
-        .viewType = common->layered_dpb && is_dpb ?
-                    VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D,
-        .format = vkf,
-        .image = src->img[0],
-        .components = (VkComponentMapping) {
-            .r = VK_COMPONENT_SWIZZLE_IDENTITY,
-            .g = VK_COMPONENT_SWIZZLE_IDENTITY,
-            .b = VK_COMPONENT_SWIZZLE_IDENTITY,
-            .a = VK_COMPONENT_SWIZZLE_IDENTITY,
-        },
-        .subresourceRange = (VkImageSubresourceRange) {
-            .aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT,
-            .baseArrayLayer = 0,
-            .layerCount     = common->layered_dpb && is_dpb ?
-                              VK_REMAINING_ARRAY_LAYERS : 1,
-            .levelCount     = 1,
-        },
-    };
-
-    ret = vk->CreateImageView(s->hwctx->act_dev, &img_view_create_info,
-                              s->hwctx->alloc, view);
-    if (ret != VK_SUCCESS)
-        return AVERROR_EXTERNAL;
-
-    *aspect = aspect_mask;
-
-    return 0;
-}
-
-av_cold void ff_vk_video_common_uninit(FFVulkanContext *s,
-                                       FFVkVideoCommon *common)
-{
-    FFVulkanFunctions *vk = &s->vkfn;
-
-    if (common->session) {
-        vk->DestroyVideoSessionKHR(s->hwctx->act_dev, common->session,
-                                   s->hwctx->alloc);
-        common->session = VK_NULL_HANDLE;
-    }
-
-    if (common->nb_mem && common->mem)
-        for (int i = 0; i < common->nb_mem; i++)
-            vk->FreeMemory(s->hwctx->act_dev, common->mem[i], s->hwctx->alloc);
-
-    av_freep(&common->mem);
-
-    if (common->layered_view)
-        vk->DestroyImageView(s->hwctx->act_dev, common->layered_view,
-                             s->hwctx->alloc);
-
-    av_frame_free(&common->layered_frame);
-
-    av_buffer_unref(&common->dpb_hwfc_ref);
-
-    if (common->yuv_sampler)
-        vk->DestroySamplerYcbcrConversion(s->hwctx->act_dev, common->yuv_sampler,
-                                          s->hwctx->alloc);
-}
-
-av_cold int ff_vk_video_common_init(AVCodecContext *avctx, FFVulkanContext *s,
-                                    FFVkVideoCommon *common,
-                                    VkVideoSessionCreateInfoKHR *session_create)
-{
-    int err;
-    VkResult ret;
-    FFVulkanFunctions *vk = &s->vkfn;
-    VkVideoSessionMemoryRequirementsKHR *mem = NULL;
-    VkBindVideoSessionMemoryInfoKHR *bind_mem = NULL;
-
-    int cxpos = 0, cypos = 0;
-    VkSamplerYcbcrConversionCreateInfo yuv_sampler_info = {
-        .sType      = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
-        .components = ff_comp_identity_map,
-        .ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
-        .ycbcrRange = avctx->color_range == AVCOL_RANGE_MPEG, /* Ignored */
-        .format     = session_create->pictureFormat,
-    };
-
-    /* Create identity YUV sampler
-     * (VkImageViews of YUV image formats require it, even if it does nothing) */
-    av_chroma_location_enum_to_pos(&cxpos, &cypos, avctx->chroma_sample_location);
-    yuv_sampler_info.xChromaOffset = cxpos >> 7;
-    yuv_sampler_info.yChromaOffset = cypos >> 7;
-    ret = vk->CreateSamplerYcbcrConversion(s->hwctx->act_dev, &yuv_sampler_info,
-                                           s->hwctx->alloc, &common->yuv_sampler);
-    if (ret != VK_SUCCESS)
-        return AVERROR_EXTERNAL;
-
-    /* Create session */
-    ret = vk->CreateVideoSessionKHR(s->hwctx->act_dev, session_create,
-                                    s->hwctx->alloc, &common->session);
-    if (ret != VK_SUCCESS)
-        return AVERROR_EXTERNAL;
-
-    /* Get memory requirements */
-    ret = vk->GetVideoSessionMemoryRequirementsKHR(s->hwctx->act_dev,
-                                                   common->session,
-                                                   &common->nb_mem,
-                                                   NULL);
-    if (ret != VK_SUCCESS) {
-        err = AVERROR_EXTERNAL;
-        goto fail;
-    }
-
-    /* Allocate all memory needed to actually allocate memory */
-    common->mem = av_mallocz(sizeof(*common->mem)*common->nb_mem);
-    if (!common->mem) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-    mem = av_mallocz(sizeof(*mem)*common->nb_mem);
-    if (!mem) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-    bind_mem = av_mallocz(sizeof(*bind_mem)*common->nb_mem);
-    if (!bind_mem) {
-        err = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    /* Set the needed fields to get the memory requirements */
-    for (int i = 0; i < common->nb_mem; i++) {
-        mem[i] = (VkVideoSessionMemoryRequirementsKHR) {
-            .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_MEMORY_REQUIREMENTS_KHR,
-        };
-    }
-
-    /* Finally get the memory requirements */
-    ret = vk->GetVideoSessionMemoryRequirementsKHR(s->hwctx->act_dev,
-                                                   common->session, &common->nb_mem,
-                                                   mem);
-    if (ret != VK_SUCCESS) {
-        err = AVERROR_EXTERNAL;
-        goto fail;
-    }
-
-    /* Now allocate each requested memory.
-     * For ricing, could pool together memory that ends up in the same index. */
-    for (int i = 0; i < common->nb_mem; i++) {
-        err = ff_vk_alloc_mem(s, &mem[i].memoryRequirements,
-                              UINT32_MAX, NULL, NULL, &common->mem[i]);
-        if (err < 0)
-            goto fail;
-
-        bind_mem[i] = (VkBindVideoSessionMemoryInfoKHR) {
-            .sType = VK_STRUCTURE_TYPE_BIND_VIDEO_SESSION_MEMORY_INFO_KHR,
-            .memory = common->mem[i],
-            .memoryBindIndex = mem[i].memoryBindIndex,
-            .memoryOffset = 0,
-            .memorySize = mem[i].memoryRequirements.size,
-        };
-
-        av_log(avctx, AV_LOG_VERBOSE, "Allocating %"PRIu64" bytes in bind index %i for video session\n",
-               bind_mem[i].memorySize, bind_mem[i].memoryBindIndex);
-    }
-
-    /* Bind the allocated memory */
-    ret = vk->BindVideoSessionMemoryKHR(s->hwctx->act_dev, common->session,
-                                        common->nb_mem, bind_mem);
-    if (ret != VK_SUCCESS) {
-        err = AVERROR_EXTERNAL;
-        goto fail;
-    }
-
-    av_freep(&mem);
-    av_freep(&bind_mem);
-
-    return 0;
-
-fail:
-    av_freep(&mem);
-    av_freep(&bind_mem);
-
-    ff_vk_video_common_uninit(s, common);
-    return err;
-}
-- 
2.49.1


From 129144fc65ec1b7ec3c028265eb2efa03b3e0ea8 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:42:03 +0000
Subject: [PATCH 090/118] Changing vulkan file directory

---
 libavcodec/vulkan/vulkan_video.c | 482 +++++++++++++++++++++++++++++++
 1 file changed, 482 insertions(+)
 create mode 100644 libavcodec/vulkan/vulkan_video.c

diff --git a/libavcodec/vulkan/vulkan_video.c b/libavcodec/vulkan/vulkan_video.c
new file mode 100644
index 0000000000..819940460f
--- /dev/null
+++ b/libavcodec/vulkan/vulkan_video.c
@@ -0,0 +1,482 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/mem.h"
+#include "vulkan_video.h"
+
+#define ASPECT_2PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT)
+#define ASPECT_3PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT)
+
+static const struct FFVkFormatMapEntry {
+    VkFormat vkf;
+    enum AVPixelFormat pixfmt;
+    VkImageAspectFlags aspect;
+} vk_format_map[] = {
+    /* Gray formats */
+    { VK_FORMAT_R8_UNORM,   AV_PIX_FMT_GRAY8,   VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GRAY16,  VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GRAYF32, VK_IMAGE_ASPECT_COLOR_BIT },
+
+    /* RGB formats */
+    { VK_FORMAT_B8G8R8A8_UNORM,           AV_PIX_FMT_BGRA,    VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_R8G8B8A8_UNORM,           AV_PIX_FMT_RGBA,    VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_R8G8B8_UNORM,             AV_PIX_FMT_RGB24,   VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_B8G8R8_UNORM,             AV_PIX_FMT_BGR24,   VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_R16G16B16_UNORM,          AV_PIX_FMT_RGB48,   VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_R16G16B16A16_UNORM,       AV_PIX_FMT_RGBA64,  VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_R5G6B5_UNORM_PACK16,      AV_PIX_FMT_RGB565,  VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_B5G6R5_UNORM_PACK16,      AV_PIX_FMT_BGR565,  VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_B8G8R8A8_UNORM,           AV_PIX_FMT_BGR0,    VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_R8G8B8A8_UNORM,           AV_PIX_FMT_RGB0,    VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_A2R10G10B10_UNORM_PACK32, AV_PIX_FMT_X2RGB10, VK_IMAGE_ASPECT_COLOR_BIT },
+
+    /* Planar RGB */
+    { VK_FORMAT_R8_UNORM,   AV_PIX_FMT_GBRAP,    VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRAP16,  VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GBRPF32,  VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GBRAPF32, VK_IMAGE_ASPECT_COLOR_BIT },
+
+    /* Two-plane 420 YUV at 8, 10, 12 and 16 bits */
+    { VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,                  AV_PIX_FMT_NV12, ASPECT_2PLANE },
+    { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, AV_PIX_FMT_P010, ASPECT_2PLANE },
+    { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, AV_PIX_FMT_P012, ASPECT_2PLANE },
+    { VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,               AV_PIX_FMT_P016, ASPECT_2PLANE },
+
+    /* Two-plane 422 YUV at 8, 10 and 16 bits */
+    { VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,                  AV_PIX_FMT_NV16, ASPECT_2PLANE },
+    { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, AV_PIX_FMT_P210, ASPECT_2PLANE },
+    { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, AV_PIX_FMT_P212, ASPECT_2PLANE },
+    { VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,               AV_PIX_FMT_P216, ASPECT_2PLANE },
+
+    /* Two-plane 444 YUV at 8, 10 and 16 bits */
+    { VK_FORMAT_G8_B8R8_2PLANE_444_UNORM,                  AV_PIX_FMT_NV24, ASPECT_2PLANE },
+    { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16, AV_PIX_FMT_P410, ASPECT_2PLANE },
+    { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16, AV_PIX_FMT_P412, ASPECT_2PLANE },
+    { VK_FORMAT_G16_B16R16_2PLANE_444_UNORM,               AV_PIX_FMT_P416, ASPECT_2PLANE },
+
+    /* Three-plane 420, 422, 444 at 8, 10, 12 and 16 bits */
+    { VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,    AV_PIX_FMT_YUV420P,   ASPECT_3PLANE },
+    { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P10, ASPECT_3PLANE },
+    { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P12, ASPECT_3PLANE },
+    { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P16, ASPECT_3PLANE },
+    { VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,    AV_PIX_FMT_YUV422P,   ASPECT_3PLANE },
+    { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P10, ASPECT_3PLANE },
+    { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P12, ASPECT_3PLANE },
+    { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P16, ASPECT_3PLANE },
+    { VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,    AV_PIX_FMT_YUV444P,   ASPECT_3PLANE },
+    { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P10, ASPECT_3PLANE },
+    { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P12, ASPECT_3PLANE },
+    { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P16, ASPECT_3PLANE },
+
+    /* Single plane 422 at 8, 10, 12 and 16 bits */
+    { VK_FORMAT_G8B8G8R8_422_UNORM,                     AV_PIX_FMT_YUYV422, VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_B8G8R8G8_422_UNORM,                     AV_PIX_FMT_UYVY422, VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, AV_PIX_FMT_Y210,    VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, AV_PIX_FMT_Y212,    VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_G16B16G16R16_422_UNORM,                 AV_PIX_FMT_Y216,    VK_IMAGE_ASPECT_COLOR_BIT },
+
+    /* Single plane 444 at 10 and 12 bits */
+    { VK_FORMAT_A2R10G10B10_UNORM_PACK32,               AV_PIX_FMT_XV30,    VK_IMAGE_ASPECT_COLOR_BIT },
+    { VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,     AV_PIX_FMT_XV36,    VK_IMAGE_ASPECT_COLOR_BIT },
+};
+static const int nb_vk_format_map = FF_ARRAY_ELEMS(vk_format_map);
+
+enum AVPixelFormat ff_vk_pix_fmt_from_vkfmt(VkFormat vkf)
+{
+    for (int i = 0; i < nb_vk_format_map; i++)
+        if (vk_format_map[i].vkf == vkf)
+            return vk_format_map[i].pixfmt;
+    return AV_PIX_FMT_NONE;
+}
+
+VkImageAspectFlags ff_vk_aspect_bits_from_vkfmt(VkFormat vkf)
+{
+    for (int i = 0; i < nb_vk_format_map; i++)
+        if (vk_format_map[i].vkf == vkf)
+            return vk_format_map[i].aspect;
+    return VK_IMAGE_ASPECT_NONE;
+}
+
+VkVideoChromaSubsamplingFlagBitsKHR ff_vk_subsampling_from_av_desc(const AVPixFmtDescriptor *desc)
+{
+    if (desc->nb_components == 1)
+        return VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR;
+    else if (!desc->log2_chroma_w && !desc->log2_chroma_h)
+        return VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR;
+    else if (!desc->log2_chroma_w && desc->log2_chroma_h == 1)
+        return VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR;
+    else if (desc->log2_chroma_w == 1 && desc->log2_chroma_h == 1)
+        return VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR;
+    return VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_KHR;
+}
+
+VkVideoComponentBitDepthFlagBitsKHR ff_vk_depth_from_av_depth(int depth)
+{
+    switch (depth) {
+    case  8: return VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR;
+    case 10: return VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR;
+    case 12: return VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR;
+    default: break;
+    }
+    return VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR;
+}
+
+int ff_vk_h264_level_to_av(StdVideoH264LevelIdc level)
+{
+    switch (level) {
+    case STD_VIDEO_H264_LEVEL_IDC_1_0: return 10;
+    case STD_VIDEO_H264_LEVEL_IDC_1_1: return 11;
+    case STD_VIDEO_H264_LEVEL_IDC_1_2: return 12;
+    case STD_VIDEO_H264_LEVEL_IDC_1_3: return 13;
+    case STD_VIDEO_H264_LEVEL_IDC_2_0: return 20;
+    case STD_VIDEO_H264_LEVEL_IDC_2_1: return 21;
+    case STD_VIDEO_H264_LEVEL_IDC_2_2: return 22;
+    case STD_VIDEO_H264_LEVEL_IDC_3_0: return 30;
+    case STD_VIDEO_H264_LEVEL_IDC_3_1: return 31;
+    case STD_VIDEO_H264_LEVEL_IDC_3_2: return 32;
+    case STD_VIDEO_H264_LEVEL_IDC_4_0: return 40;
+    case STD_VIDEO_H264_LEVEL_IDC_4_1: return 41;
+    case STD_VIDEO_H264_LEVEL_IDC_4_2: return 42;
+    case STD_VIDEO_H264_LEVEL_IDC_5_0: return 50;
+    case STD_VIDEO_H264_LEVEL_IDC_5_1: return 51;
+    case STD_VIDEO_H264_LEVEL_IDC_5_2: return 52;
+    case STD_VIDEO_H264_LEVEL_IDC_6_0: return 60;
+    case STD_VIDEO_H264_LEVEL_IDC_6_1: return 61;
+    default:
+    case STD_VIDEO_H264_LEVEL_IDC_6_2: return 62;
+    }
+}
+
+StdVideoH264LevelIdc ff_vk_h264_level_to_vk(int level_idc)
+{
+    switch (level_idc) {
+    case 10: return STD_VIDEO_H264_LEVEL_IDC_1_0;
+    case 11: return STD_VIDEO_H264_LEVEL_IDC_1_1;
+    case 12: return STD_VIDEO_H264_LEVEL_IDC_1_2;
+    case 13: return STD_VIDEO_H264_LEVEL_IDC_1_3;
+    case 20: return STD_VIDEO_H264_LEVEL_IDC_2_0;
+    case 21: return STD_VIDEO_H264_LEVEL_IDC_2_1;
+    case 22: return STD_VIDEO_H264_LEVEL_IDC_2_2;
+    case 30: return STD_VIDEO_H264_LEVEL_IDC_3_0;
+    case 31: return STD_VIDEO_H264_LEVEL_IDC_3_1;
+    case 32: return STD_VIDEO_H264_LEVEL_IDC_3_2;
+    case 40: return STD_VIDEO_H264_LEVEL_IDC_4_0;
+    case 41: return STD_VIDEO_H264_LEVEL_IDC_4_1;
+    case 42: return STD_VIDEO_H264_LEVEL_IDC_4_2;
+    case 50: return STD_VIDEO_H264_LEVEL_IDC_5_0;
+    case 51: return STD_VIDEO_H264_LEVEL_IDC_5_1;
+    case 52: return STD_VIDEO_H264_LEVEL_IDC_5_2;
+    case 60: return STD_VIDEO_H264_LEVEL_IDC_6_0;
+    case 61: return STD_VIDEO_H264_LEVEL_IDC_6_1;
+    default:
+    case 62: return STD_VIDEO_H264_LEVEL_IDC_6_2;
+    }
+}
+
+int ff_vk_h265_level_to_av(StdVideoH265LevelIdc level)
+{
+    switch (level) {
+    case STD_VIDEO_H265_LEVEL_IDC_1_0: return 10;
+    case STD_VIDEO_H265_LEVEL_IDC_2_0: return 20;
+    case STD_VIDEO_H265_LEVEL_IDC_2_1: return 21;
+    case STD_VIDEO_H265_LEVEL_IDC_3_0: return 30;
+    case STD_VIDEO_H265_LEVEL_IDC_3_1: return 31;
+    case STD_VIDEO_H265_LEVEL_IDC_4_0: return 40;
+    case STD_VIDEO_H265_LEVEL_IDC_4_1: return 41;
+    case STD_VIDEO_H265_LEVEL_IDC_5_0: return 50;
+    case STD_VIDEO_H265_LEVEL_IDC_5_1: return 51;
+    case STD_VIDEO_H265_LEVEL_IDC_6_0: return 60;
+    case STD_VIDEO_H265_LEVEL_IDC_6_1: return 61;
+    default:
+    case STD_VIDEO_H265_LEVEL_IDC_6_2: return 62;
+    }
+}
+
+StdVideoH265LevelIdc ff_vk_h265_level_to_vk(int level_idc)
+{
+    switch (level_idc) {
+    case 10: return STD_VIDEO_H265_LEVEL_IDC_1_0;
+    case 20: return STD_VIDEO_H265_LEVEL_IDC_2_0;
+    case 21: return STD_VIDEO_H265_LEVEL_IDC_2_1;
+    case 30: return STD_VIDEO_H265_LEVEL_IDC_3_0;
+    case 31: return STD_VIDEO_H265_LEVEL_IDC_3_1;
+    case 40: return STD_VIDEO_H265_LEVEL_IDC_4_0;
+    case 41: return STD_VIDEO_H265_LEVEL_IDC_4_1;
+    case 50: return STD_VIDEO_H265_LEVEL_IDC_5_0;
+    case 51: return STD_VIDEO_H265_LEVEL_IDC_5_1;
+    case 60: return STD_VIDEO_H265_LEVEL_IDC_6_0;
+    case 61: return STD_VIDEO_H265_LEVEL_IDC_6_1;
+    default:
+    case 62: return STD_VIDEO_H265_LEVEL_IDC_6_2;
+    }
+}
+
+StdVideoAV1Level ff_vk_av1_level_to_vk(int level)
+{
+    switch (level) {
+    case 20: return STD_VIDEO_AV1_LEVEL_2_0;
+    case 21: return STD_VIDEO_AV1_LEVEL_2_1;
+    case 22: return STD_VIDEO_AV1_LEVEL_2_2;
+    case 23: return STD_VIDEO_AV1_LEVEL_2_3;
+    case 30: return STD_VIDEO_AV1_LEVEL_3_0;
+    case 31: return STD_VIDEO_AV1_LEVEL_3_1;
+    case 32: return STD_VIDEO_AV1_LEVEL_3_2;
+    case 33: return STD_VIDEO_AV1_LEVEL_3_3;
+    case 40: return STD_VIDEO_AV1_LEVEL_4_0;
+    case 41: return STD_VIDEO_AV1_LEVEL_4_1;
+    case 42: return STD_VIDEO_AV1_LEVEL_4_2;
+    case 43: return STD_VIDEO_AV1_LEVEL_4_3;
+    case 50: return STD_VIDEO_AV1_LEVEL_5_0;
+    case 51: return STD_VIDEO_AV1_LEVEL_5_1;
+    case 52: return STD_VIDEO_AV1_LEVEL_5_2;
+    case 53: return STD_VIDEO_AV1_LEVEL_5_3;
+    case 60: return STD_VIDEO_AV1_LEVEL_6_0;
+    case 61: return STD_VIDEO_AV1_LEVEL_6_1;
+    case 62: return STD_VIDEO_AV1_LEVEL_6_2;
+    case 63: return STD_VIDEO_AV1_LEVEL_6_3;
+    case 70: return STD_VIDEO_AV1_LEVEL_7_0;
+    case 71: return STD_VIDEO_AV1_LEVEL_7_1;
+    case 72: return STD_VIDEO_AV1_LEVEL_7_2;
+    default:
+    case 73: return STD_VIDEO_AV1_LEVEL_7_3;
+    }
+}
+
+StdVideoH264ProfileIdc ff_vk_h264_profile_to_vk(int profile)
+{
+    switch (profile) {
+    case AV_PROFILE_H264_CONSTRAINED_BASELINE: return STD_VIDEO_H264_PROFILE_IDC_BASELINE;
+    case AV_PROFILE_H264_MAIN: return STD_VIDEO_H264_PROFILE_IDC_MAIN;
+    case AV_PROFILE_H264_HIGH: return STD_VIDEO_H264_PROFILE_IDC_HIGH;
+    case AV_PROFILE_H264_HIGH_444_PREDICTIVE: return STD_VIDEO_H264_PROFILE_IDC_HIGH_444_PREDICTIVE;
+    default: return STD_VIDEO_H264_PROFILE_IDC_INVALID;
+    }
+}
+
+StdVideoH265ProfileIdc ff_vk_h265_profile_to_vk(int profile)
+{
+    switch (profile) {
+    case AV_PROFILE_HEVC_MAIN:    return STD_VIDEO_H265_PROFILE_IDC_MAIN;
+    case AV_PROFILE_HEVC_MAIN_10: return STD_VIDEO_H265_PROFILE_IDC_MAIN_10;
+    case AV_PROFILE_HEVC_REXT:    return STD_VIDEO_H265_PROFILE_IDC_FORMAT_RANGE_EXTENSIONS;
+    default: return STD_VIDEO_H265_PROFILE_IDC_INVALID;
+    }
+}
+
+StdVideoAV1Profile ff_vk_av1_profile_to_vk(int profile)
+{
+    switch (profile) {
+    case AV_PROFILE_AV1_MAIN: return STD_VIDEO_AV1_PROFILE_MAIN;
+    case AV_PROFILE_AV1_HIGH: return STD_VIDEO_AV1_PROFILE_HIGH;
+    case AV_PROFILE_AV1_PROFESSIONAL: return STD_VIDEO_AV1_PROFILE_PROFESSIONAL;
+    default: return STD_VIDEO_AV1_PROFILE_INVALID;
+    }
+}
+
+int ff_vk_create_view(FFVulkanContext *s, FFVkVideoCommon *common,
+                      VkImageView *view, VkImageAspectFlags *aspect,
+                      AVVkFrame *src, VkFormat vkf, int is_dpb)
+{
+    VkResult ret;
+    FFVulkanFunctions *vk = &s->vkfn;
+    VkImageAspectFlags aspect_mask = ff_vk_aspect_bits_from_vkfmt(vkf);
+
+    VkSamplerYcbcrConversionInfo yuv_sampler_info = {
+        .sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
+        .conversion = common->yuv_sampler,
+    };
+    VkImageViewCreateInfo img_view_create_info = {
+        .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+        .pNext = &yuv_sampler_info,
+        .viewType = common->layered_dpb && is_dpb ?
+                    VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D,
+        .format = vkf,
+        .image = src->img[0],
+        .components = (VkComponentMapping) {
+            .r = VK_COMPONENT_SWIZZLE_IDENTITY,
+            .g = VK_COMPONENT_SWIZZLE_IDENTITY,
+            .b = VK_COMPONENT_SWIZZLE_IDENTITY,
+            .a = VK_COMPONENT_SWIZZLE_IDENTITY,
+        },
+        .subresourceRange = (VkImageSubresourceRange) {
+            .aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT,
+            .baseArrayLayer = 0,
+            .layerCount     = common->layered_dpb && is_dpb ?
+                              VK_REMAINING_ARRAY_LAYERS : 1,
+            .levelCount     = 1,
+        },
+    };
+
+    ret = vk->CreateImageView(s->hwctx->act_dev, &img_view_create_info,
+                              s->hwctx->alloc, view);
+    if (ret != VK_SUCCESS)
+        return AVERROR_EXTERNAL;
+
+    *aspect = aspect_mask;
+
+    return 0;
+}
+
+av_cold void ff_vk_video_common_uninit(FFVulkanContext *s,
+                                       FFVkVideoCommon *common)
+{
+    FFVulkanFunctions *vk = &s->vkfn;
+
+    if (common->session) {
+        vk->DestroyVideoSessionKHR(s->hwctx->act_dev, common->session,
+                                   s->hwctx->alloc);
+        common->session = VK_NULL_HANDLE;
+    }
+
+    if (common->nb_mem && common->mem)
+        for (int i = 0; i < common->nb_mem; i++)
+            vk->FreeMemory(s->hwctx->act_dev, common->mem[i], s->hwctx->alloc);
+
+    av_freep(&common->mem);
+
+    if (common->layered_view)
+        vk->DestroyImageView(s->hwctx->act_dev, common->layered_view,
+                             s->hwctx->alloc);
+
+    av_frame_free(&common->layered_frame);
+
+    av_buffer_unref(&common->dpb_hwfc_ref);
+
+    if (common->yuv_sampler)
+        vk->DestroySamplerYcbcrConversion(s->hwctx->act_dev, common->yuv_sampler,
+                                          s->hwctx->alloc);
+}
+
+av_cold int ff_vk_video_common_init(AVCodecContext *avctx, FFVulkanContext *s,
+                                    FFVkVideoCommon *common,
+                                    VkVideoSessionCreateInfoKHR *session_create)
+{
+    int err;
+    VkResult ret;
+    FFVulkanFunctions *vk = &s->vkfn;
+    VkVideoSessionMemoryRequirementsKHR *mem = NULL;
+    VkBindVideoSessionMemoryInfoKHR *bind_mem = NULL;
+
+    int cxpos = 0, cypos = 0;
+    VkSamplerYcbcrConversionCreateInfo yuv_sampler_info = {
+        .sType      = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
+        .components = ff_comp_identity_map,
+        .ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
+        .ycbcrRange = avctx->color_range == AVCOL_RANGE_MPEG, /* Ignored */
+        .format     = session_create->pictureFormat,
+    };
+
+    /* Create identity YUV sampler
+     * (VkImageViews of YUV image formats require it, even if it does nothing) */
+    av_chroma_location_enum_to_pos(&cxpos, &cypos, avctx->chroma_sample_location);
+    yuv_sampler_info.xChromaOffset = cxpos >> 7;
+    yuv_sampler_info.yChromaOffset = cypos >> 7;
+    ret = vk->CreateSamplerYcbcrConversion(s->hwctx->act_dev, &yuv_sampler_info,
+                                           s->hwctx->alloc, &common->yuv_sampler);
+    if (ret != VK_SUCCESS)
+        return AVERROR_EXTERNAL;
+
+    /* Create session */
+    ret = vk->CreateVideoSessionKHR(s->hwctx->act_dev, session_create,
+                                    s->hwctx->alloc, &common->session);
+    if (ret != VK_SUCCESS)
+        return AVERROR_EXTERNAL;
+
+    /* Get memory requirements */
+    ret = vk->GetVideoSessionMemoryRequirementsKHR(s->hwctx->act_dev,
+                                                   common->session,
+                                                   &common->nb_mem,
+                                                   NULL);
+    if (ret != VK_SUCCESS) {
+        err = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+    /* Allocate all memory needed to actually allocate memory */
+    common->mem = av_mallocz(sizeof(*common->mem)*common->nb_mem);
+    if (!common->mem) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+    mem = av_mallocz(sizeof(*mem)*common->nb_mem);
+    if (!mem) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+    bind_mem = av_mallocz(sizeof(*bind_mem)*common->nb_mem);
+    if (!bind_mem) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    /* Set the needed fields to get the memory requirements */
+    for (int i = 0; i < common->nb_mem; i++) {
+        mem[i] = (VkVideoSessionMemoryRequirementsKHR) {
+            .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_MEMORY_REQUIREMENTS_KHR,
+        };
+    }
+
+    /* Finally get the memory requirements */
+    ret = vk->GetVideoSessionMemoryRequirementsKHR(s->hwctx->act_dev,
+                                                   common->session, &common->nb_mem,
+                                                   mem);
+    if (ret != VK_SUCCESS) {
+        err = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+    /* Now allocate each requested memory.
+     * For ricing, could pool together memory that ends up in the same index. */
+    for (int i = 0; i < common->nb_mem; i++) {
+        err = ff_vk_alloc_mem(s, &mem[i].memoryRequirements,
+                              UINT32_MAX, NULL, NULL, &common->mem[i]);
+        if (err < 0)
+            goto fail;
+
+        bind_mem[i] = (VkBindVideoSessionMemoryInfoKHR) {
+            .sType = VK_STRUCTURE_TYPE_BIND_VIDEO_SESSION_MEMORY_INFO_KHR,
+            .memory = common->mem[i],
+            .memoryBindIndex = mem[i].memoryBindIndex,
+            .memoryOffset = 0,
+            .memorySize = mem[i].memoryRequirements.size,
+        };
+
+        av_log(avctx, AV_LOG_VERBOSE, "Allocating %"PRIu64" bytes in bind index %i for video session\n",
+               bind_mem[i].memorySize, bind_mem[i].memoryBindIndex);
+    }
+
+    /* Bind the allocated memory */
+    ret = vk->BindVideoSessionMemoryKHR(s->hwctx->act_dev, common->session,
+                                        common->nb_mem, bind_mem);
+    if (ret != VK_SUCCESS) {
+        err = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+    av_freep(&mem);
+    av_freep(&bind_mem);
+
+    return 0;
+
+fail:
+    av_freep(&mem);
+    av_freep(&bind_mem);
+
+    ff_vk_video_common_uninit(s, common);
+    return err;
+}
-- 
2.49.1


From 3e4da93daae961ba6b9e853c2e8f43b5a9f9c109 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:42:25 +0000
Subject: [PATCH 091/118] Changing vulkan file directory

---
 libavcodec/vulkan_vp9.c | 371 ----------------------------------------
 1 file changed, 371 deletions(-)
 delete mode 100644 libavcodec/vulkan_vp9.c

diff --git a/libavcodec/vulkan_vp9.c b/libavcodec/vulkan_vp9.c
deleted file mode 100644
index 7b852a29a5..0000000000
--- a/libavcodec/vulkan_vp9.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "vp9dec.h"
-
-#include "vulkan_decode.h"
-
-const FFVulkanDecodeDescriptor ff_vk_dec_vp9_desc = {
-    .codec_id         = AV_CODEC_ID_VP9,
-    .decode_extension = FF_VK_EXT_VIDEO_DECODE_VP9,
-    .queue_flags      = VK_QUEUE_VIDEO_DECODE_BIT_KHR,
-    .decode_op        = VK_VIDEO_CODEC_OPERATION_DECODE_VP9_BIT_KHR,
-    .ext_props = {
-        .extensionName = VK_STD_VULKAN_VIDEO_CODEC_VP9_DECODE_EXTENSION_NAME,
-        .specVersion   = VK_STD_VULKAN_VIDEO_CODEC_VP9_DECODE_SPEC_VERSION,
-    },
-};
-
-typedef struct VP9VulkanDecodePicture {
-    FFVulkanDecodePicture           vp;
-
-    /* TODO: investigate if this can be removed to make decoding completely
-     * independent. */
-    FFVulkanDecodeContext          *dec;
-
-    /* Current picture */
-    StdVideoVP9ColorConfig color_config;
-    StdVideoVP9Segmentation segmentation;
-    StdVideoVP9LoopFilter loop_filter;
-    StdVideoDecodeVP9PictureInfo std_pic_info;
-    VkVideoDecodeVP9PictureInfoKHR vp9_pic_info;
-
-    const VP9Frame *ref_src[8];
-
-    uint8_t frame_id_set;
-    uint8_t frame_id;
-    uint8_t ref_frame_sign_bias_mask;
-} VP9VulkanDecodePicture;
-
-static int vk_vp9_fill_pict(AVCodecContext *avctx, const VP9Frame **ref_src,
-                            VkVideoReferenceSlotInfoKHR *ref_slot,      /* Main structure */
-                            VkVideoPictureResourceInfoKHR *ref,         /* Goes in ^ */
-                            const VP9Frame *pic, int is_current)
-{
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    FFVulkanDecodeShared *ctx = dec->shared_ctx;
-    VP9VulkanDecodePicture *hp = pic->hwaccel_picture_private;
-    FFVulkanDecodePicture *vkpic = &hp->vp;
-
-    int err = ff_vk_decode_prepare_frame(dec, pic->tf.f, vkpic, is_current,
-                                         dec->dedicated_dpb);
-    if (err < 0)
-        return err;
-
-    *ref = (VkVideoPictureResourceInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
-        .codedOffset = (VkOffset2D){ 0, 0 },
-        .codedExtent = (VkExtent2D){ pic->tf.f->width, pic->tf.f->height },
-        .baseArrayLayer = (dec->dedicated_dpb && ctx->common.layered_dpb) ?
-                          hp->frame_id : 0,
-        .imageViewBinding = vkpic->view.ref[0],
-    };
-
-    *ref_slot = (VkVideoReferenceSlotInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
-        .slotIndex = hp->frame_id,
-        .pPictureResource = ref,
-    };
-
-    if (ref_src)
-        *ref_src = pic;
-
-    return 0;
-}
-
-static enum StdVideoVP9InterpolationFilter remap_interp(uint8_t is_filter_switchable,
-                                                        uint8_t raw_interpolation_filter_type)
-{
-    static const enum StdVideoVP9InterpolationFilter remap[] = {
-        STD_VIDEO_VP9_INTERPOLATION_FILTER_EIGHTTAP_SMOOTH,
-        STD_VIDEO_VP9_INTERPOLATION_FILTER_EIGHTTAP,
-        STD_VIDEO_VP9_INTERPOLATION_FILTER_EIGHTTAP_SHARP,
-        STD_VIDEO_VP9_INTERPOLATION_FILTER_BILINEAR,
-    };
-    if (is_filter_switchable)
-        return STD_VIDEO_VP9_INTERPOLATION_FILTER_SWITCHABLE;
-    return remap[raw_interpolation_filter_type];
-}
-
-static int vk_vp9_start_frame(AVCodecContext          *avctx,
-                              av_unused const AVBufferRef *buffer_ref,
-                              av_unused const uint8_t *buffer,
-                              av_unused uint32_t       size)
-{
-    int err;
-    int ref_count = 0;
-    const VP9Context *priv = avctx->priv_data;
-    const CodedBitstreamVP9Context *vp9 = priv->cbc->priv_data;
-    const VP9SharedContext *s = &priv->s;
-    uint32_t frame_id_alloc_mask = 0;
-
-    const VP9Frame *pic = &s->frames[CUR_FRAME];
-    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
-    uint8_t profile = (pic->frame_header->profile_high_bit << 1) | pic->frame_header->profile_low_bit;
-
-    VP9VulkanDecodePicture *ap = pic->hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &ap->vp;
-
-    /* Use the current frame_ids in ref_frames[] to decide occupied frame_ids */
-    for (int i = 0; i < STD_VIDEO_VP9_NUM_REF_FRAMES; i++) {
-        const VP9VulkanDecodePicture* rp = s->ref_frames[i].hwaccel_picture_private;
-        if (rp)
-            frame_id_alloc_mask |= 1 << rp->frame_id;
-    }
-
-    if (!ap->frame_id_set) {
-        unsigned slot_idx = 0;
-        for (unsigned i = 0; i < 32; i++) {
-            if (!(frame_id_alloc_mask & (1 << i))) {
-                slot_idx = i;
-                break;
-            }
-        }
-        ap->frame_id = slot_idx;
-        ap->frame_id_set = 1;
-        frame_id_alloc_mask |= (1 << slot_idx);
-    }
-
-    for (int i = 0; i < STD_VIDEO_VP9_REFS_PER_FRAME; i++) {
-        const int idx = pic->frame_header->ref_frame_idx[i];
-        const VP9Frame *ref_frame = &s->ref_frames[idx];
-        VP9VulkanDecodePicture *hp = ref_frame->hwaccel_picture_private;
-        int found = 0;
-
-        if (!ref_frame->tf.f)
-            continue;
-
-        for (int j = 0; j < ref_count; j++) {
-            if (vp->ref_slots[j].slotIndex == hp->frame_id) {
-                found = 1;
-                break;
-            }
-        }
-        if (found)
-            continue;
-
-        err = vk_vp9_fill_pict(avctx, &ap->ref_src[ref_count],
-                               &vp->ref_slots[ref_count], &vp->refs[ref_count],
-                               ref_frame, 0);
-        if (err < 0)
-            return err;
-
-        ref_count++;
-    }
-
-    err = vk_vp9_fill_pict(avctx, NULL, &vp->ref_slot, &vp->ref,
-                           pic, 1);
-    if (err < 0)
-        return err;
-
-    ap->loop_filter = (StdVideoVP9LoopFilter) {
-        .flags = (StdVideoVP9LoopFilterFlags) {
-            .loop_filter_delta_enabled = pic->frame_header->loop_filter_delta_enabled,
-            .loop_filter_delta_update = pic->frame_header->loop_filter_delta_update,
-        },
-        .loop_filter_level = pic->frame_header->loop_filter_level,
-        .loop_filter_sharpness = pic->frame_header->loop_filter_sharpness,
-        .update_ref_delta = 0x0,
-        .update_mode_delta = 0x0,
-    };
-
-    for (int i = 0; i < STD_VIDEO_VP9_MAX_REF_FRAMES; i++) {
-        ap->loop_filter.loop_filter_ref_deltas[i] = vp9->loop_filter_ref_deltas[i];
-        ap->loop_filter.update_ref_delta |= pic->frame_header->update_ref_delta[i];
-    }
-    for (int i = 0; i < STD_VIDEO_VP9_LOOP_FILTER_ADJUSTMENTS; i++) {
-        ap->loop_filter.loop_filter_mode_deltas[i] = vp9->loop_filter_mode_deltas[i];
-        ap->loop_filter.update_mode_delta |= pic->frame_header->update_mode_delta[i];
-    }
-
-    ap->segmentation = (StdVideoVP9Segmentation) {
-        .flags = (StdVideoVP9SegmentationFlags) {
-            .segmentation_update_map = pic->frame_header->segmentation_update_map,
-            .segmentation_temporal_update = pic->frame_header->segmentation_temporal_update,
-            .segmentation_update_data = pic->frame_header->segmentation_update_data,
-            .segmentation_abs_or_delta_update = pic->frame_header->segmentation_abs_or_delta_update,
-        },
-    };
-
-    for (int i = 0; i < STD_VIDEO_VP9_MAX_SEGMENTATION_TREE_PROBS; i++)
-        ap->segmentation.segmentation_tree_probs[i] = vp9->segmentation_tree_probs[i];
-    for (int i = 0; i < STD_VIDEO_VP9_MAX_SEGMENTATION_PRED_PROB; i++)
-        ap->segmentation.segmentation_pred_prob[i] = vp9->segmentation_pred_prob[i];
-    for (int i = 0; i < STD_VIDEO_VP9_MAX_SEGMENTS; i++) {
-        ap->segmentation.FeatureEnabled[i] = 0x0;
-        for (int j = 0; j < STD_VIDEO_VP9_SEG_LVL_MAX; j++) {
-            ap->segmentation.FeatureEnabled[i] |= vp9->feature_enabled[i][j] << j;
-            ap->segmentation.FeatureData[i][j] = vp9->feature_sign[i][j] ?
-                                                 -vp9->feature_value[i][j] :
-                                                 +vp9->feature_value[i][j];
-        }
-    }
-
-    ap->color_config = (StdVideoVP9ColorConfig) {
-        .flags = (StdVideoVP9ColorConfigFlags) {
-            .color_range = pic->frame_header->color_range,
-        },
-        .BitDepth = profile < 2 ? 8 :
-                    pic->frame_header->ten_or_twelve_bit ? 12 : 10,
-        .subsampling_x = pic->frame_header->subsampling_x,
-        .subsampling_y = pic->frame_header->subsampling_y,
-        .color_space = pic->frame_header->color_space,
-    };
-
-    ap->std_pic_info = (StdVideoDecodeVP9PictureInfo) {
-        .flags = (StdVideoDecodeVP9PictureInfoFlags) {
-           .error_resilient_mode = pic->frame_header->error_resilient_mode,
-           .intra_only = pic->frame_header->intra_only,
-           .allow_high_precision_mv = pic->frame_header->allow_high_precision_mv,
-           .refresh_frame_context = pic->frame_header->refresh_frame_context,
-           .frame_parallel_decoding_mode = pic->frame_header->frame_parallel_decoding_mode,
-           .segmentation_enabled = pic->frame_header->segmentation_enabled,
-           .show_frame = pic->frame_header->segmentation_enabled,
-           .UsePrevFrameMvs = s->h.use_last_frame_mvs,
-        },
-        .profile = profile,
-        .frame_type = pic->frame_header->frame_type,
-        .frame_context_idx = pic->frame_header->frame_context_idx,
-        .reset_frame_context = pic->frame_header->reset_frame_context,
-        .refresh_frame_flags = pic->frame_header->refresh_frame_flags,
-        .ref_frame_sign_bias_mask = 0x0,
-        .interpolation_filter = remap_interp(pic->frame_header->is_filter_switchable,
-                                             pic->frame_header->raw_interpolation_filter_type),
-        .base_q_idx = pic->frame_header->base_q_idx,
-        .delta_q_y_dc = pic->frame_header->delta_q_y_dc,
-        .delta_q_uv_dc = pic->frame_header->delta_q_uv_dc,
-        .delta_q_uv_ac = pic->frame_header->delta_q_uv_ac,
-        .tile_cols_log2 = pic->frame_header->tile_cols_log2,
-        .tile_rows_log2 = pic->frame_header->tile_rows_log2,
-        /* Reserved */
-        .pColorConfig = &ap->color_config,
-        .pLoopFilter = &ap->loop_filter,
-        .pSegmentation = &ap->segmentation,
-    };
-
-    for (int i = VP9_LAST_FRAME; i <= VP9_ALTREF_FRAME; i++)
-        ap->std_pic_info.ref_frame_sign_bias_mask |= pic->frame_header->ref_frame_sign_bias[i] << i;
-
-    ap->vp9_pic_info = (VkVideoDecodeVP9PictureInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_VP9_PICTURE_INFO_KHR,
-        .pStdPictureInfo = &ap->std_pic_info,
-        .uncompressedHeaderOffset = 0,
-        .compressedHeaderOffset = s->h.uncompressed_header_size,
-        .tilesOffset = s->h.uncompressed_header_size +
-                       s->h.compressed_header_size,
-    };
-
-    for (int i = 0; i < STD_VIDEO_VP9_REFS_PER_FRAME; i++) {
-        const int idx = pic->frame_header->ref_frame_idx[i];
-        const VP9Frame *ref_frame = &s->ref_frames[idx];
-        VP9VulkanDecodePicture *hp = ref_frame->hwaccel_picture_private;
-
-        if (!ref_frame->tf.f)
-            ap->vp9_pic_info.referenceNameSlotIndices[i] = -1;
-        else
-            ap->vp9_pic_info.referenceNameSlotIndices[i] = hp->frame_id;
-    }
-
-    vp->decode_info = (VkVideoDecodeInfoKHR) {
-        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR,
-        .pNext = &ap->vp9_pic_info,
-        .flags = 0x0,
-        .pSetupReferenceSlot = &vp->ref_slot,
-        .referenceSlotCount = ref_count,
-        .pReferenceSlots = vp->ref_slots,
-        .dstPictureResource = (VkVideoPictureResourceInfoKHR) {
-            .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
-            .codedOffset = (VkOffset2D){ 0, 0 },
-            .codedExtent = (VkExtent2D){ pic->tf.f->width, pic->tf.f->height },
-            .baseArrayLayer = 0,
-            .imageViewBinding = vp->view.out[0],
-        },
-    };
-
-    ap->dec = dec;
-
-    return 0;
-}
-
-static int vk_vp9_decode_slice(AVCodecContext *avctx,
-                               const uint8_t  *data,
-                               uint32_t        size)
-{
-    int err;
-    const VP9SharedContext *s = avctx->priv_data;
-    VP9VulkanDecodePicture *ap = s->frames[CUR_FRAME].hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &ap->vp;
-
-    err = ff_vk_decode_add_slice(avctx, vp, data, size, 0, NULL, NULL);
-    if (err < 0)
-        return err;
-
-    return 0;
-}
-
-static int vk_vp9_end_frame(AVCodecContext *avctx)
-{
-    const VP9SharedContext *s = avctx->priv_data;
-
-    const VP9Frame *pic = &s->frames[CUR_FRAME];
-    VP9VulkanDecodePicture *ap = pic->hwaccel_picture_private;
-    FFVulkanDecodePicture *vp = &ap->vp;
-    FFVulkanDecodePicture *rvp[STD_VIDEO_VP9_REFS_PER_FRAME] = { 0 };
-    AVFrame *rav[STD_VIDEO_VP9_REFS_PER_FRAME] = { 0 };
-
-    for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
-        const VP9Frame *rp = ap->ref_src[i];
-        VP9VulkanDecodePicture *rhp = rp->hwaccel_picture_private;
-
-        rvp[i] = &rhp->vp;
-        rav[i] = ap->ref_src[i]->tf.f;
-    }
-
-    av_log(avctx, AV_LOG_VERBOSE, "Decoding frame, %"SIZE_SPECIFIER" bytes\n",
-           vp->slices_size);
-
-    return ff_vk_decode_frame(avctx, pic->tf.f, vp, rav, rvp);
-}
-
-static void vk_vp9_free_frame_priv(AVRefStructOpaque _hwctx, void *data)
-{
-    AVHWDeviceContext *hwctx = _hwctx.nc;
-    VP9VulkanDecodePicture *ap = data;
-
-    /* Free frame resources, this also destroys the session parameters. */
-    ff_vk_decode_free_frame(hwctx, &ap->vp);
-}
-
-const FFHWAccel ff_vp9_vulkan_hwaccel = {
-    .p.name                = "vp9_vulkan",
-    .p.type                = AVMEDIA_TYPE_VIDEO,
-    .p.id                  = AV_CODEC_ID_VP9,
-    .p.pix_fmt             = AV_PIX_FMT_VULKAN,
-    .start_frame           = &vk_vp9_start_frame,
-    .decode_slice          = &vk_vp9_decode_slice,
-    .end_frame             = &vk_vp9_end_frame,
-    .free_frame_priv       = &vk_vp9_free_frame_priv,
-    .frame_priv_data_size  = sizeof(VP9VulkanDecodePicture),
-    .init                  = &ff_vk_decode_init,
-    .update_thread_context = &ff_vk_update_thread_context,
-    .flush                 = &ff_vk_decode_flush,
-    .uninit                = &ff_vk_decode_uninit,
-    .frame_params          = &ff_vk_frame_params,
-    .priv_data_size        = sizeof(FFVulkanDecodeContext),
-    .caps_internal         = HWACCEL_CAP_ASYNC_SAFE,
-};
-- 
2.49.1


From 35b069c88ef3463985f3327388c577cb54cdfb78 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:42:57 +0000
Subject: [PATCH 092/118] Changing vulkan file directory

---
 libavcodec/vulkan/vulkan_vp9.c | 371 +++++++++++++++++++++++++++++++++
 1 file changed, 371 insertions(+)
 create mode 100644 libavcodec/vulkan/vulkan_vp9.c

diff --git a/libavcodec/vulkan/vulkan_vp9.c b/libavcodec/vulkan/vulkan_vp9.c
new file mode 100644
index 0000000000..b150d25160
--- /dev/null
+++ b/libavcodec/vulkan/vulkan_vp9.c
@@ -0,0 +1,371 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavcodec/vp9dec.h"
+
+#include "vulkan_decode.h"
+
+const FFVulkanDecodeDescriptor ff_vk_dec_vp9_desc = {
+    .codec_id         = AV_CODEC_ID_VP9,
+    .decode_extension = FF_VK_EXT_VIDEO_DECODE_VP9,
+    .queue_flags      = VK_QUEUE_VIDEO_DECODE_BIT_KHR,
+    .decode_op        = VK_VIDEO_CODEC_OPERATION_DECODE_VP9_BIT_KHR,
+    .ext_props = {
+        .extensionName = VK_STD_VULKAN_VIDEO_CODEC_VP9_DECODE_EXTENSION_NAME,
+        .specVersion   = VK_STD_VULKAN_VIDEO_CODEC_VP9_DECODE_SPEC_VERSION,
+    },
+};
+
+typedef struct VP9VulkanDecodePicture {
+    FFVulkanDecodePicture           vp;
+
+    /* TODO: investigate if this can be removed to make decoding completely
+     * independent. */
+    FFVulkanDecodeContext          *dec;
+
+    /* Current picture */
+    StdVideoVP9ColorConfig color_config;
+    StdVideoVP9Segmentation segmentation;
+    StdVideoVP9LoopFilter loop_filter;
+    StdVideoDecodeVP9PictureInfo std_pic_info;
+    VkVideoDecodeVP9PictureInfoKHR vp9_pic_info;
+
+    const VP9Frame *ref_src[8];
+
+    uint8_t frame_id_set;
+    uint8_t frame_id;
+    uint8_t ref_frame_sign_bias_mask;
+} VP9VulkanDecodePicture;
+
+static int vk_vp9_fill_pict(AVCodecContext *avctx, const VP9Frame **ref_src,
+                            VkVideoReferenceSlotInfoKHR *ref_slot,      /* Main structure */
+                            VkVideoPictureResourceInfoKHR *ref,         /* Goes in ^ */
+                            const VP9Frame *pic, int is_current)
+{
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    FFVulkanDecodeShared *ctx = dec->shared_ctx;
+    VP9VulkanDecodePicture *hp = pic->hwaccel_picture_private;
+    FFVulkanDecodePicture *vkpic = &hp->vp;
+
+    int err = ff_vk_decode_prepare_frame(dec, pic->tf.f, vkpic, is_current,
+                                         dec->dedicated_dpb);
+    if (err < 0)
+        return err;
+
+    *ref = (VkVideoPictureResourceInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
+        .codedOffset = (VkOffset2D){ 0, 0 },
+        .codedExtent = (VkExtent2D){ pic->tf.f->width, pic->tf.f->height },
+        .baseArrayLayer = (dec->dedicated_dpb && ctx->common.layered_dpb) ?
+                          hp->frame_id : 0,
+        .imageViewBinding = vkpic->view.ref[0],
+    };
+
+    *ref_slot = (VkVideoReferenceSlotInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
+        .slotIndex = hp->frame_id,
+        .pPictureResource = ref,
+    };
+
+    if (ref_src)
+        *ref_src = pic;
+
+    return 0;
+}
+
+static enum StdVideoVP9InterpolationFilter remap_interp(uint8_t is_filter_switchable,
+                                                        uint8_t raw_interpolation_filter_type)
+{
+    static const enum StdVideoVP9InterpolationFilter remap[] = {
+        STD_VIDEO_VP9_INTERPOLATION_FILTER_EIGHTTAP_SMOOTH,
+        STD_VIDEO_VP9_INTERPOLATION_FILTER_EIGHTTAP,
+        STD_VIDEO_VP9_INTERPOLATION_FILTER_EIGHTTAP_SHARP,
+        STD_VIDEO_VP9_INTERPOLATION_FILTER_BILINEAR,
+    };
+    if (is_filter_switchable)
+        return STD_VIDEO_VP9_INTERPOLATION_FILTER_SWITCHABLE;
+    return remap[raw_interpolation_filter_type];
+}
+
+static int vk_vp9_start_frame(AVCodecContext          *avctx,
+                              av_unused const AVBufferRef *buffer_ref,
+                              av_unused const uint8_t *buffer,
+                              av_unused uint32_t       size)
+{
+    int err;
+    int ref_count = 0;
+    const VP9Context *priv = avctx->priv_data;
+    const CodedBitstreamVP9Context *vp9 = priv->cbc->priv_data;
+    const VP9SharedContext *s = &priv->s;
+    uint32_t frame_id_alloc_mask = 0;
+
+    const VP9Frame *pic = &s->frames[CUR_FRAME];
+    FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+    uint8_t profile = (pic->frame_header->profile_high_bit << 1) | pic->frame_header->profile_low_bit;
+
+    VP9VulkanDecodePicture *ap = pic->hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &ap->vp;
+
+    /* Use the current frame_ids in ref_frames[] to decide occupied frame_ids */
+    for (int i = 0; i < STD_VIDEO_VP9_NUM_REF_FRAMES; i++) {
+        const VP9VulkanDecodePicture* rp = s->ref_frames[i].hwaccel_picture_private;
+        if (rp)
+            frame_id_alloc_mask |= 1 << rp->frame_id;
+    }
+
+    if (!ap->frame_id_set) {
+        unsigned slot_idx = 0;
+        for (unsigned i = 0; i < 32; i++) {
+            if (!(frame_id_alloc_mask & (1 << i))) {
+                slot_idx = i;
+                break;
+            }
+        }
+        ap->frame_id = slot_idx;
+        ap->frame_id_set = 1;
+        frame_id_alloc_mask |= (1 << slot_idx);
+    }
+
+    for (int i = 0; i < STD_VIDEO_VP9_REFS_PER_FRAME; i++) {
+        const int idx = pic->frame_header->ref_frame_idx[i];
+        const VP9Frame *ref_frame = &s->ref_frames[idx];
+        VP9VulkanDecodePicture *hp = ref_frame->hwaccel_picture_private;
+        int found = 0;
+
+        if (!ref_frame->tf.f)
+            continue;
+
+        for (int j = 0; j < ref_count; j++) {
+            if (vp->ref_slots[j].slotIndex == hp->frame_id) {
+                found = 1;
+                break;
+            }
+        }
+        if (found)
+            continue;
+
+        err = vk_vp9_fill_pict(avctx, &ap->ref_src[ref_count],
+                               &vp->ref_slots[ref_count], &vp->refs[ref_count],
+                               ref_frame, 0);
+        if (err < 0)
+            return err;
+
+        ref_count++;
+    }
+
+    err = vk_vp9_fill_pict(avctx, NULL, &vp->ref_slot, &vp->ref,
+                           pic, 1);
+    if (err < 0)
+        return err;
+
+    ap->loop_filter = (StdVideoVP9LoopFilter) {
+        .flags = (StdVideoVP9LoopFilterFlags) {
+            .loop_filter_delta_enabled = pic->frame_header->loop_filter_delta_enabled,
+            .loop_filter_delta_update = pic->frame_header->loop_filter_delta_update,
+        },
+        .loop_filter_level = pic->frame_header->loop_filter_level,
+        .loop_filter_sharpness = pic->frame_header->loop_filter_sharpness,
+        .update_ref_delta = 0x0,
+        .update_mode_delta = 0x0,
+    };
+
+    for (int i = 0; i < STD_VIDEO_VP9_MAX_REF_FRAMES; i++) {
+        ap->loop_filter.loop_filter_ref_deltas[i] = vp9->loop_filter_ref_deltas[i];
+        ap->loop_filter.update_ref_delta |= pic->frame_header->update_ref_delta[i];
+    }
+    for (int i = 0; i < STD_VIDEO_VP9_LOOP_FILTER_ADJUSTMENTS; i++) {
+        ap->loop_filter.loop_filter_mode_deltas[i] = vp9->loop_filter_mode_deltas[i];
+        ap->loop_filter.update_mode_delta |= pic->frame_header->update_mode_delta[i];
+    }
+
+    ap->segmentation = (StdVideoVP9Segmentation) {
+        .flags = (StdVideoVP9SegmentationFlags) {
+            .segmentation_update_map = pic->frame_header->segmentation_update_map,
+            .segmentation_temporal_update = pic->frame_header->segmentation_temporal_update,
+            .segmentation_update_data = pic->frame_header->segmentation_update_data,
+            .segmentation_abs_or_delta_update = pic->frame_header->segmentation_abs_or_delta_update,
+        },
+    };
+
+    for (int i = 0; i < STD_VIDEO_VP9_MAX_SEGMENTATION_TREE_PROBS; i++)
+        ap->segmentation.segmentation_tree_probs[i] = vp9->segmentation_tree_probs[i];
+    for (int i = 0; i < STD_VIDEO_VP9_MAX_SEGMENTATION_PRED_PROB; i++)
+        ap->segmentation.segmentation_pred_prob[i] = vp9->segmentation_pred_prob[i];
+    for (int i = 0; i < STD_VIDEO_VP9_MAX_SEGMENTS; i++) {
+        ap->segmentation.FeatureEnabled[i] = 0x0;
+        for (int j = 0; j < STD_VIDEO_VP9_SEG_LVL_MAX; j++) {
+            ap->segmentation.FeatureEnabled[i] |= vp9->feature_enabled[i][j] << j;
+            ap->segmentation.FeatureData[i][j] = vp9->feature_sign[i][j] ?
+                                                 -vp9->feature_value[i][j] :
+                                                 +vp9->feature_value[i][j];
+        }
+    }
+
+    ap->color_config = (StdVideoVP9ColorConfig) {
+        .flags = (StdVideoVP9ColorConfigFlags) {
+            .color_range = pic->frame_header->color_range,
+        },
+        .BitDepth = profile < 2 ? 8 :
+                    pic->frame_header->ten_or_twelve_bit ? 12 : 10,
+        .subsampling_x = pic->frame_header->subsampling_x,
+        .subsampling_y = pic->frame_header->subsampling_y,
+        .color_space = pic->frame_header->color_space,
+    };
+
+    ap->std_pic_info = (StdVideoDecodeVP9PictureInfo) {
+        .flags = (StdVideoDecodeVP9PictureInfoFlags) {
+           .error_resilient_mode = pic->frame_header->error_resilient_mode,
+           .intra_only = pic->frame_header->intra_only,
+           .allow_high_precision_mv = pic->frame_header->allow_high_precision_mv,
+           .refresh_frame_context = pic->frame_header->refresh_frame_context,
+           .frame_parallel_decoding_mode = pic->frame_header->frame_parallel_decoding_mode,
+           .segmentation_enabled = pic->frame_header->segmentation_enabled,
+           .show_frame = pic->frame_header->segmentation_enabled,
+           .UsePrevFrameMvs = s->h.use_last_frame_mvs,
+        },
+        .profile = profile,
+        .frame_type = pic->frame_header->frame_type,
+        .frame_context_idx = pic->frame_header->frame_context_idx,
+        .reset_frame_context = pic->frame_header->reset_frame_context,
+        .refresh_frame_flags = pic->frame_header->refresh_frame_flags,
+        .ref_frame_sign_bias_mask = 0x0,
+        .interpolation_filter = remap_interp(pic->frame_header->is_filter_switchable,
+                                             pic->frame_header->raw_interpolation_filter_type),
+        .base_q_idx = pic->frame_header->base_q_idx,
+        .delta_q_y_dc = pic->frame_header->delta_q_y_dc,
+        .delta_q_uv_dc = pic->frame_header->delta_q_uv_dc,
+        .delta_q_uv_ac = pic->frame_header->delta_q_uv_ac,
+        .tile_cols_log2 = pic->frame_header->tile_cols_log2,
+        .tile_rows_log2 = pic->frame_header->tile_rows_log2,
+        /* Reserved */
+        .pColorConfig = &ap->color_config,
+        .pLoopFilter = &ap->loop_filter,
+        .pSegmentation = &ap->segmentation,
+    };
+
+    for (int i = VP9_LAST_FRAME; i <= VP9_ALTREF_FRAME; i++)
+        ap->std_pic_info.ref_frame_sign_bias_mask |= pic->frame_header->ref_frame_sign_bias[i] << i;
+
+    ap->vp9_pic_info = (VkVideoDecodeVP9PictureInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_VP9_PICTURE_INFO_KHR,
+        .pStdPictureInfo = &ap->std_pic_info,
+        .uncompressedHeaderOffset = 0,
+        .compressedHeaderOffset = s->h.uncompressed_header_size,
+        .tilesOffset = s->h.uncompressed_header_size +
+                       s->h.compressed_header_size,
+    };
+
+    for (int i = 0; i < STD_VIDEO_VP9_REFS_PER_FRAME; i++) {
+        const int idx = pic->frame_header->ref_frame_idx[i];
+        const VP9Frame *ref_frame = &s->ref_frames[idx];
+        VP9VulkanDecodePicture *hp = ref_frame->hwaccel_picture_private;
+
+        if (!ref_frame->tf.f)
+            ap->vp9_pic_info.referenceNameSlotIndices[i] = -1;
+        else
+            ap->vp9_pic_info.referenceNameSlotIndices[i] = hp->frame_id;
+    }
+
+    vp->decode_info = (VkVideoDecodeInfoKHR) {
+        .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR,
+        .pNext = &ap->vp9_pic_info,
+        .flags = 0x0,
+        .pSetupReferenceSlot = &vp->ref_slot,
+        .referenceSlotCount = ref_count,
+        .pReferenceSlots = vp->ref_slots,
+        .dstPictureResource = (VkVideoPictureResourceInfoKHR) {
+            .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
+            .codedOffset = (VkOffset2D){ 0, 0 },
+            .codedExtent = (VkExtent2D){ pic->tf.f->width, pic->tf.f->height },
+            .baseArrayLayer = 0,
+            .imageViewBinding = vp->view.out[0],
+        },
+    };
+
+    ap->dec = dec;
+
+    return 0;
+}
+
+static int vk_vp9_decode_slice(AVCodecContext *avctx,
+                               const uint8_t  *data,
+                               uint32_t        size)
+{
+    int err;
+    const VP9SharedContext *s = avctx->priv_data;
+    VP9VulkanDecodePicture *ap = s->frames[CUR_FRAME].hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &ap->vp;
+
+    err = ff_vk_decode_add_slice(avctx, vp, data, size, 0, NULL, NULL);
+    if (err < 0)
+        return err;
+
+    return 0;
+}
+
+static int vk_vp9_end_frame(AVCodecContext *avctx)
+{
+    const VP9SharedContext *s = avctx->priv_data;
+
+    const VP9Frame *pic = &s->frames[CUR_FRAME];
+    VP9VulkanDecodePicture *ap = pic->hwaccel_picture_private;
+    FFVulkanDecodePicture *vp = &ap->vp;
+    FFVulkanDecodePicture *rvp[STD_VIDEO_VP9_REFS_PER_FRAME] = { 0 };
+    AVFrame *rav[STD_VIDEO_VP9_REFS_PER_FRAME] = { 0 };
+
+    for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
+        const VP9Frame *rp = ap->ref_src[i];
+        VP9VulkanDecodePicture *rhp = rp->hwaccel_picture_private;
+
+        rvp[i] = &rhp->vp;
+        rav[i] = ap->ref_src[i]->tf.f;
+    }
+
+    av_log(avctx, AV_LOG_VERBOSE, "Decoding frame, %"SIZE_SPECIFIER" bytes\n",
+           vp->slices_size);
+
+    return ff_vk_decode_frame(avctx, pic->tf.f, vp, rav, rvp);
+}
+
+static void vk_vp9_free_frame_priv(AVRefStructOpaque _hwctx, void *data)
+{
+    AVHWDeviceContext *hwctx = _hwctx.nc;
+    VP9VulkanDecodePicture *ap = data;
+
+    /* Free frame resources, this also destroys the session parameters. */
+    ff_vk_decode_free_frame(hwctx, &ap->vp);
+}
+
+const FFHWAccel ff_vp9_vulkan_hwaccel = {
+    .p.name                = "vp9_vulkan",
+    .p.type                = AVMEDIA_TYPE_VIDEO,
+    .p.id                  = AV_CODEC_ID_VP9,
+    .p.pix_fmt             = AV_PIX_FMT_VULKAN,
+    .start_frame           = &vk_vp9_start_frame,
+    .decode_slice          = &vk_vp9_decode_slice,
+    .end_frame             = &vk_vp9_end_frame,
+    .free_frame_priv       = &vk_vp9_free_frame_priv,
+    .frame_priv_data_size  = sizeof(VP9VulkanDecodePicture),
+    .init                  = &ff_vk_decode_init,
+    .update_thread_context = &ff_vk_update_thread_context,
+    .flush                 = &ff_vk_decode_flush,
+    .uninit                = &ff_vk_decode_uninit,
+    .frame_params          = &ff_vk_frame_params,
+    .priv_data_size        = sizeof(FFVulkanDecodeContext),
+    .caps_internal         = HWACCEL_CAP_ASYNC_SAFE,
+};
-- 
2.49.1


From 59a745ed0eb1ae1171b0e8aa06aafd276cb76097 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:43:49 +0000
Subject: [PATCH 093/118] Changing vulkan file directory

---
 libavcodec/vulkan_video.h | 102 --------------------------------------
 1 file changed, 102 deletions(-)
 delete mode 100644 libavcodec/vulkan_video.h

diff --git a/libavcodec/vulkan_video.h b/libavcodec/vulkan_video.h
deleted file mode 100644
index 1b29f7adc7..0000000000
--- a/libavcodec/vulkan_video.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVCODEC_VULKAN_VIDEO_H
-#define AVCODEC_VULKAN_VIDEO_H
-
-#include "avcodec.h"
-#include "libavutil/vulkan.h"
-
-#include <vk_video/vulkan_video_codecs_common.h>
-
-#define CODEC_VER_MAJ(ver) (ver >> 22)
-#define CODEC_VER_MIN(ver) ((ver >> 12) & ((1 << 10) - 1))
-#define CODEC_VER_PAT(ver) (ver & ((1 << 12) - 1))
-#define CODEC_VER(ver) CODEC_VER_MAJ(ver), CODEC_VER_MIN(ver), CODEC_VER_PAT(ver)
-
-typedef struct FFVkVideoSession {
-    VkVideoSessionKHR session;
-    VkDeviceMemory *mem;
-    uint32_t nb_mem;
-
-    VkSamplerYcbcrConversion yuv_sampler;
-
-    AVBufferRef *dpb_hwfc_ref;
-    int layered_dpb;
-    AVFrame *layered_frame;
-    VkImageView layered_view;
-    VkImageAspectFlags layered_aspect;
-} FFVkVideoCommon;
-
-/**
- * Get pixfmt from a Vulkan format.
- */
-enum AVPixelFormat ff_vk_pix_fmt_from_vkfmt(VkFormat vkf);
-
-/**
- * Get aspect bits which include all planes from a VkFormat.
- */
-VkImageAspectFlags ff_vk_aspect_bits_from_vkfmt(VkFormat vkf);
-
-/**
- * Get Vulkan's chroma subsampling from a pixfmt descriptor.
- */
-VkVideoChromaSubsamplingFlagBitsKHR ff_vk_subsampling_from_av_desc(const AVPixFmtDescriptor *desc);
-
-/**
- * Get Vulkan's bit depth from an [8:12] integer.
- */
-VkVideoComponentBitDepthFlagBitsKHR ff_vk_depth_from_av_depth(int depth);
-
-/**
- * Convert level from Vulkan to AV.
- */
-int ff_vk_h264_level_to_av(StdVideoH264LevelIdc level);
-int ff_vk_h265_level_to_av(StdVideoH265LevelIdc level);
-
-StdVideoH264LevelIdc ff_vk_h264_level_to_vk(int level_idc);
-StdVideoH265LevelIdc ff_vk_h265_level_to_vk(int level_idc);
-StdVideoAV1Level     ff_vk_av1_level_to_vk(int level);
-
-/**
- * Convert profile from/to AV to Vulkan
- */
-StdVideoH264ProfileIdc ff_vk_h264_profile_to_vk(int profile);
-StdVideoH265ProfileIdc ff_vk_h265_profile_to_vk(int profile);
-StdVideoAV1Profile     ff_vk_av1_profile_to_vk(int profile);
-
-/**
- * Creates image views for video frames.
- */
-int ff_vk_create_view(FFVulkanContext *s, FFVkVideoCommon *common,
-                      VkImageView *view, VkImageAspectFlags *aspect,
-                      AVVkFrame *src, VkFormat vkf, int is_dpb);
-
-/**
- * Initialize video session, allocating and binding necessary memory.
- */
-int ff_vk_video_common_init(AVCodecContext *avctx, FFVulkanContext *s,
-                            FFVkVideoCommon *common,
-                            VkVideoSessionCreateInfoKHR *session_create);
-
-/**
- * Free video session and required resources.
- */
-void ff_vk_video_common_uninit(FFVulkanContext *s, FFVkVideoCommon *common);
-
-#endif /* AVCODEC_VULKAN_VIDEO_H */
-- 
2.49.1


From 8035b576c288705df92e6c71a4c35dc4b08b1630 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:44:11 +0000
Subject: [PATCH 094/118] Changing vulkan file directory

---
 libavcodec/vulkan/vulkan_video.h | 102 +++++++++++++++++++++++++++++++
 1 file changed, 102 insertions(+)
 create mode 100644 libavcodec/vulkan/vulkan_video.h

diff --git a/libavcodec/vulkan/vulkan_video.h b/libavcodec/vulkan/vulkan_video.h
new file mode 100644
index 0000000000..e460fe78b1
--- /dev/null
+++ b/libavcodec/vulkan/vulkan_video.h
@@ -0,0 +1,102 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_VULKAN_VIDEO_H
+#define AVCODEC_VULKAN_VIDEO_H
+
+#include "libavcodec/avcodec.h"
+#include "../../libavutil/vulkan/vulkan.h"
+
+#include <vk_video/vulkan_video_codecs_common.h>
+
+#define CODEC_VER_MAJ(ver) (ver >> 22)
+#define CODEC_VER_MIN(ver) ((ver >> 12) & ((1 << 10) - 1))
+#define CODEC_VER_PAT(ver) (ver & ((1 << 12) - 1))
+#define CODEC_VER(ver) CODEC_VER_MAJ(ver), CODEC_VER_MIN(ver), CODEC_VER_PAT(ver)
+
+typedef struct FFVkVideoSession {
+    VkVideoSessionKHR session;
+    VkDeviceMemory *mem;
+    uint32_t nb_mem;
+
+    VkSamplerYcbcrConversion yuv_sampler;
+
+    AVBufferRef *dpb_hwfc_ref;
+    int layered_dpb;
+    AVFrame *layered_frame;
+    VkImageView layered_view;
+    VkImageAspectFlags layered_aspect;
+} FFVkVideoCommon;
+
+/**
+ * Get pixfmt from a Vulkan format.
+ */
+enum AVPixelFormat ff_vk_pix_fmt_from_vkfmt(VkFormat vkf);
+
+/**
+ * Get aspect bits which include all planes from a VkFormat.
+ */
+VkImageAspectFlags ff_vk_aspect_bits_from_vkfmt(VkFormat vkf);
+
+/**
+ * Get Vulkan's chroma subsampling from a pixfmt descriptor.
+ */
+VkVideoChromaSubsamplingFlagBitsKHR ff_vk_subsampling_from_av_desc(const AVPixFmtDescriptor *desc);
+
+/**
+ * Get Vulkan's bit depth from an [8:12] integer.
+ */
+VkVideoComponentBitDepthFlagBitsKHR ff_vk_depth_from_av_depth(int depth);
+
+/**
+ * Convert level from Vulkan to AV.
+ */
+int ff_vk_h264_level_to_av(StdVideoH264LevelIdc level);
+int ff_vk_h265_level_to_av(StdVideoH265LevelIdc level);
+
+StdVideoH264LevelIdc ff_vk_h264_level_to_vk(int level_idc);
+StdVideoH265LevelIdc ff_vk_h265_level_to_vk(int level_idc);
+StdVideoAV1Level     ff_vk_av1_level_to_vk(int level);
+
+/**
+ * Convert profile from/to AV to Vulkan
+ */
+StdVideoH264ProfileIdc ff_vk_h264_profile_to_vk(int profile);
+StdVideoH265ProfileIdc ff_vk_h265_profile_to_vk(int profile);
+StdVideoAV1Profile     ff_vk_av1_profile_to_vk(int profile);
+
+/**
+ * Creates image views for video frames.
+ */
+int ff_vk_create_view(FFVulkanContext *s, FFVkVideoCommon *common,
+                      VkImageView *view, VkImageAspectFlags *aspect,
+                      AVVkFrame *src, VkFormat vkf, int is_dpb);
+
+/**
+ * Initialize video session, allocating and binding necessary memory.
+ */
+int ff_vk_video_common_init(AVCodecContext *avctx, FFVulkanContext *s,
+                            FFVkVideoCommon *common,
+                            VkVideoSessionCreateInfoKHR *session_create);
+
+/**
+ * Free video session and required resources.
+ */
+void ff_vk_video_common_uninit(FFVulkanContext *s, FFVkVideoCommon *common);
+
+#endif /* AVCODEC_VULKAN_VIDEO_H */
-- 
2.49.1


From dde06811eeee2711405f8097b7c28aea38a80860 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:44:32 +0000
Subject: [PATCH 095/118] Changing vulkan file directory

---
 libavcodec/vulkan/common.comp | 279 ----------------------------------
 1 file changed, 279 deletions(-)
 delete mode 100644 libavcodec/vulkan/common.comp

diff --git a/libavcodec/vulkan/common.comp b/libavcodec/vulkan/common.comp
deleted file mode 100644
index 6825693fa3..0000000000
--- a/libavcodec/vulkan/common.comp
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (c) 2024 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-layout(buffer_reference, buffer_reference_align = 1) buffer u8buf {
-    uint8_t v;
-};
-
-layout(buffer_reference, buffer_reference_align = 1) buffer u8vec2buf {
-    u8vec2 v;
-};
-
-layout(buffer_reference, buffer_reference_align = 1) buffer u8vec4buf {
-    u8vec4 v;
-};
-
-layout(buffer_reference, buffer_reference_align = 2) buffer u16buf {
-    uint16_t v;
-};
-
-layout(buffer_reference, buffer_reference_align = 4) buffer u32buf {
-    uint32_t v;
-};
-
-layout(buffer_reference, buffer_reference_align = 4) buffer u32vec2buf {
-    u32vec2 v;
-};
-
-layout(buffer_reference, buffer_reference_align = 8) buffer u64buf {
-    uint64_t v;
-};
-
-#define OFFBUF(type, b, l) \
-    type(uint64_t(b) + uint64_t(l))
-
-#define zero_extend(a, p) \
-    ((a) & ((1 << (p)) - 1))
-
-#define sign_extend(val, bits) \
-    bitfieldExtract(val, 0, bits)
-
-#define fold(diff, bits) \
-    sign_extend(diff, bits)
-
-#define mid_pred(a, b, c) \
-    max(min((a), (b)), min(max((a), (b)), (c)))
-
-/* TODO: optimize */
-uint align(uint src, uint a)
-{
-    uint res = src % a;
-    if (res == 0)
-        return src;
-    return src + a - res;
-}
-
-/* TODO: optimize */
-uint64_t align64(uint64_t src, uint64_t a)
-{
-    uint64_t res = src % a;
-    if (res == 0)
-        return src;
-    return src + a - res;
-}
-
-#define reverse4(src) \
-    (pack32(unpack8(uint32_t(src)).wzyx))
-
-u32vec2 reverse8(uint64_t src)
-{
-    u32vec2 tmp = unpack32(src);
-    tmp.x = reverse4(tmp.x);
-    tmp.y = reverse4(tmp.y);
-    return tmp.yx;
-}
-
-#ifdef PB_32
-#define BIT_BUF_TYPE uint32_t
-#define BUF_TYPE u32buf
-#define BUF_REVERSE(src) reverse4(src)
-#define BUF_BITS uint8_t(32)
-#define BUF_BYTES uint8_t(4)
-#define BYTE_EXTRACT(src, byte_off) \
-    (uint8_t(bitfieldExtract((src), ((byte_off) << 3), 8)))
-#else
-#define BIT_BUF_TYPE uint64_t
-#define BUF_TYPE u32vec2buf
-#define BUF_REVERSE(src) reverse8(src)
-#define BUF_BITS uint8_t(64)
-#define BUF_BYTES uint8_t(8)
-#define BYTE_EXTRACT(src, byte_off) \
-    (uint8_t(((src) >> ((byte_off) << 3)) & 0xFF))
-#endif
-
-struct PutBitContext {
-    uint64_t buf_start;
-    uint64_t buf;
-
-    BIT_BUF_TYPE bit_buf;
-    uint8_t bit_left;
-};
-
-void put_bits(inout PutBitContext pb, const uint32_t n, uint32_t value)
-{
-    if (n < pb.bit_left) {
-        pb.bit_buf = (pb.bit_buf << n) | value;
-        pb.bit_left -= uint8_t(n);
-    } else {
-        pb.bit_buf <<= pb.bit_left;
-        pb.bit_buf |= (value >> (n - pb.bit_left));
-
-#ifdef PB_UNALIGNED
-        u8buf bs = u8buf(pb.buf);
-        [[unroll]]
-        for (uint8_t i = uint8_t(0); i < BUF_BYTES; i++)
-            bs[i].v = BYTE_EXTRACT(pb.bit_buf, BUF_BYTES - uint8_t(1) - i);
-#else
-#ifdef DEBUG
-        if ((pb.buf % BUF_BYTES) != 0)
-            debugPrintfEXT("put_bits buffer is not aligned!");
-#endif
-
-        BUF_TYPE bs = BUF_TYPE(pb.buf);
-        bs.v = BUF_REVERSE(pb.bit_buf);
-#endif
-        pb.buf = uint64_t(bs) + BUF_BYTES;
-
-        pb.bit_left += BUF_BITS - uint8_t(n);
-        pb.bit_buf = value;
-    }
-}
-
-uint32_t flush_put_bits(inout PutBitContext pb)
-{
-    /* Align bits to MSBs */
-    if (pb.bit_left < BUF_BITS)
-        pb.bit_buf <<= pb.bit_left;
-
-    if (pb.bit_left < BUF_BITS) {
-        uint to_write = ((BUF_BITS - pb.bit_left - 1) >> 3) + 1;
-
-        u8buf bs = u8buf(pb.buf);
-        for (int i = 0; i < to_write; i++)
-            bs[i].v = BYTE_EXTRACT(pb.bit_buf, BUF_BYTES - uint8_t(1) - i);
-        pb.buf = uint64_t(bs) + to_write;
-    }
-
-    pb.bit_left = BUF_BITS;
-    pb.bit_buf = 0x0;
-
-    return uint32_t(pb.buf - pb.buf_start);
-}
-
-void init_put_bits(out PutBitContext pb, u8buf data, uint64_t len)
-{
-    pb.buf_start = uint64_t(data);
-    pb.buf = uint64_t(data);
-
-    pb.bit_buf = 0;
-    pb.bit_left = BUF_BITS;
-}
-
-uint64_t put_bits_count(in PutBitContext pb)
-{
-    return (pb.buf - pb.buf_start)*8 + BUF_BITS - pb.bit_left;
-}
-
-uint32_t put_bytes_count(in PutBitContext pb)
-{
-    uint64_t num_bytes = (pb.buf - pb.buf_start) + ((BUF_BITS - pb.bit_left) >> 3);
-    return uint32_t(num_bytes);
-}
-
-struct GetBitContext {
-    uint64_t buf_start;
-    uint64_t buf;
-    uint64_t buf_end;
-
-    uint64_t bits;
-    int bits_valid;
-    int size_in_bits;
-};
-
-#define LOAD64()                                       \
-    {                                                  \
-        u8vec4buf ptr = u8vec4buf(gb.buf);             \
-        uint32_t rf1 = pack32((ptr[0].v).wzyx);        \
-        uint32_t rf2 = pack32((ptr[1].v).wzyx);        \
-        gb.buf += 8;                                   \
-        gb.bits = uint64_t(rf1) << 32 | uint64_t(rf2); \
-        gb.bits_valid = 64;                            \
-    }
-
-#define RELOAD32()                                                \
-    {                                                             \
-        u8vec4buf ptr = u8vec4buf(gb.buf);                        \
-        uint32_t rf = pack32((ptr[0].v).wzyx);                    \
-        gb.buf += 4;                                              \
-        gb.bits = uint64_t(rf) << (32 - gb.bits_valid) | gb.bits; \
-        gb.bits_valid += 32;                                      \
-    }
-
-void init_get_bits(inout GetBitContext gb, u8buf data, int len)
-{
-    gb.buf = gb.buf_start = uint64_t(data);
-    gb.buf_end = uint64_t(data) + len;
-    gb.size_in_bits = len * 8;
-
-    /* Preload */
-    LOAD64()
-}
-
-bool get_bit(inout GetBitContext gb)
-{
-    if (gb.bits_valid == 0)
-        LOAD64()
-
-    bool val = bool(gb.bits >> (64 - 1));
-    gb.bits <<= 1;
-    gb.bits_valid--;
-    return val;
-}
-
-uint get_bits(inout GetBitContext gb, int n)
-{
-    if (n == 0)
-        return 0;
-
-    if (n > gb.bits_valid)
-        RELOAD32()
-
-    uint val = uint(gb.bits >> (64 - n));
-    gb.bits <<= n;
-    gb.bits_valid -= n;
-    return val;
-}
-
-uint show_bits(inout GetBitContext gb, int n)
-{
-    if (n > gb.bits_valid)
-        RELOAD32()
-
-    return uint(gb.bits >> (64 - n));
-}
-
-void skip_bits(inout GetBitContext gb, int n)
-{
-    if (n > gb.bits_valid)
-        RELOAD32()
-
-    gb.bits <<= n;
-    gb.bits_valid -= n;
-}
-
-int tell_bits(in GetBitContext gb)
-{
-    return int(gb.buf - gb.buf_start) * 8 - gb.bits_valid;
-}
-
-int left_bits(in GetBitContext gb)
-{
-    return gb.size_in_bits - int(gb.buf - gb.buf_start) * 8 + gb.bits_valid;
-}
-- 
2.49.1


From f241968840f63c796955f65c57591201100b6a3b Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:44:41 +0000
Subject: [PATCH 096/118] Changing vulkan file directory

---
 libavcodec/vulkan/ffv1_common.comp | 181 -----------------------------
 1 file changed, 181 deletions(-)
 delete mode 100644 libavcodec/vulkan/ffv1_common.comp

diff --git a/libavcodec/vulkan/ffv1_common.comp b/libavcodec/vulkan/ffv1_common.comp
deleted file mode 100644
index 3d40592739..0000000000
--- a/libavcodec/vulkan/ffv1_common.comp
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * FFv1 codec
- *
- * Copyright (c) 2024 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-struct SliceContext {
-    RangeCoder c;
-
-#if !defined(DECODE)
-    PutBitContext pb; /* 8*8 bytes */
-#else
-    GetBitContext gb;
-#endif
-
-    ivec2 slice_dim;
-    ivec2 slice_pos;
-    ivec2 slice_rct_coef;
-    u8vec3 quant_table_idx;
-
-    uint hdr_len; // only used for golomb
-
-    uint slice_coding_mode;
-    bool slice_reset_contexts;
-};
-
-/* -1, { -1, 0 } */
-int predict(int L, ivec2 top)
-{
-    return mid_pred(L, L + top[1] - top[0], top[1]);
-}
-
-/* { -2, -1 }, { -1, 0, 1 }, 0 */
-int get_context(VTYPE2 cur_l, VTYPE3 top_l, TYPE top2, uint8_t quant_table_idx)
-{
-    const int LT = top_l[0]; /* -1 */
-    const int T  = top_l[1]; /*  0 */
-    const int RT = top_l[2]; /*  1 */
-    const int L  = cur_l[1]; /* -1 */
-
-    int base = quant_table[quant_table_idx][0][(L - LT) & MAX_QUANT_TABLE_MASK] +
-               quant_table[quant_table_idx][1][(LT - T) & MAX_QUANT_TABLE_MASK] +
-               quant_table[quant_table_idx][2][(T - RT) & MAX_QUANT_TABLE_MASK];
-
-    if ((quant_table[quant_table_idx][3][127] == 0) &&
-        (quant_table[quant_table_idx][4][127] == 0))
-        return base;
-
-    const int TT = top2;     /* -2 */
-    const int LL = cur_l[0]; /* -2 */
-    return base +
-           quant_table[quant_table_idx][3][(LL - L) & MAX_QUANT_TABLE_MASK] +
-           quant_table[quant_table_idx][4][(TT - T) & MAX_QUANT_TABLE_MASK];
-}
-
-const uint32_t log2_run[41] = {
-     0,  0,  0,  0,  1,  1,  1,  1,
-     2,  2,  2,  2,  3,  3,  3,  3,
-     4,  4,  5,  5,  6,  6,  7,  7,
-     8,  9, 10, 11, 12, 13, 14, 15,
-    16, 17, 18, 19, 20, 21, 22, 23,
-    24,
-};
-
-uint slice_coord(uint width, uint sx, uint num_h_slices, uint chroma_shift)
-{
-    uint mpw = 1 << chroma_shift;
-    uint awidth = align(width, mpw);
-
-    if ((version < 4) || ((version == 4) && (micro_version < 3)))
-        return width * sx / num_h_slices;
-
-    sx = (2 * awidth * sx + num_h_slices * mpw) / (2 * num_h_slices * mpw) * mpw;
-    if (sx == awidth)
-        sx = width;
-
-    return sx;
-}
-
-#ifdef RGB
-#define RGB_LBUF (RGB_LINECACHE - 1)
-#define LADDR(p) (ivec2((p).x, ((p).y & RGB_LBUF)))
-
-ivec2 get_pred(readonly uimage2D pred, ivec2 sp, ivec2 off,
-               int comp, int sw, uint8_t quant_table_idx, bool extend_lookup)
-{
-    const ivec2 yoff_border1 = expectEXT(off.x == 0, false) ? off + ivec2(1, -1) : off;
-
-    /* Thanks to the same coincidence as below, we can skip checking if off == 0, 1 */
-    VTYPE3 top  = VTYPE3(TYPE(imageLoad(pred, sp + LADDR(yoff_border1 + ivec2(-1, -1)))[comp]),
-                         TYPE(imageLoad(pred, sp + LADDR(off + ivec2(0, -1)))[comp]),
-                         TYPE(imageLoad(pred, sp + LADDR(off + ivec2(min(1, sw - off.x - 1), -1)))[comp]));
-
-    /* Normally, we'd need to check if off != ivec2(0, 0) here, since otherwise, we must
-     * return zero. However, ivec2(-1,  0) + ivec2(1, -1) == ivec2(0, -1), e.g. previous
-     * row, 0 offset, same slice, which is zero since we zero out the buffer for RGB */
-    TYPE cur = TYPE(imageLoad(pred, sp + LADDR(yoff_border1 + ivec2(-1,  0)))[comp]);
-
-    int base = quant_table[quant_table_idx][0][(cur    - top[0]) & MAX_QUANT_TABLE_MASK] +
-               quant_table[quant_table_idx][1][(top[0] - top[1]) & MAX_QUANT_TABLE_MASK] +
-               quant_table[quant_table_idx][2][(top[1] - top[2]) & MAX_QUANT_TABLE_MASK];
-
-    if (expectEXT(extend_lookup, false)) {
-        TYPE cur2 = TYPE(0);
-        if (expectEXT(off.x > 0, true)) {
-            const ivec2 yoff_border2 = expectEXT(off.x == 1, false) ? ivec2(-1, -1) : ivec2(-2, 0);
-            cur2 = TYPE(imageLoad(pred, sp + LADDR(off + yoff_border2))[comp]);
-        }
-        base += quant_table[quant_table_idx][3][(cur2 - cur) & MAX_QUANT_TABLE_MASK];
-
-        /* top-2 became current upon swap */
-        TYPE top2 = TYPE(imageLoad(pred, sp + LADDR(off))[comp]);
-        base += quant_table[quant_table_idx][4][(top2 - top[1]) & MAX_QUANT_TABLE_MASK];
-    }
-
-    /* context, prediction */
-    return ivec2(base, predict(cur, VTYPE2(top)));
-}
-
-#else /* RGB */
-
-#define LADDR(p) (p)
-
-ivec2 get_pred(readonly uimage2D pred, ivec2 sp, ivec2 off,
-               int comp, int sw, uint8_t quant_table_idx, bool extend_lookup)
-{
-    const ivec2 yoff_border1 = off.x == 0 ? ivec2(1, -1) : ivec2(0, 0);
-    sp += off;
-
-    VTYPE3 top  = VTYPE3(TYPE(0),
-                         TYPE(0),
-                         TYPE(0));
-    if (off.y > 0 && off != ivec2(0, 1))
-        top[0] = TYPE(imageLoad(pred, sp + ivec2(-1, -1) + yoff_border1)[comp]);
-    if (off.y > 0) {
-        top[1] = TYPE(imageLoad(pred, sp + ivec2(0, -1))[comp]);
-        top[2] = TYPE(imageLoad(pred, sp + ivec2(min(1, sw - off.x - 1), -1))[comp]);
-    }
-
-    TYPE cur = TYPE(0);
-    if (off != ivec2(0, 0))
-        cur = TYPE(imageLoad(pred, sp + ivec2(-1,  0) + yoff_border1)[comp]);
-
-    int base = quant_table[quant_table_idx][0][(cur - top[0]) & MAX_QUANT_TABLE_MASK] +
-               quant_table[quant_table_idx][1][(top[0] - top[1]) & MAX_QUANT_TABLE_MASK] +
-               quant_table[quant_table_idx][2][(top[1] - top[2]) & MAX_QUANT_TABLE_MASK];
-
-    if (expectEXT(extend_lookup, false)) {
-        TYPE cur2 = TYPE(0);
-        if (off.x > 0 && off != ivec2(1, 0)) {
-            const ivec2 yoff_border2 = off.x == 1 ? ivec2(1, -1) : ivec2(0, 0);
-            cur2 = TYPE(imageLoad(pred, sp + ivec2(-2,  0) + yoff_border2)[comp]);
-        }
-        base += quant_table[quant_table_idx][3][(cur2 - cur) & MAX_QUANT_TABLE_MASK];
-
-        TYPE top2 = TYPE(0);
-        if (off.y > 1)
-            top2 = TYPE(imageLoad(pred, sp + ivec2(0, -2))[comp]);
-        base += quant_table[quant_table_idx][4][(top2 - top[1]) & MAX_QUANT_TABLE_MASK];
-    }
-
-    /* context, prediction */
-    return ivec2(base, predict(cur, VTYPE2(top)));
-}
-#endif
-- 
2.49.1


From 568a7db96c8ab8035b6082a4791611b79f9f6443 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:44:50 +0000
Subject: [PATCH 097/118] Changing vulkan file directory

---
 libavcodec/vulkan/ffv1_dec.comp | 302 --------------------------------
 1 file changed, 302 deletions(-)
 delete mode 100644 libavcodec/vulkan/ffv1_dec.comp

diff --git a/libavcodec/vulkan/ffv1_dec.comp b/libavcodec/vulkan/ffv1_dec.comp
deleted file mode 100644
index eb795dcba4..0000000000
--- a/libavcodec/vulkan/ffv1_dec.comp
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * FFv1 codec
- *
- * Copyright (c) 2024 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef GOLOMB
-#ifdef CACHED_SYMBOL_READER
-shared uint8_t state[CONTEXT_SIZE];
-#define READ(c, off) get_rac_direct(c, state[off])
-#else
-#define READ(c, off) get_rac(c, uint64_t(slice_state) + (state_off + off))
-#endif
-
-int get_isymbol(inout RangeCoder c, uint state_off)
-{
-    if (READ(c, 0))
-        return 0;
-
-    uint e = 1;
-    for (; e < 33; e++)
-        if (!READ(c, min(e, 10)))
-            break;
-
-    if (expectEXT(e == 1, false)) {
-        return READ(c, 11) ? -1 : 1;
-    } else if (expectEXT(e == 33, false)) {
-        corrupt = true;
-        return 0;
-    }
-
-    int a = 1;
-    for (uint i = e + 20; i >= 22; i--) {
-        a <<= 1;
-        a |= int(READ(c, min(i, 31)));
-    }
-
-    return READ(c, min(e + 10, 21)) ? -a : a;
-}
-
-void decode_line_pcm(inout SliceContext sc, ivec2 sp, int w, int y, int p, int bits)
-{
-#ifdef CACHED_SYMBOL_READER
-    if (gl_LocalInvocationID.x > 0)
-        return;
-#endif
-
-#ifndef RGB
-    if (p > 0 && p < 3) {
-        w >>= chroma_shift.x;
-        sp >>= chroma_shift;
-    }
-#endif
-
-    for (int x = 0; x < w; x++) {
-        uint v = 0;
-        for (int i = (bits - 1); i >= 0; i--)
-            v |= uint(get_rac_equi(sc.c)) << i;
-
-        imageStore(dec[p], sp + LADDR(ivec2(x, y)), uvec4(v));
-    }
-}
-
-void decode_line(inout SliceContext sc, ivec2 sp, int w,
-                 int y, int p, int bits, uint state_off,
-                 uint8_t quant_table_idx, const int run_index)
-{
-#ifndef RGB
-    if (p > 0 && p < 3) {
-        w >>= chroma_shift.x;
-        sp >>= chroma_shift;
-    }
-#endif
-
-    for (int x = 0; x < w; x++) {
-        ivec2 pr = get_pred(dec[p], sp, ivec2(x, y), 0, w,
-                            quant_table_idx, extend_lookup[quant_table_idx] > 0);
-
-        uint context_off = state_off + CONTEXT_SIZE*abs(pr[0]);
-#ifdef CACHED_SYMBOL_READER
-        u8buf sb = u8buf(uint64_t(slice_state) + context_off + gl_LocalInvocationID.x);
-        state[gl_LocalInvocationID.x] = sb.v;
-        barrier();
-        if (gl_LocalInvocationID.x == 0) {
-
-#endif
-
-            int diff = get_isymbol(sc.c, context_off);
-            if (pr[0] < 0)
-                diff = -diff;
-
-            uint v = zero_extend(pr[1] + diff, bits);
-            imageStore(dec[p], sp + LADDR(ivec2(x, y)), uvec4(v));
-
-#ifdef CACHED_SYMBOL_READER
-        }
-
-        barrier();
-        sb.v = state[gl_LocalInvocationID.x];
-#endif
-    }
-}
-
-#else /* GOLOMB */
-
-void decode_line(inout SliceContext sc, ivec2 sp, int w,
-                 int y, int p, int bits, uint state_off,
-                 uint8_t quant_table_idx, inout int run_index)
-{
-#ifndef RGB
-    if (p > 0 && p < 3) {
-        w >>= chroma_shift.x;
-        sp >>= chroma_shift;
-    }
-#endif
-
-    int run_count = 0;
-    int run_mode  = 0;
-
-    for (int x = 0; x < w; x++) {
-        ivec2 pos = sp + ivec2(x, y);
-        int diff;
-        ivec2 pr = get_pred(dec[p], sp, ivec2(x, y), 0, w,
-                            quant_table_idx, extend_lookup[quant_table_idx] > 0);
-
-        uint context_off = state_off + VLC_STATE_SIZE*abs(pr[0]);
-        VlcState sb = VlcState(uint64_t(slice_state) + context_off);
-
-        if (pr[0] == 0 && run_mode == 0)
-            run_mode = 1;
-
-        if (run_mode != 0) {
-            if (run_count == 0 && run_mode == 1) {
-                int tmp_idx = int(log2_run[run_index]);
-                if (get_bit(sc.gb)) {
-                    run_count = 1 << tmp_idx;
-                    if (x + run_count <= w)
-                        run_index++;
-                } else {
-                    if (tmp_idx != 0) {
-                        run_count = int(get_bits(sc.gb, tmp_idx));
-                    } else
-                        run_count = 0;
-
-                    if (run_index != 0)
-                        run_index--;
-                    run_mode = 2;
-                }
-            }
-
-            run_count--;
-            if (run_count < 0) {
-                run_mode  = 0;
-                run_count = 0;
-                diff = read_vlc_symbol(sc.gb, sb, bits);
-                if (diff >= 0)
-                    diff++;
-            } else {
-                diff = 0;
-            }
-        } else {
-            diff = read_vlc_symbol(sc.gb, sb, bits);
-        }
-
-        if (pr[0] < 0)
-            diff = -diff;
-
-        uint v = zero_extend(pr[1] + diff, bits);
-        imageStore(dec[p], sp + LADDR(ivec2(x, y)), uvec4(v));
-    }
-}
-#endif
-
-#ifdef RGB
-ivec4 transform_sample(ivec4 pix, ivec2 rct_coef)
-{
-    pix.b -= rct_offset;
-    pix.r -= rct_offset;
-    pix.g -= (pix.b*rct_coef.y + pix.r*rct_coef.x) >> 2;
-    pix.b += pix.g;
-    pix.r += pix.g;
-    return ivec4(pix[fmt_lut[0]], pix[fmt_lut[1]],
-                 pix[fmt_lut[2]], pix[fmt_lut[3]]);
-}
-
-void writeout_rgb(in SliceContext sc, ivec2 sp, int w, int y, bool apply_rct)
-{
-    for (uint x = gl_LocalInvocationID.x; x < w; x += gl_WorkGroupSize.x) {
-        ivec2 lpos = sp + LADDR(ivec2(x, y));
-        ivec2 pos = sc.slice_pos + ivec2(x, y);
-
-        ivec4 pix;
-        pix.r = int(imageLoad(dec[2], lpos)[0]);
-        pix.g = int(imageLoad(dec[0], lpos)[0]);
-        pix.b = int(imageLoad(dec[1], lpos)[0]);
-        if (transparency != 0)
-            pix.a = int(imageLoad(dec[3], lpos)[0]);
-
-        if (expectEXT(apply_rct, true))
-            pix = transform_sample(pix, sc.slice_rct_coef);
-
-        imageStore(dst[0], pos, pix);
-        if (planar_rgb != 0) {
-            for (int i = 1; i < color_planes; i++)
-                imageStore(dst[i], pos, ivec4(pix[i]));
-        }
-    }
-}
-#endif
-
-void decode_slice(inout SliceContext sc, const uint slice_idx)
-{
-    int w = sc.slice_dim.x;
-    ivec2 sp = sc.slice_pos;
-
-#ifndef RGB
-    int bits = bits_per_raw_sample;
-#else
-    int bits = 9;
-    if (bits != 8 || sc.slice_coding_mode != 0)
-        bits = bits_per_raw_sample + int(sc.slice_coding_mode != 1);
-
-    sp.y = int(gl_WorkGroupID.y)*RGB_LINECACHE;
-#endif
-
-    /* PCM coding */
-#ifndef GOLOMB
-    if (sc.slice_coding_mode == 1) {
-#ifndef RGB
-        for (int p = 0; p < planes; p++) {
-            int h = sc.slice_dim.y;
-            if (p > 0 && p < 3)
-                h >>= chroma_shift.y;
-
-            for (int y = 0; y < h; y++)
-                decode_line_pcm(sc, sp, w, y, p, bits);
-        }
-#else
-        for (int y = 0; y < sc.slice_dim.y; y++) {
-            for (int p = 0; p < color_planes; p++)
-                decode_line_pcm(sc, sp, w, y, p, bits);
-
-            writeout_rgb(sc, sp, w, y, false);
-        }
-#endif
-    } else
-
-    /* Arithmetic coding */
-#endif
-    {
-        u8vec4 quant_table_idx = sc.quant_table_idx.xyyz;
-        u32vec4 slice_state_off = (slice_idx*codec_planes + uvec4(0, 1, 1, 2))*plane_state_size;
-
-#ifndef RGB
-        for (int p = 0; p < planes; p++) {
-            int h = sc.slice_dim.y;
-            if (p > 0 && p < 3)
-                h >>= chroma_shift.y;
-
-            int run_index = 0;
-            for (int y = 0; y < h; y++)
-                decode_line(sc, sp, w, y, p, bits,
-                            slice_state_off[p], quant_table_idx[p], run_index);
-        }
-#else
-        int run_index = 0;
-        for (int y = 0; y < sc.slice_dim.y; y++) {
-            for (int p = 0; p < color_planes; p++)
-                decode_line(sc, sp, w, y, p, bits,
-                            slice_state_off[p], quant_table_idx[p], run_index);
-
-            writeout_rgb(sc, sp, w, y, true);
-        }
-#endif
-    }
-}
-
-void main(void)
-{
-    const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;
-    decode_slice(slice_ctx[slice_idx], slice_idx);
-
-    uint32_t status = corrupt ? uint32_t(corrupt) : overread;
-    if (status != 0)
-        slice_status[2*slice_idx + 1] = status;
-}
-- 
2.49.1


From 9fa42bc2aa39806085cf6093a280f4e8b038e0ab Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:45:00 +0000
Subject: [PATCH 098/118] Changing vulkan file directory

---
 libavcodec/vulkan/ffv1_dec_setup.comp | 140 --------------------------
 1 file changed, 140 deletions(-)
 delete mode 100644 libavcodec/vulkan/ffv1_dec_setup.comp

diff --git a/libavcodec/vulkan/ffv1_dec_setup.comp b/libavcodec/vulkan/ffv1_dec_setup.comp
deleted file mode 100644
index 5da09df21c..0000000000
--- a/libavcodec/vulkan/ffv1_dec_setup.comp
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * FFv1 codec
- *
- * Copyright (c) 2024 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-uint8_t setup_state[CONTEXT_SIZE];
-
-uint get_usymbol(inout RangeCoder c)
-{
-    if (get_rac_direct(c, setup_state[0]))
-        return 0;
-
-    int e = 0;
-    while (get_rac_direct(c, setup_state[1 + min(e, 9)])) { // 1..10
-        e++;
-        if (e > 31) {
-            corrupt = true;
-            return 0;
-        }
-    }
-
-    uint a = 1;
-    for (int i = e - 1; i >= 0; i--) {
-        a <<= 1;
-        a |= uint(get_rac_direct(c, setup_state[22 + min(i, 9)]));  // 22..31
-    }
-
-    return a;
-}
-
-bool decode_slice_header(inout SliceContext sc)
-{
-    [[unroll]]
-    for (int i = 0; i < CONTEXT_SIZE; i++)
-        setup_state[i] = uint8_t(128);
-
-    uint sx = get_usymbol(sc.c);
-    uint sy = get_usymbol(sc.c);
-    uint sw = get_usymbol(sc.c) + 1;
-    uint sh = get_usymbol(sc.c) + 1;
-
-    if (sx < 0 || sy < 0 || sw <= 0 || sh <= 0 ||
-        sx > (gl_NumWorkGroups.x - sw) || sy > (gl_NumWorkGroups.y - sh) ||
-        corrupt) {
-        return true;
-    }
-
-    /* Set coordinates */
-    uint sxs = slice_coord(img_size.x, sx     , gl_NumWorkGroups.x, chroma_shift.x);
-    uint sxe = slice_coord(img_size.x, sx + sw, gl_NumWorkGroups.x, chroma_shift.x);
-    uint sys = slice_coord(img_size.y, sy     , gl_NumWorkGroups.y, chroma_shift.y);
-    uint sye = slice_coord(img_size.y, sy + sh, gl_NumWorkGroups.y, chroma_shift.y);
-
-    sc.slice_pos = ivec2(sxs, sys);
-    sc.slice_dim = ivec2(sxe - sxs, sye - sys);
-    sc.slice_rct_coef = ivec2(1, 1);
-    sc.slice_coding_mode = int(0);
-
-    for (uint i = 0; i < codec_planes; i++) {
-        uint idx = get_usymbol(sc.c);
-        if (idx >= quant_table_count)
-            return true;
-        sc.quant_table_idx[i] = uint8_t(idx);
-    }
-
-    get_usymbol(sc.c);
-    get_usymbol(sc.c);
-    get_usymbol(sc.c);
-
-    if (version >= 4) {
-        sc.slice_reset_contexts = get_rac_direct(sc.c, setup_state[0]);
-        sc.slice_coding_mode = get_usymbol(sc.c);
-        if (sc.slice_coding_mode != 1 && colorspace == 1) {
-            sc.slice_rct_coef.x = int(get_usymbol(sc.c));
-            sc.slice_rct_coef.y = int(get_usymbol(sc.c));
-            if (sc.slice_rct_coef.x + sc.slice_rct_coef.y > 4)
-                return true;
-        }
-    }
-
-    return false;
-}
-
-void golomb_init(inout SliceContext sc)
-{
-    if (version == 3 && micro_version > 1 || version > 3) {
-        setup_state[0] = uint8_t(129);
-        get_rac_direct(sc.c, setup_state[0]);
-    }
-
-    uint64_t ac_byte_count = sc.c.bytestream - sc.c.bytestream_start - 1;
-    init_get_bits(sc.gb, u8buf(sc.c.bytestream_start + ac_byte_count),
-                  int(sc.c.bytestream_end - sc.c.bytestream_start - ac_byte_count));
-}
-
-void main(void)
-{
-    const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;
-
-    u8buf bs = u8buf(slice_data + slice_offsets[2*slice_idx + 0]);
-    uint32_t slice_size = slice_offsets[2*slice_idx + 1];
-
-    rac_init_dec(slice_ctx[slice_idx].c,
-                 bs, slice_size);
-
-    if (slice_idx == (gl_NumWorkGroups.x*gl_NumWorkGroups.y - 1))
-        get_rac_equi(slice_ctx[slice_idx].c);
-
-    decode_slice_header(slice_ctx[slice_idx]);
-
-    if (golomb == 1)
-        golomb_init(slice_ctx[slice_idx]);
-
-    if (ec != 0 && check_crc != 0) {
-        uint32_t crc = crcref;
-        for (int i = 0; i < slice_size; i++)
-            crc = crc_ieee[(crc & 0xFF) ^ uint32_t(bs[i].v)] ^ (crc >> 8);
-
-        slice_status[2*slice_idx + 0] = crc;
-    }
-
-    slice_status[2*slice_idx + 1] = corrupt ? uint32_t(corrupt) : overread;
-}
-- 
2.49.1


From e05343395790ad698ea8bcae0ff95be1a1199568 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:45:09 +0000
Subject: [PATCH 099/118] Changing vulkan file directory

---
 libavcodec/vulkan/ffv1_enc.comp | 358 --------------------------------
 1 file changed, 358 deletions(-)
 delete mode 100644 libavcodec/vulkan/ffv1_enc.comp

diff --git a/libavcodec/vulkan/ffv1_enc.comp b/libavcodec/vulkan/ffv1_enc.comp
deleted file mode 100644
index 78372f5b3a..0000000000
--- a/libavcodec/vulkan/ffv1_enc.comp
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * FFv1 codec
- *
- * Copyright (c) 2024 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef GOLOMB
-#ifdef CACHED_SYMBOL_READER
-shared uint8_t state[CONTEXT_SIZE];
-#define WRITE(c, off, val) put_rac_direct(c, state[off], val)
-#else
-#define WRITE(c, off, val) put_rac(c, uint64_t(slice_state) + (state_off + off), val)
-#endif
-
-/* Note - only handles signed values */
-void put_symbol(inout RangeCoder c, uint state_off, int v)
-{
-    bool is_nil = (v == 0);
-    WRITE(c, 0, is_nil);
-    if (is_nil)
-        return;
-
-    const int a = abs(v);
-    const int e = findMSB(a);
-
-    for (int i = 0; i < e; i++)
-        WRITE(c, 1 + min(i, 9), true);
-    WRITE(c, 1 + min(e, 9), false);
-
-    for (int i = e - 1; i >= 0; i--)
-        WRITE(c, 22 + min(i, 9), bool(bitfieldExtract(a, i, 1)));
-
-    WRITE(c, 22 - 11 + min(e, 10), v < 0);
-}
-
-void encode_line_pcm(inout SliceContext sc, readonly uimage2D img,
-                     ivec2 sp, int y, int p, int comp, int bits)
-{
-    int w = sc.slice_dim.x;
-
-#ifdef CACHED_SYMBOL_READER
-    if (gl_LocalInvocationID.x > 0)
-        return;
-#endif
-
-#ifndef RGB
-    if (p > 0 && p < 3) {
-        w >>= chroma_shift.x;
-        sp >>= chroma_shift;
-    }
-#endif
-
-    for (int x = 0; x < w; x++) {
-        uint v = imageLoad(img, sp + LADDR(ivec2(x, y)))[comp];
-        for (int i = (bits - 1); i >= 0; i--)
-            put_rac_equi(sc.c, bool(bitfieldExtract(v, i, 1)));
-    }
-}
-
-void encode_line(inout SliceContext sc, readonly uimage2D img, uint state_off,
-                 ivec2 sp, int y, int p, int comp, int bits,
-                 uint8_t quant_table_idx, const int run_index)
-{
-    int w = sc.slice_dim.x;
-
-#ifndef RGB
-    if (p > 0 && p < 3) {
-        w >>= chroma_shift.x;
-        sp >>= chroma_shift;
-    }
-#endif
-
-    for (int x = 0; x < w; x++) {
-        ivec2 d = get_pred(img, sp, ivec2(x, y), comp, w,
-                           quant_table_idx, extend_lookup[quant_table_idx] > 0);
-        d[1] = int(imageLoad(img, sp + LADDR(ivec2(x, y)))[comp]) - d[1];
-
-        if (d[0] < 0)
-            d = -d;
-
-        d[1] = fold(d[1], bits);
-
-        uint context_off = state_off + CONTEXT_SIZE*d[0];
-#ifdef CACHED_SYMBOL_READER
-        u8buf sb = u8buf(uint64_t(slice_state) + context_off + gl_LocalInvocationID.x);
-        state[gl_LocalInvocationID.x] = sb.v;
-        barrier();
-        if (gl_LocalInvocationID.x == 0)
-#endif
-
-            put_symbol(sc.c, context_off, d[1]);
-
-#ifdef CACHED_SYMBOL_READER
-        barrier();
-        sb.v = state[gl_LocalInvocationID.x];
-#endif
-    }
-}
-
-#else /* GOLOMB */
-
-void encode_line(inout SliceContext sc, readonly uimage2D img, uint state_off,
-                 ivec2 sp, int y, int p, int comp, int bits,
-                 uint8_t quant_table_idx, inout int run_index)
-{
-    int w = sc.slice_dim.x;
-
-#ifndef RGB
-    if (p > 0 && p < 3) {
-        w >>= chroma_shift.x;
-        sp >>= chroma_shift;
-    }
-#endif
-
-    int run_count = 0;
-    bool run_mode = false;
-
-    for (int x = 0; x < w; x++) {
-        ivec2 d = get_pred(img, sp, ivec2(x, y), comp, w,
-                           quant_table_idx, extend_lookup[quant_table_idx] > 0);
-        d[1] = int(imageLoad(img, sp + LADDR(ivec2(x, y)))[comp]) - d[1];
-
-        if (d[0] < 0)
-            d = -d;
-
-        d[1] = fold(d[1], bits);
-
-        if (d[0] == 0)
-            run_mode = true;
-
-        if (run_mode) {
-            if (d[1] != 0) {
-                /* A very unlikely loop */
-                while (run_count >= 1 << log2_run[run_index]) {
-                    run_count -= 1 << log2_run[run_index];
-                    run_index++;
-                    put_bits(sc.pb, 1, 1);
-                }
-
-                put_bits(sc.pb, 1 + log2_run[run_index], run_count);
-                if (run_index != 0)
-                    run_index--;
-                run_count = 0;
-                run_mode  = false;
-                if (d[1] > 0)
-                    d[1]--;
-            } else {
-                run_count++;
-            }
-        }
-
-        if (!run_mode) {
-            VlcState sb = VlcState(uint64_t(slice_state) + state_off + VLC_STATE_SIZE*d[0]);
-            Symbol sym = get_vlc_symbol(sb, d[1], bits);
-            put_bits(sc.pb, sym.bits, sym.val);
-        }
-    }
-
-    if (run_mode) {
-        while (run_count >= (1 << log2_run[run_index])) {
-            run_count -= 1 << log2_run[run_index];
-            run_index++;
-            put_bits(sc.pb, 1, 1);
-        }
-
-        if (run_count > 0)
-            put_bits(sc.pb, 1, 1);
-    }
-}
-#endif
-
-#ifdef RGB
-ivec4 load_components(ivec2 pos)
-{
-    ivec4 pix = ivec4(imageLoad(src[0], pos));
-    if (planar_rgb != 0) {
-        for (int i = 1; i < (3 + transparency); i++)
-            pix[i] = int(imageLoad(src[i], pos)[0]);
-    }
-
-    return ivec4(pix[fmt_lut[0]], pix[fmt_lut[1]],
-                 pix[fmt_lut[2]], pix[fmt_lut[3]]);
-}
-
-void transform_sample(inout ivec4 pix, ivec2 rct_coef)
-{
-    pix.b -= pix.g;
-    pix.r -= pix.g;
-    pix.g += (pix.r*rct_coef.x + pix.b*rct_coef.y) >> 2;
-    pix.b += rct_offset;
-    pix.r += rct_offset;
-}
-
-void preload_rgb(in SliceContext sc, ivec2 sp, int w, int y, bool apply_rct)
-{
-    for (uint x = gl_LocalInvocationID.x; x < w; x += gl_WorkGroupSize.x) {
-        ivec2 lpos = sp + LADDR(ivec2(x, y));
-        ivec2 pos = sc.slice_pos + ivec2(x, y);
-
-        ivec4 pix = load_components(pos);
-
-        if (expectEXT(apply_rct, true))
-            transform_sample(pix, sc.slice_rct_coef);
-
-        imageStore(tmp, lpos, pix);
-    }
-}
-#endif
-
-void encode_slice(inout SliceContext sc, const uint slice_idx)
-{
-    ivec2 sp = sc.slice_pos;
-
-#ifndef RGB
-    int bits = bits_per_raw_sample;
-#else
-    int bits = 9;
-    if (bits != 8 || sc.slice_coding_mode != 0)
-        bits = bits_per_raw_sample + int(sc.slice_coding_mode != 1);
-
-    sp.y = int(gl_WorkGroupID.y)*RGB_LINECACHE;
-#endif
-
-#ifndef GOLOMB
-    if (sc.slice_coding_mode == 1) {
-#ifndef RGB
-        for (int c = 0; c < components; c++) {
-
-            int h = sc.slice_dim.y;
-            if (c > 0 && c < 3)
-                h >>= chroma_shift.y;
-
-            /* Takes into account dual-plane YUV formats */
-            int p = min(c, planes - 1);
-            int comp = c - p;
-
-            for (int y = 0; y < h; y++)
-                encode_line_pcm(sc, src[p], sp, y, p, comp, bits);
-        }
-#else
-        for (int y = 0; y < sc.slice_dim.y; y++) {
-            preload_rgb(sc, sp, sc.slice_dim.x, y, false);
-
-            encode_line_pcm(sc, tmp, sp, y, 0, 1, bits);
-            encode_line_pcm(sc, tmp, sp, y, 0, 2, bits);
-            encode_line_pcm(sc, tmp, sp, y, 0, 0, bits);
-            if (transparency == 1)
-                encode_line_pcm(sc, tmp, sp, y, 0, 3, bits);
-        }
-#endif
-    } else
-#endif
-    {
-        u8vec4 quant_table_idx = sc.quant_table_idx.xyyz;
-        u32vec4 slice_state_off = (slice_idx*codec_planes + uvec4(0, 1, 1, 2))*plane_state_size;
-
-#ifndef RGB
-        for (int c = 0; c < components; c++) {
-            int run_index = 0;
-
-            int h = sc.slice_dim.y;
-            if (c > 0 && c < 3)
-                h >>= chroma_shift.y;
-
-            int p = min(c, planes - 1);
-            int comp = c - p;
-
-            for (int y = 0; y < h; y++)
-                encode_line(sc, src[p], slice_state_off[c], sp, y, p,
-                            comp, bits, quant_table_idx[c], run_index);
-        }
-#else
-        int run_index = 0;
-        for (int y = 0; y < sc.slice_dim.y; y++) {
-            preload_rgb(sc, sp, sc.slice_dim.x, y, true);
-
-            encode_line(sc, tmp, slice_state_off[0],
-                        sp, y, 0, 1, bits, quant_table_idx[0], run_index);
-            encode_line(sc, tmp, slice_state_off[1],
-                        sp, y, 0, 2, bits, quant_table_idx[1], run_index);
-            encode_line(sc, tmp, slice_state_off[2],
-                        sp, y, 0, 0, bits, quant_table_idx[2], run_index);
-            if (transparency == 1)
-                encode_line(sc, tmp, slice_state_off[3],
-                            sp, y, 0, 3, bits, quant_table_idx[3], run_index);
-        }
-#endif
-    }
-}
-
-void finalize_slice(inout SliceContext sc, const uint slice_idx)
-{
-#ifdef CACHED_SYMBOL_READER
-    if (gl_LocalInvocationID.x > 0)
-        return;
-#endif
-
-#ifdef GOLOMB
-    uint32_t enc_len = sc.hdr_len + flush_put_bits(sc.pb);
-#else
-    uint32_t enc_len = rac_terminate(sc.c);
-#endif
-
-    u8buf bs = u8buf(sc.c.bytestream_start);
-
-    /* Append slice length */
-    u8vec4 enc_len_p = unpack8(enc_len);
-    bs[enc_len + 0].v = enc_len_p.z;
-    bs[enc_len + 1].v = enc_len_p.y;
-    bs[enc_len + 2].v = enc_len_p.x;
-    enc_len += 3;
-
-    /* Calculate and write CRC */
-    if (ec != 0) {
-        bs[enc_len].v = uint8_t(0);
-        enc_len++;
-
-        uint32_t crc = crcref;
-        for (int i = 0; i < enc_len; i++)
-            crc = crc_ieee[(crc & 0xFF) ^ uint32_t(bs[i].v)] ^ (crc >> 8);
-
-        if (crcref != 0x00000000)
-            crc ^= 0x8CD88196;
-
-        u8vec4 crc_p = unpack8(crc);
-        bs[enc_len + 0].v = crc_p.x;
-        bs[enc_len + 1].v = crc_p.y;
-        bs[enc_len + 2].v = crc_p.z;
-        bs[enc_len + 3].v = crc_p.w;
-        enc_len += 4;
-    }
-
-    slice_results[slice_idx*2 + 0] = enc_len;
-    slice_results[slice_idx*2 + 1] = uint64_t(bs) - uint64_t(out_data);
-}
-
-void main(void)
-{
-    const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;
-    encode_slice(slice_ctx[slice_idx], slice_idx);
-    finalize_slice(slice_ctx[slice_idx], slice_idx);
-}
-- 
2.49.1


From ee72295e48e812d416d1865b6336292d7a6f42b2 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:45:26 +0000
Subject: [PATCH 100/118] Changing vulkan file directory

---
 libavcodec/vulkan/ffv1_enc_rct.comp | 79 -----------------------------
 1 file changed, 79 deletions(-)
 delete mode 100644 libavcodec/vulkan/ffv1_enc_rct.comp

diff --git a/libavcodec/vulkan/ffv1_enc_rct.comp b/libavcodec/vulkan/ffv1_enc_rct.comp
deleted file mode 100644
index b611f4be98..0000000000
--- a/libavcodec/vulkan/ffv1_enc_rct.comp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * FFv1 codec
- *
- * Copyright (c) 2024 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-ivec4 load_components(ivec2 pos)
-{
-    ivec4 pix = ivec4(imageLoad(src[0], pos));
-    if (planar_rgb != 0) {
-        for (int i = 1; i < (3 + transparency); i++)
-            pix[i] = int(imageLoad(src[i], pos)[0]);
-    }
-
-    return ivec4(pix[fmt_lut[0]], pix[fmt_lut[1]],
-                 pix[fmt_lut[2]], pix[fmt_lut[3]]);
-}
-
-void bypass_sample(ivec2 pos)
-{
-    imageStore(dst[0], pos, load_components(pos));
-}
-
-void bypass_block(in SliceContext sc)
-{
-    ivec2 start = ivec2(gl_LocalInvocationID) + sc.slice_pos;
-    ivec2 end = sc.slice_pos + sc.slice_dim;
-    for (uint y = start.y; y < end.y; y += gl_WorkGroupSize.y)
-        for (uint x = start.x; x < end.x; x += gl_WorkGroupSize.x)
-            bypass_sample(ivec2(x, y));
-}
-
-void transform_sample(ivec2 pos, ivec2 rct_coef)
-{
-    ivec4 pix = load_components(pos);
-    pix.b -= pix.g;
-    pix.r -= pix.g;
-    pix.g += (pix.r*rct_coef.x + pix.b*rct_coef.y) >> 2;
-    pix.b += offset;
-    pix.r += offset;
-    imageStore(dst[0], pos, pix);
-}
-
-void transform_block(in SliceContext sc)
-{
-    const ivec2 rct_coef = sc.slice_rct_coef;
-    const ivec2 start = ivec2(gl_LocalInvocationID) + sc.slice_pos;
-    const ivec2 end = sc.slice_pos + sc.slice_dim;
-
-    for (uint y = start.y; y < end.y; y += gl_WorkGroupSize.y)
-        for (uint x = start.x; x < end.x; x += gl_WorkGroupSize.x)
-            transform_sample(ivec2(x, y), rct_coef);
-}
-
-void main()
-{
-    const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;
-
-    if (slice_ctx[slice_idx].slice_coding_mode == 1)
-        bypass_block(slice_ctx[slice_idx]);
-    else
-        transform_block(slice_ctx[slice_idx]);
-}
-- 
2.49.1


From 24394e99ef5cef3d53e68498149ea7ebca4ea64a Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:45:42 +0000
Subject: [PATCH 101/118] Changing vulkan file directory

---
 libavcodec/vulkan/ffv1_enc_setup.comp | 126 --------------------------
 1 file changed, 126 deletions(-)
 delete mode 100644 libavcodec/vulkan/ffv1_enc_setup.comp

diff --git a/libavcodec/vulkan/ffv1_enc_setup.comp b/libavcodec/vulkan/ffv1_enc_setup.comp
deleted file mode 100644
index 5f8e6704b0..0000000000
--- a/libavcodec/vulkan/ffv1_enc_setup.comp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * FFv1 codec
- *
- * Copyright (c) 2024 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-uint8_t state[CONTEXT_SIZE];
-
-void init_slice(inout SliceContext sc, const uint slice_idx)
-{
-    /* Set coordinates */
-    uvec2 img_size = imageSize(src[0]);
-    uint sxs = slice_coord(img_size.x, gl_WorkGroupID.x + 0,
-                           gl_NumWorkGroups.x, chroma_shift.x);
-    uint sxe = slice_coord(img_size.x, gl_WorkGroupID.x + 1,
-                           gl_NumWorkGroups.x, chroma_shift.x);
-    uint sys = slice_coord(img_size.y, gl_WorkGroupID.y + 0,
-                           gl_NumWorkGroups.y, chroma_shift.y);
-    uint sye = slice_coord(img_size.y, gl_WorkGroupID.y + 1,
-                           gl_NumWorkGroups.y, chroma_shift.y);
-
-    sc.slice_pos = ivec2(sxs, sys);
-    sc.slice_dim = ivec2(sxe - sxs, sye - sys);
-    sc.slice_coding_mode = int(force_pcm == 1);
-    sc.slice_reset_contexts = sc.slice_coding_mode == 1;
-    sc.quant_table_idx = u8vec3(context_model);
-
-    if ((rct_search == 0) || (sc.slice_coding_mode == 1))
-        sc.slice_rct_coef = ivec2(1, 1);
-
-    rac_init(sc.c,
-             OFFBUF(u8buf, out_data, slice_idx * slice_size_max),
-             slice_size_max);
-}
-
-void put_usymbol(inout RangeCoder c, uint v)
-{
-    bool is_nil = (v == 0);
-    put_rac_direct(c, state[0], is_nil);
-    if (is_nil)
-        return;
-
-    const int e = findMSB(v);
-
-    for (int i = 0; i < e; i++)
-        put_rac_direct(c, state[1 + min(i, 9)], true);
-    put_rac_direct(c, state[1 + min(e, 9)], false);
-
-    for (int i = e - 1; i >= 0; i--)
-        put_rac_direct(c, state[22 + min(i, 9)], bool(bitfieldExtract(v, i, 1)));
-}
-
-void write_slice_header(inout SliceContext sc)
-{
-    [[unroll]]
-    for (int i = 0; i < CONTEXT_SIZE; i++)
-        state[i] = uint8_t(128);
-
-    put_usymbol(sc.c, gl_WorkGroupID.x);
-    put_usymbol(sc.c, gl_WorkGroupID.y);
-    put_usymbol(sc.c, 0);
-    put_usymbol(sc.c, 0);
-
-    for (int i = 0; i < codec_planes; i++)
-        put_usymbol(sc.c, sc.quant_table_idx[i]);
-
-    put_usymbol(sc.c, pic_mode);
-    put_usymbol(sc.c, sar.x);
-    put_usymbol(sc.c, sar.y);
-
-    if (version >= 4) {
-        put_rac_direct(sc.c, state[0], sc.slice_reset_contexts);
-        put_usymbol(sc.c, sc.slice_coding_mode);
-        if (sc.slice_coding_mode != 1 && colorspace == 1) {
-            put_usymbol(sc.c, sc.slice_rct_coef.y);
-            put_usymbol(sc.c, sc.slice_rct_coef.x);
-        }
-    }
-}
-
-void write_frame_header(inout SliceContext sc)
-{
-    put_rac_equi(sc.c, bool(key_frame));
-}
-
-#ifdef GOLOMB
-void init_golomb(inout SliceContext sc)
-{
-    sc.hdr_len = rac_terminate(sc.c);
-    init_put_bits(sc.pb,
-                  OFFBUF(u8buf, sc.c.bytestream_start, sc.hdr_len),
-                  slice_size_max - sc.hdr_len);
-}
-#endif
-
-void main(void)
-{
-    const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;
-
-    init_slice(slice_ctx[slice_idx], slice_idx);
-
-    if (slice_idx == 0)
-        write_frame_header(slice_ctx[slice_idx]);
-
-    write_slice_header(slice_ctx[slice_idx]);
-
-#ifdef GOLOMB
-    init_golomb(slice_ctx[slice_idx]);
-#endif
-}
-- 
2.49.1


From e007175b4b786003be145c307de81c6690a3a7d0 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:45:58 +0000
Subject: [PATCH 102/118] Changing vulkan file directory

---
 libavcodec/vulkan/ffv1_rct.comp | 90 ---------------------------------
 1 file changed, 90 deletions(-)
 delete mode 100644 libavcodec/vulkan/ffv1_rct.comp

diff --git a/libavcodec/vulkan/ffv1_rct.comp b/libavcodec/vulkan/ffv1_rct.comp
deleted file mode 100644
index b10bb47132..0000000000
--- a/libavcodec/vulkan/ffv1_rct.comp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * FFv1 codec
- *
- * Copyright (c) 2024 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-ivec4 load_components(ivec2 pos)
-{
-    ivec4 pix = ivec4(imageLoad(src[0], pos));
-    if (planar_rgb != 0) {
-        for (int i = 1; i < (3 + transparency); i++)
-            pix[i] = int(imageLoad(src[i], pos)[0]);
-    }
-
-    return ivec4(pix[fmt_lut[0]], pix[fmt_lut[1]],
-                 pix[fmt_lut[2]], pix[fmt_lut[3]]);
-}
-
-void bypass_sample(ivec2 pos)
-{
-    imageStore(dst[0], pos, load_components(pos));
-}
-
-void bypass_block(in SliceContext sc)
-{
-    ivec2 start = ivec2(gl_LocalInvocationID) + sc.slice_pos;
-    ivec2 end = sc.slice_pos + sc.slice_dim;
-    for (uint y = start.y; y < end.y; y += gl_WorkGroupSize.y)
-        for (uint x = start.x; x < end.x; x += gl_WorkGroupSize.x)
-            bypass_sample(ivec2(x, y));
-}
-
-void transform_sample(ivec2 pos, ivec2 rct_coef)
-{
-    ivec4 pix = load_components(pos);
-    pix.b -= offset;
-    pix.r -= offset;
-    pix.g -= (pix.r*rct_coef.x + pix.b*rct_coef.y) >> 2;
-    pix.b += pix.g;
-    pix.r += pix.g;
-    imageStore(dst[0], pos, pix);
-}
-
-void transform_sample(ivec2 pos, ivec2 rct_coef)
-{
-    ivec4 pix = load_components(pos);
-    pix.b -= pix.g;
-    pix.r -= pix.g;
-    pix.g += (pix.r*rct_coef.x + pix.b*rct_coef.y) >> 2;
-    pix.b += offset;
-    pix.r += offset;
-    imageStore(dst[0], pos, pix);
-}
-
-void transform_block(in SliceContext sc)
-{
-    const ivec2 rct_coef = sc.slice_rct_coef;
-    const ivec2 start = ivec2(gl_LocalInvocationID) + sc.slice_pos;
-    const ivec2 end = sc.slice_pos + sc.slice_dim;
-
-    for (uint y = start.y; y < end.y; y += gl_WorkGroupSize.y)
-        for (uint x = start.x; x < end.x; x += gl_WorkGroupSize.x)
-            transform_sample(ivec2(x, y), rct_coef);
-}
-
-void main()
-{
-    const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;
-
-    if (slice_ctx[slice_idx].slice_coding_mode == 1)
-        bypass_block(slice_ctx[slice_idx]);
-    else
-        transform_block(slice_ctx[slice_idx]);
-}
-- 
2.49.1


From 1b7b18b6595d5ca5d27af05b4c203ecbe5034255 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:46:14 +0000
Subject: [PATCH 103/118] Changing vulkan file directory

---
 libavcodec/vulkan/ffv1_rct_search.comp | 139 -------------------------
 1 file changed, 139 deletions(-)
 delete mode 100644 libavcodec/vulkan/ffv1_rct_search.comp

diff --git a/libavcodec/vulkan/ffv1_rct_search.comp b/libavcodec/vulkan/ffv1_rct_search.comp
deleted file mode 100644
index 055bde46c4..0000000000
--- a/libavcodec/vulkan/ffv1_rct_search.comp
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * FFv1 codec
- *
- * Copyright (c) 2024 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-ivec3 load_components(ivec2 pos)
-{
-    ivec3 pix = ivec3(imageLoad(src[0], pos));
-    if (planar_rgb != 0) {
-        for (int i = 1; i < 3; i++)
-            pix[i] = int(imageLoad(src[i], pos)[0]);
-    }
-
-    return ivec3(pix[fmt_lut[0]], pix[fmt_lut[1]], pix[fmt_lut[2]]);
-}
-
-#define NUM_CHECKS 15
-const ivec2 rct_y_coeff[NUM_CHECKS] = {
-    ivec2(0, 0), //      4G
-
-    ivec2(0, 1), //      3G +  B
-    ivec2(1, 0), //  R + 3G
-    ivec2(1, 1), //  R + 2G + B
-
-    ivec2(0, 2), //      2G + 2B
-    ivec2(2, 0), // 2R + 2G
-    ivec2(2, 2), // 2R      + 2B
-
-    ivec2(0, 3), //      1G + 3B
-    ivec2(3, 0), // 3R + 1G
-
-    ivec2(0, 4), //           4B
-    ivec2(4, 0), // 4R
-
-    ivec2(1, 2), //  R +  G + 2B
-    ivec2(2, 1), // 2R +  G +  B
-
-    ivec2(3, 1), // 3R      +  B
-    ivec2(1, 3), //  R      + 3B
-};
-
-shared ivec3 pix_buf[gl_WorkGroupSize.x + 1][gl_WorkGroupSize.y + 1] = { };
-
-ivec3 transform_sample(ivec3 pix, ivec2 rct_coef)
-{
-    pix.b -= pix.g;
-    pix.r -= pix.g;
-    pix.g += (pix.r*rct_coef.x + pix.b*rct_coef.y) >> 2;
-    pix.b += rct_offset;
-    pix.r += rct_offset;
-    return pix;
-}
-
-uint get_dist(ivec3 cur)
-{
-    ivec3 LL = pix_buf[gl_LocalInvocationID.x + 0][gl_LocalInvocationID.y + 1];
-    ivec3 TL = pix_buf[gl_LocalInvocationID.x + 0][gl_LocalInvocationID.y + 0];
-    ivec3 TT = pix_buf[gl_LocalInvocationID.x + 1][gl_LocalInvocationID.y + 0];
-
-    ivec3 pred = ivec3(predict(LL.r, ivec2(TL.r, TT.r)),
-                       predict(LL.g, ivec2(TL.g, TT.g)),
-                       predict(LL.b, ivec2(TL.b, TT.b)));
-
-    uvec3 c = abs(pred - cur);
-    return mid_pred(c.r, c.g, c.b);
-}
-
-shared uint score_cols[gl_WorkGroupSize.y] = { };
-shared uint score_mode[16] = { };
-
-void process(ivec2 pos)
-{
-    ivec3 pix = load_components(pos);
-
-    for (int i = 0; i < NUM_CHECKS; i++) {
-        ivec3 tx_pix = transform_sample(pix, rct_y_coeff[i]);
-        pix_buf[gl_LocalInvocationID.x + 1][gl_LocalInvocationID.y + 1] = tx_pix;
-        memoryBarrierShared();
-
-        uint dist = get_dist(tx_pix);
-        atomicAdd(score_mode[i], dist);
-    }
-}
-
-void coeff_search(inout SliceContext sc)
-{
-    uvec2 img_size = imageSize(src[0]);
-    uint sxs = slice_coord(img_size.x, gl_WorkGroupID.x + 0,
-                           gl_NumWorkGroups.x, 0);
-    uint sxe = slice_coord(img_size.x, gl_WorkGroupID.x + 1,
-                           gl_NumWorkGroups.x, 0);
-    uint sys = slice_coord(img_size.y, gl_WorkGroupID.y + 0,
-                           gl_NumWorkGroups.y, 0);
-    uint sye = slice_coord(img_size.y, gl_WorkGroupID.y + 1,
-                           gl_NumWorkGroups.y, 0);
-
-    for (uint y = sys + gl_LocalInvocationID.y; y < sye; y += gl_WorkGroupSize.y) {
-        for (uint x = sxs + gl_LocalInvocationID.x; x < sxe; x += gl_WorkGroupSize.x) {
-            process(ivec2(x, y));
-        }
-    }
-
-    if (gl_LocalInvocationID.x == 0 && gl_LocalInvocationID.y == 0) {
-        uint min_score = 0xFFFFFFFF;
-        uint min_idx = 3;
-        for (int i = 0; i < NUM_CHECKS; i++) {
-            if (score_mode[i] < min_score) {
-                min_score = score_mode[i];
-                min_idx = i;
-            }
-        }
-        sc.slice_rct_coef = rct_y_coeff[min_idx];
-    }
-}
-
-void main(void)
-{
-    if (force_pcm == 1)
-        return;
-    const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;
-    coeff_search(slice_ctx[slice_idx]);
-}
-- 
2.49.1


From 10545089bfaf3a97f270af1c337f0f5b1e08fc8a Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:46:29 +0000
Subject: [PATCH 104/118] Changing vulkan file directory

---
 libavcodec/vulkan/ffv1_reset.comp | 57 -------------------------------
 1 file changed, 57 deletions(-)
 delete mode 100644 libavcodec/vulkan/ffv1_reset.comp

diff --git a/libavcodec/vulkan/ffv1_reset.comp b/libavcodec/vulkan/ffv1_reset.comp
deleted file mode 100644
index cfb7dcc444..0000000000
--- a/libavcodec/vulkan/ffv1_reset.comp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * FFv1 codec
- *
- * Copyright (c) 2024 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-void main(void)
-{
-    const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;
-
-    if (key_frame == 0 &&
-        slice_ctx[slice_idx].slice_reset_contexts == false)
-        return;
-
-    const uint8_t qidx = slice_ctx[slice_idx].quant_table_idx[gl_WorkGroupID.z];
-    uint contexts = context_count[qidx];
-    uint64_t slice_state_off = uint64_t(slice_state) +
-                               slice_idx*plane_state_size*codec_planes;
-
-#ifdef GOLOMB
-    uint64_t start = slice_state_off +
-                     (gl_WorkGroupID.z*(plane_state_size/VLC_STATE_SIZE) + gl_LocalInvocationID.x)*VLC_STATE_SIZE;
-    for (uint x = gl_LocalInvocationID.x; x < contexts; x += gl_WorkGroupSize.x) {
-        VlcState sb = VlcState(start);
-        sb.drift     =  int16_t(0);
-        sb.error_sum = uint16_t(4);
-        sb.bias      =   int8_t(0);
-        sb.count     =  uint8_t(1);
-        start += gl_WorkGroupSize.x*VLC_STATE_SIZE;
-    }
-#else
-    uint64_t start = slice_state_off +
-                     gl_WorkGroupID.z*plane_state_size +
-                     (gl_LocalInvocationID.x << 2 /* dwords */); /* Bytes */
-    uint count_total = contexts*(CONTEXT_SIZE /* bytes */ >> 2 /* dwords */);
-    for (uint x = gl_LocalInvocationID.x; x < count_total; x += gl_WorkGroupSize.x) {
-        u32buf(start).v = 0x80808080;
-        start += gl_WorkGroupSize.x*(CONTEXT_SIZE >> 3 /* 1/8th of context */);
-    }
-#endif
-}
-- 
2.49.1


From 9ad230315c5911e06966ecae75170a126489fc5b Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:46:39 +0000
Subject: [PATCH 105/118] Changing vulkan file directory

---
 libavcodec/vulkan/ffv1_vlc.comp | 159 --------------------------------
 1 file changed, 159 deletions(-)
 delete mode 100644 libavcodec/vulkan/ffv1_vlc.comp

diff --git a/libavcodec/vulkan/ffv1_vlc.comp b/libavcodec/vulkan/ffv1_vlc.comp
deleted file mode 100644
index 32a6ca9f37..0000000000
--- a/libavcodec/vulkan/ffv1_vlc.comp
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * FFv1 codec
- *
- * Copyright (c) 2024 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#define VLC_STATE_SIZE 8
-layout(buffer_reference, buffer_reference_align = VLC_STATE_SIZE) buffer VlcState {
-    uint32_t error_sum;
-    int16_t  drift;
-    int8_t   bias;
-    uint8_t  count;
-};
-
-void update_vlc_state(inout VlcState state, const int v)
-{
-    int drift = state.drift;
-    int count = state.count;
-    int bias = state.bias;
-    state.error_sum += uint16_t(abs(v));
-    drift           += v;
-
-    if (count == 128) { // FIXME: variable
-        count           >>= 1;
-        drift           >>= 1;
-        state.error_sum >>= 1;
-    }
-    count++;
-
-    if (drift <= -count) {
-        bias = max(bias - 1, -128);
-        drift = max(drift + count, -count + 1);
-    } else if (drift > 0) {
-        bias = min(bias + 1, 127);
-        drift = min(drift - count, 0);
-    }
-
-    state.bias = int8_t(bias);
-    state.drift = int16_t(drift);
-    state.count = uint8_t(count);
-}
-
-struct Symbol {
-    uint32_t bits;
-    uint32_t val;
-};
-
-Symbol set_ur_golomb(int i, int k, int limit, int esc_len)
-{
-    int e;
-    Symbol sym;
-
-#ifdef DEBUG
-    if (i < 0)
-        debugPrintfEXT("Error: i is zero!");
-#endif
-
-    e = i >> k;
-    if (e < limit) {
-        sym.bits = e + k + 1;
-        sym.val = (1 << k) + zero_extend(i, k);
-    } else {
-        sym.bits = limit + esc_len;
-        sym.val = i - limit + 1;
-    }
-
-    return sym;
-}
-
-/**
- * write signed golomb rice code (ffv1).
- */
-Symbol set_sr_golomb(int i, int k, int limit, int esc_len)
-{
-    int v;
-
-    v  = -2 * i - 1;
-    v ^= (v >> 31);
-
-    return set_ur_golomb(v, k, limit, esc_len);
-}
-
-Symbol get_vlc_symbol(inout VlcState state, int v, int bits)
-{
-    int i, k, code;
-    Symbol sym;
-    v = fold(v - int(state.bias), bits);
-
-    i = state.count;
-    k = 0;
-    while (i < state.error_sum) { // FIXME: optimize
-        k++;
-        i += i;
-    }
-
-#ifdef DEBUG
-    if (k > 16)
-        debugPrintfEXT("Error: k > 16!");
-#endif
-
-    code = v ^ ((2 * state.drift + state.count) >> 31);
-
-    update_vlc_state(state, v);
-
-    return set_sr_golomb(code, k, 12, bits);
-}
-
-uint get_ur_golomb(inout GetBitContext gb, int k, int limit, int esc_len)
-{
-    for (uint i = 0; i < 12; i++)
-        if (get_bit(gb))
-            return get_bits(gb, k) + (i << k);
-
-    return get_bits(gb, esc_len) + 11;
-}
-
-int get_sr_golomb(inout GetBitContext gb, int k, int limit, int esc_len)
-{
-    int v = int(get_ur_golomb(gb, k, limit, esc_len));
-    return (v >> 1) ^ -(v & 1);
-}
-
-int read_vlc_symbol(inout GetBitContext gb, inout VlcState state, int bits)
-{
-    int k, i, v, ret;
-
-    i = state.count;
-    k = 0;
-    while (i < state.error_sum) { // FIXME: optimize
-        k++;
-        i += i;
-    }
-
-    v = get_sr_golomb(gb, k, 12, bits);
-
-    v ^= ((2 * state.drift + state.count) >> 31);
-
-    ret = fold(v + state.bias, bits);
-
-    update_vlc_state(state, v);
-
-    return ret;
-}
-- 
2.49.1


From 8c5ff2dfea361bda7859ac22a0c39b109cf29e64 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:46:57 +0000
Subject: [PATCH 106/118] Changing vulkan file directory

---
 libavcodec/vulkan/prores_raw.comp | 347 ------------------------------
 1 file changed, 347 deletions(-)
 delete mode 100644 libavcodec/vulkan/prores_raw.comp

diff --git a/libavcodec/vulkan/prores_raw.comp b/libavcodec/vulkan/prores_raw.comp
deleted file mode 100644
index 89eece3c7e..0000000000
--- a/libavcodec/vulkan/prores_raw.comp
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * ProRes RAW decoder
- *
- * Copyright (c) 2025 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#define I16(x) (int16_t(x))
-
-#define COMP_ID (gl_LocalInvocationID.z)
-#define BLOCK_ID (gl_LocalInvocationID.y)
-#define ROW_ID (gl_LocalInvocationID.x)
-
-GetBitContext gb;
-shared float btemp[gl_WorkGroupSize.z][16][64] = { };
-shared float block[gl_WorkGroupSize.z][16][64];
-
-void idct8_horiz(const uint row_id)
-{
-    float t0, t1, t2, t3, t4, t5, t6, t7, u8;
-    float u0, u1, u2, u3, u4, u5, u6, u7;
-
-    /* Input */
-    t0 = block[COMP_ID][BLOCK_ID][8*row_id + 0];
-    u4 = block[COMP_ID][BLOCK_ID][8*row_id + 1];
-    t2 = block[COMP_ID][BLOCK_ID][8*row_id + 2];
-    u6 = block[COMP_ID][BLOCK_ID][8*row_id + 3];
-    t1 = block[COMP_ID][BLOCK_ID][8*row_id + 4];
-    u5 = block[COMP_ID][BLOCK_ID][8*row_id + 5];
-    t3 = block[COMP_ID][BLOCK_ID][8*row_id + 6];
-    u7 = block[COMP_ID][BLOCK_ID][8*row_id + 7];
-
-    /* Embedded scaled inverse 4-point Type-II DCT */
-    u0 = t0 + t1;
-    u1 = t0 - t1;
-    u3 = t2 + t3;
-    u2 = (t2 - t3)*(1.4142135623730950488016887242097f) - u3;
-    t0 = u0 + u3;
-    t3 = u0 - u3;
-    t1 = u1 + u2;
-    t2 = u1 - u2;
-
-    /* Embedded scaled inverse 4-point Type-IV DST */
-    t5 = u5 + u6;
-    t6 = u5 - u6;
-    t7 = u4 + u7;
-    t4 = u4 - u7;
-    u7 = t7 + t5;
-    u5 = (t7 - t5)*(1.4142135623730950488016887242097f);
-    u8 = (t4 + t6)*(1.8477590650225735122563663787936f);
-    u4 = u8 - t4*(1.0823922002923939687994464107328f);
-    u6 = u8 - t6*(2.6131259297527530557132863468544f);
-    t7 = u7;
-    t6 = t7 - u6;
-    t5 = t6 + u5;
-    t4 = t5 - u4;
-
-    /* Butterflies */
-    u0 = t0 + t7;
-    u7 = t0 - t7;
-    u6 = t1 + t6;
-    u1 = t1 - t6;
-    u2 = t2 + t5;
-    u5 = t2 - t5;
-    u4 = t3 + t4;
-    u3 = t3 - t4;
-
-    /* Output */
-    btemp[COMP_ID][BLOCK_ID][0*8 + row_id] = u0;
-    btemp[COMP_ID][BLOCK_ID][1*8 + row_id] = u1;
-    btemp[COMP_ID][BLOCK_ID][2*8 + row_id] = u2;
-    btemp[COMP_ID][BLOCK_ID][3*8 + row_id] = u3;
-    btemp[COMP_ID][BLOCK_ID][4*8 + row_id] = u4;
-    btemp[COMP_ID][BLOCK_ID][5*8 + row_id] = u5;
-    btemp[COMP_ID][BLOCK_ID][6*8 + row_id] = u6;
-    btemp[COMP_ID][BLOCK_ID][7*8 + row_id] = u7;
-}
-
-void idct8_vert(const uint row_id)
-{
-    float t0, t1, t2, t3, t4, t5, t6, t7, u8;
-    float u0, u1, u2, u3, u4, u5, u6, u7;
-
-    /* Input */
-    t0 = btemp[COMP_ID][BLOCK_ID][8*row_id + 0] + 0.5f; // NOTE
-    u4 = btemp[COMP_ID][BLOCK_ID][8*row_id + 1];
-    t2 = btemp[COMP_ID][BLOCK_ID][8*row_id + 2];
-    u6 = btemp[COMP_ID][BLOCK_ID][8*row_id + 3];
-    t1 = btemp[COMP_ID][BLOCK_ID][8*row_id + 4];
-    u5 = btemp[COMP_ID][BLOCK_ID][8*row_id + 5];
-    t3 = btemp[COMP_ID][BLOCK_ID][8*row_id + 6];
-    u7 = btemp[COMP_ID][BLOCK_ID][8*row_id + 7];
-
-    /* Embedded scaled inverse 4-point Type-II DCT */
-    u0 = t0 + t1;
-    u1 = t0 - t1;
-    u3 = t2 + t3;
-    u2 = (t2 - t3)*(1.4142135623730950488016887242097f) - u3;
-    t0 = u0 + u3;
-    t3 = u0 - u3;
-    t1 = u1 + u2;
-    t2 = u1 - u2;
-
-    /* Embedded scaled inverse 4-point Type-IV DST */
-    t5 = u5 + u6;
-    t6 = u5 - u6;
-    t7 = u4 + u7;
-    t4 = u4 - u7;
-    u7 = t7 + t5;
-    u5 = (t7 - t5)*(1.4142135623730950488016887242097f);
-    u8 = (t4 + t6)*(1.8477590650225735122563663787936f);
-    u4 = u8 - t4*(1.0823922002923939687994464107328f);
-    u6 = u8 - t6*(2.6131259297527530557132863468544f);
-    t7 = u7;
-    t6 = t7 - u6;
-    t5 = t6 + u5;
-    t4 = t5 - u4;
-
-    /* Butterflies */
-    u0 = t0 + t7;
-    u7 = t0 - t7;
-    u6 = t1 + t6;
-    u1 = t1 - t6;
-    u2 = t2 + t5;
-    u5 = t2 - t5;
-    u4 = t3 + t4;
-    u3 = t3 - t4;
-
-    /* Output */
-    block[COMP_ID][BLOCK_ID][0*8 + row_id] = u0;
-    block[COMP_ID][BLOCK_ID][1*8 + row_id] = u1;
-    block[COMP_ID][BLOCK_ID][2*8 + row_id] = u2;
-    block[COMP_ID][BLOCK_ID][3*8 + row_id] = u3;
-    block[COMP_ID][BLOCK_ID][4*8 + row_id] = u4;
-    block[COMP_ID][BLOCK_ID][5*8 + row_id] = u5;
-    block[COMP_ID][BLOCK_ID][6*8 + row_id] = u6;
-    block[COMP_ID][BLOCK_ID][7*8 + row_id] = u7;
-}
-
-int16_t get_value(int16_t codebook)
-{
-    const int16_t switch_bits = codebook >> 8;
-    const int16_t rice_order  = codebook & I16(0xf);
-    const int16_t exp_order   = (codebook >> 4) & I16(0xf);
-
-    uint32_t b = show_bits(gb, 32);
-    if (expectEXT(b == 0, false))
-        return I16(0);
-    int16_t q = I16(31) - I16(findMSB(b));
-
-    if ((b & 0x80000000) != 0) {
-        skip_bits(gb, 1 + rice_order);
-        return I16((b & 0x7FFFFFFF) >> (31 - rice_order));
-    }
-
-    if (q <= switch_bits) {
-        skip_bits(gb, q + rice_order + 1);
-        return I16((q << rice_order) +
-                   (((b << (q + 1)) >> 1) >> (31 - rice_order)));
-    }
-
-    int16_t bits = exp_order + (q << 1) - switch_bits;
-    skip_bits(gb, bits);
-    return I16((b >> (32 - bits)) +
-               ((switch_bits + 1) << rice_order) -
-               (1 << exp_order));
-}
-
-#define TODCCODEBOOK(x) ((x + 1) >> 1)
-
-void read_dc_vals(const uint nb_blocks)
-{
-    int16_t dc, dc_add;
-    int16_t prev_dc = I16(0), sign = I16(0);
-
-    /* Special handling for first block */
-    dc = get_value(I16(700));
-    prev_dc = (dc >> 1) ^ -(dc & I16(1));
-    btemp[COMP_ID][0][0] = prev_dc;
-
-    for (uint n = 1; n < nb_blocks; n++) {
-        if (expectEXT(left_bits(gb) <= 0, false))
-            break;
-
-        uint8_t dc_codebook;
-        if ((n & 15) == 1)
-            dc_codebook = uint8_t(100);
-        else
-            dc_codebook = dc_cb[min(TODCCODEBOOK(dc), 13 - 1)];
-
-        dc = get_value(dc_codebook);
-
-        sign = sign ^ dc & int16_t(1);
-        dc_add = (-sign ^ I16(TODCCODEBOOK(dc))) + sign;
-        sign = I16(dc_add < 0);
-        prev_dc += dc_add;
-
-        btemp[COMP_ID][n][0] = prev_dc;
-    }
-}
-
-void read_ac_vals(const uint nb_blocks)
-{
-    const uint nb_codes = nb_blocks << 6;
-    const uint log2_nb_blocks = findMSB(nb_blocks);
-    const uint block_mask = (1 << log2_nb_blocks) - 1;
-
-    int16_t ac, rn, ln;
-    int16_t ac_codebook = I16(49);
-    int16_t rn_codebook = I16( 0);
-    int16_t ln_codebook = I16(66);
-    int16_t sign;
-    int16_t val;
-
-    for (uint n = nb_blocks; n <= nb_codes;) {
-        if (expectEXT(left_bits(gb) <= 0, false))
-            break;
-
-        ln = get_value(ln_codebook);
-        for (uint i = 0; i < ln; i++) {
-            if (expectEXT(left_bits(gb) <= 0, false))
-                break;
-
-            if (expectEXT(n >= nb_codes, false))
-                break;
-
-            ac = get_value(ac_codebook);
-            ac_codebook = ac_cb[min(ac, 95 - 1)];
-            sign = -int16_t(get_bit(gb));
-
-            val = ((ac + I16(1)) ^ sign) - sign;
-            btemp[COMP_ID][n & block_mask][n >> log2_nb_blocks] = val;
-
-            n++;
-        }
-
-        if (expectEXT(n >= nb_codes, false))
-            break;
-
-        rn = get_value(rn_codebook);
-        rn_codebook = rn_cb[min(rn, 28 - 1)];
-
-        n += rn + 1;
-        if (expectEXT(n >= nb_codes, false))
-            break;
-
-        if (expectEXT(left_bits(gb) <= 0, false))
-            break;
-
-        ac = get_value(ac_codebook);
-        sign = -int16_t(get_bit(gb));
-
-        val = ((ac + I16(1)) ^ sign) - sign;
-        btemp[COMP_ID][n & block_mask][n >> log2_nb_blocks] = val;
-
-        ac_codebook = ac_cb[min(ac, 95 - 1)];
-        ln_codebook = ln_cb[min(ac, 15 - 1)];
-
-        n++;
-    }
-}
-
-void main(void)
-{
-    const uint tile_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;
-    TileData td = tile_data[tile_idx];
-
-    if (expectEXT(td.pos.x >= frame_size.x, false))
-        return;
-
-    uint64_t pkt_offset = uint64_t(pkt_data) + td.offset;
-    u8vec2buf hdr_data = u8vec2buf(pkt_offset);
-    float qscale = float(pack16(hdr_data[0].v.yx)) / 2.0f;
-
-    ivec4 size = ivec4(td.size,
-                       pack16(hdr_data[2].v.yx),
-                       pack16(hdr_data[1].v.yx),
-                       pack16(hdr_data[3].v.yx));
-    size[0] = size[0] - size[1] - size[2] - size[3] - 8;
-    if (expectEXT(size[0] < 0, false))
-        return;
-
-    const ivec2 offs = td.pos + ivec2(COMP_ID & 1, COMP_ID >> 1);
-    const uint w = min(tile_size.x, frame_size.x - td.pos.x) / 2;
-    const uint nb_blocks = w / 8;
-
-    const ivec4 comp_offset = ivec4(size[2] + size[1] + size[3],
-                                    size[2],
-                                    0,
-                                    size[2] + size[1]);
-
-    if (BLOCK_ID == 0 && ROW_ID == 0) {
-        init_get_bits(gb, u8buf(pkt_offset + 8 + comp_offset[COMP_ID]),
-                      size[COMP_ID]);
-        read_dc_vals(nb_blocks);
-        read_ac_vals(nb_blocks);
-    }
-
-    barrier();
-
-    [[unroll]]
-    for (uint i = gl_LocalInvocationID.x; i < 64; i += gl_WorkGroupSize.x)
-        block[COMP_ID][BLOCK_ID][i] = (btemp[COMP_ID][BLOCK_ID][scan[i]] / 16384.0) *
-                                      (float(qmat[i]) / 295.0) *
-                                      idct_8x8_scales[i] * qscale;
-
-    barrier();
-
-#ifdef PARALLEL_ROWS
-    idct8_horiz(ROW_ID);
-
-    barrier();
-
-    idct8_vert(ROW_ID);
-#else
-    for (uint j = 0; j < 8; j++)
-        idct8_horiz(j);
-
-    barrier();
-
-    for (uint j = 0; j < 8; j++)
-        idct8_vert(j);
-#endif
-
-    barrier();
-
-    [[unroll]]
-    for (uint i = gl_LocalInvocationID.x; i < 64; i += gl_WorkGroupSize.x)
-         imageStore(dst,
-                    offs + 2*ivec2(BLOCK_ID*8 + (i & 7), i >> 3),
-                    vec4(block[COMP_ID][BLOCK_ID][i]));
-}
-- 
2.49.1


From 1968ad0cfccd3c08ee9ef591eb60a04e2ef8e503 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 13:47:07 +0000
Subject: [PATCH 107/118] Changing vulkan file directory

---
 libavcodec/vulkan/rangecoder.comp | 241 ------------------------------
 1 file changed, 241 deletions(-)
 delete mode 100644 libavcodec/vulkan/rangecoder.comp

diff --git a/libavcodec/vulkan/rangecoder.comp b/libavcodec/vulkan/rangecoder.comp
deleted file mode 100644
index b6b6c0490f..0000000000
--- a/libavcodec/vulkan/rangecoder.comp
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * FFv1 codec
- *
- * Copyright (c) 2024 Lynne <dev@lynne.ee>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-struct RangeCoder {
-    uint64_t bytestream_start;
-    uint64_t bytestream;
-    uint64_t bytestream_end;
-
-    int low;
-    int range;
-    uint16_t outstanding_count;
-    uint8_t outstanding_byte;
-};
-
-#ifdef FULL_RENORM
-/* Full renorm version that can handle outstanding_byte == 0xFF */
-void renorm_encoder(inout RangeCoder c)
-{
-    int bs_cnt = 0;
-    u8buf bytestream = u8buf(c.bytestream);
-
-    if (c.outstanding_byte == 0xFF) {
-        c.outstanding_byte = uint8_t(c.low >> 8);
-    } else if (c.low <= 0xFF00) {
-        bytestream[bs_cnt++].v = c.outstanding_byte;
-        uint16_t cnt = c.outstanding_count;
-        for (; cnt > 0; cnt--)
-            bytestream[bs_cnt++].v = uint8_t(0xFF);
-        c.outstanding_count = uint16_t(0);
-        c.outstanding_byte = uint8_t(c.low >> 8);
-    } else if (c.low >= 0x10000) {
-        bytestream[bs_cnt++].v = c.outstanding_byte + uint8_t(1);
-        uint16_t cnt = c.outstanding_count;
-        for (; cnt > 0; cnt--)
-            bytestream[bs_cnt++].v = uint8_t(0x00);
-        c.outstanding_count = uint16_t(0);
-        c.outstanding_byte = uint8_t(bitfieldExtract(c.low, 8, 8));
-    } else {
-        c.outstanding_count++;
-    }
-
-    c.bytestream += bs_cnt;
-    c.range <<= 8;
-    c.low = bitfieldInsert(0, c.low, 8, 8);
-}
-
-#else
-
-/* Cannot deal with outstanding_byte == -1 in the name of speed */
-void renorm_encoder(inout RangeCoder c)
-{
-    uint16_t oc = c.outstanding_count + uint16_t(1);
-    int low = c.low;
-
-    c.range <<= 8;
-    c.low = bitfieldInsert(0, low, 8, 8);
-
-    if (low > 0xFF00 && low < 0x10000) {
-        c.outstanding_count = oc;
-        return;
-    }
-
-    u8buf bs = u8buf(c.bytestream);
-    uint8_t outstanding_byte = c.outstanding_byte;
-
-    c.bytestream        = uint64_t(bs) + oc;
-    c.outstanding_count = uint16_t(0);
-    c.outstanding_byte  = uint8_t(low >> 8);
-
-    uint8_t obs = uint8_t(low > 0xFF00);
-    uint8_t fill = obs - uint8_t(1); /* unsigned underflow */
-
-    bs[0].v = outstanding_byte + obs;
-    for (int i = 1; i < oc; i++)
-        bs[i].v = fill;
-}
-#endif
-
-void put_rac_internal(inout RangeCoder c, const int range1, bool bit)
-{
-#ifdef DEBUG
-    if (range1 >= c.range)
-        debugPrintfEXT("Error: range1 >= c.range");
-    if (range1 <= 0)
-        debugPrintfEXT("Error: range1 <= 0");
-#endif
-
-    int ranged = c.range - range1;
-    c.low += bit ? ranged : 0;
-    c.range = bit ? range1 : ranged;
-
-    if (expectEXT(c.range < 0x100, false))
-        renorm_encoder(c);
-}
-
-void put_rac_direct(inout RangeCoder c, inout uint8_t state, bool bit)
-{
-    put_rac_internal(c, (c.range * state) >> 8, bit);
-    state = zero_one_state[(uint(bit) << 8) + state];
-}
-
-void put_rac(inout RangeCoder c, uint64_t state, bool bit)
-{
-    put_rac_direct(c, u8buf(state).v, bit);
-}
-
-/* Equiprobable bit */
-void put_rac_equi(inout RangeCoder c, bool bit)
-{
-    put_rac_internal(c, c.range >> 1, bit);
-}
-
-void put_rac_terminate(inout RangeCoder c)
-{
-    int range1 = (c.range * 129) >> 8;
-
-#ifdef DEBUG
-    if (range1 >= c.range)
-        debugPrintfEXT("Error: range1 >= c.range");
-    if (range1 <= 0)
-        debugPrintfEXT("Error: range1 <= 0");
-#endif
-
-    c.range -= range1;
-    if (expectEXT(c.range < 0x100, false))
-        renorm_encoder(c);
-}
-
-/* Return the number of bytes written. */
-uint32_t rac_terminate(inout RangeCoder c)
-{
-    put_rac_terminate(c);
-    c.range = uint16_t(0xFF);
-    c.low  += 0xFF;
-    renorm_encoder(c);
-    c.range = uint16_t(0xFF);
-    renorm_encoder(c);
-
-#ifdef DEBUG
-    if (c.low != 0)
-        debugPrintfEXT("Error: c.low != 0");
-    if (c.range < 0x100)
-        debugPrintfEXT("Error: range < 0x100");
-#endif
-
-    return uint32_t(uint64_t(c.bytestream) - uint64_t(c.bytestream_start));
-}
-
-void rac_init(out RangeCoder r, u8buf data, uint buf_size)
-{
-    r.bytestream_start = uint64_t(data);
-    r.bytestream = uint64_t(data);
-    r.bytestream_end = uint64_t(data) + buf_size;
-    r.low = 0;
-    r.range = 0xFF00;
-    r.outstanding_count = uint16_t(0);
-    r.outstanding_byte = uint8_t(0xFF);
-}
-
-/* Decoder */
-uint overread = 0;
-bool corrupt = false;
-
-void rac_init_dec(out RangeCoder r, u8buf data, uint buf_size)
-{
-    overread = 0;
-    corrupt = false;
-
-    /* Skip priming bytes */
-    rac_init(r, OFFBUF(u8buf, data, 2), buf_size - 2);
-
-    u8vec2 prime = u8vec2buf(data).v;
-    /* Switch endianness of the priming bytes */
-    r.low = pack16(prime.yx);
-
-    if (r.low >= 0xFF00) {
-        r.low = 0xFF00;
-        r.bytestream_end = uint64_t(data) + 2;
-    }
-}
-
-void refill(inout RangeCoder c)
-{
-    c.range <<= 8;
-    c.low   <<= 8;
-    if (expectEXT(c.bytestream < c.bytestream_end, false)) {
-        c.low |= u8buf(c.bytestream).v;
-        c.bytestream++;
-    } else {
-        overread++;
-    }
-}
-
-bool get_rac_internal(inout RangeCoder c, const int range1)
-{
-    int ranged = c.range - range1;
-    bool bit = c.low >= ranged;
-    c.low -= bit ? ranged : 0;
-    c.range = (bit ? 0 : ranged) + (bit ? range1 : 0);
-
-    if (expectEXT(c.range < 0x100, false))
-        refill(c);
-
-    return bit;
-}
-
-bool get_rac_direct(inout RangeCoder c, inout uint8_t state)
-{
-    bool bit = get_rac_internal(c, c.range * state >> 8);
-    state = zero_one_state[state + (bit ? 256 : 0)];
-    return bit;
-}
-
-bool get_rac(inout RangeCoder c, uint64_t state)
-{
-    return get_rac_direct(c, u8buf(state).v);
-}
-
-bool get_rac_equi(inout RangeCoder c)
-{
-    return get_rac_internal(c, c.range >> 1);
-}
-- 
2.49.1


From 31b2af9037bc07922a9fa8f4b122496adb678861 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 14:07:07 +0000
Subject: [PATCH 108/118] Changing vulkan file directory

---
 libavfilter/vulkan_glslang.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavfilter/vulkan_glslang.c b/libavfilter/vulkan_glslang.c
index 9aa41567a3..31e7414e90 100644
--- a/libavfilter/vulkan_glslang.c
+++ b/libavfilter/vulkan_glslang.c
@@ -16,4 +16,4 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "libavutil/vulkan_glslang.c"
+#include "libavutil/vulkan/vulkan_glslang.c"
-- 
2.49.1


From 7301c8ecbb489974974f195b33f4f5dd7b28ea97 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 14:07:55 +0000
Subject: [PATCH 109/118] Changing vulkan file directory

---
 libavfilter/vulkan_shaderc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavfilter/vulkan_shaderc.c b/libavfilter/vulkan_shaderc.c
index 9f60bf4dfd..6b80cdb111 100644
--- a/libavfilter/vulkan_shaderc.c
+++ b/libavfilter/vulkan_shaderc.c
@@ -16,4 +16,4 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "libavutil/vulkan_shaderc.c"
+#include "libavutil/vulkan/vulkan_shaderc.c"
-- 
2.49.1


From a8adcc58e28fa81d1ae3b8f5fecf73516b524af6 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 14:08:43 +0000
Subject: [PATCH 110/118] Changing vulkan file directory

---
 libavfilter/vulkan.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavfilter/vulkan.c b/libavfilter/vulkan.c
index fc8a1fa47b..f13a59e6d3 100644
--- a/libavfilter/vulkan.c
+++ b/libavfilter/vulkan.c
@@ -16,4 +16,4 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "libavutil/vulkan.c"
+#include "libavutil/vulkan/vulkan.c"
-- 
2.49.1


From d7e2e987998eabd0f5b37f8e6d48acbd722cfce3 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 14:09:23 +0000
Subject: [PATCH 111/118] Changing vulkan file directory

---
 libavcodec/vulkan.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/vulkan.c b/libavcodec/vulkan.c
index fc8a1fa47b..f13a59e6d3 100644
--- a/libavcodec/vulkan.c
+++ b/libavcodec/vulkan.c
@@ -16,4 +16,4 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "libavutil/vulkan.c"
+#include "libavutil/vulkan/vulkan.c"
-- 
2.49.1


From ddd6d34d3f8d3cf6e7ba158c9108bb79f9cbb0dd Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 14:09:55 +0000
Subject: [PATCH 112/118] Changing vulkan file directory

---
 libavcodec/vulkan_glslang.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/vulkan_glslang.c b/libavcodec/vulkan_glslang.c
index 9aa41567a3..31e7414e90 100644
--- a/libavcodec/vulkan_glslang.c
+++ b/libavcodec/vulkan_glslang.c
@@ -16,4 +16,4 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "libavutil/vulkan_glslang.c"
+#include "libavutil/vulkan/vulkan_glslang.c"
-- 
2.49.1


From 11c667d644a273439210626809821532f1867def Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 14:10:40 +0000
Subject: [PATCH 113/118] Changing vulkan file directory

---
 libavcodec/vulkan_shaderc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/vulkan_shaderc.c b/libavcodec/vulkan_shaderc.c
index 9f60bf4dfd..6b80cdb111 100644
--- a/libavcodec/vulkan_shaderc.c
+++ b/libavcodec/vulkan_shaderc.c
@@ -16,4 +16,4 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "libavutil/vulkan_shaderc.c"
+#include "libavutil/vulkan/vulkan_shaderc.c"
-- 
2.49.1


From c19c4c852935bcc1a455b34368d0d0c21e61e5e4 Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 14:16:36 +0000
Subject: [PATCH 114/118] Changing vulkan file directory

---
 libavcodec/vulkan/Makefile | 14 +++-----------
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/libavcodec/vulkan/Makefile b/libavcodec/vulkan/Makefile
index d8e1471fa6..bf6c7c81f3 100644
--- a/libavcodec/vulkan/Makefile
+++ b/libavcodec/vulkan/Makefile
@@ -3,19 +3,11 @@ GEN_CLEANSUFFIXES = *.o *.c *.d
 clean::
 	$(RM) $(GEN_CLEANSUFFIXES:%=libavcodec/vulkan/%)
 
-OBJS-$(CONFIG_FFV1_VULKAN_ENCODER)  +=  vulkan/common.o \
-					vulkan/rangecoder.o vulkan/ffv1_vlc.o \
-					vulkan/ffv1_common.o vulkan/ffv1_reset.o \
-					vulkan/ffv1_enc_rct.o vulkan/ffv1_enc_setup.o \
-					vulkan/ffv1_rct_search.o vulkan/ffv1_enc.o
+OBJS-$(CONFIG_FFV1_VULKAN_ENCODER)  +=  vulkan/vulkan_source.o
 
-OBJS-$(CONFIG_FFV1_VULKAN_HWACCEL)  +=  vulkan/common.o \
-					vulkan/rangecoder.o vulkan/ffv1_vlc.o \
-					vulkan/ffv1_common.o vulkan/ffv1_reset.o \
-					vulkan/ffv1_dec_setup.o vulkan/ffv1_dec.o
+OBJS-$(CONFIG_FFV1_VULKAN_HWACCEL)  +=  vulkan/vulkan_source.o
 
-OBJS-$(CONFIG_PRORES_RAW_VULKAN_HWACCEL) += vulkan/common.o \
-                                            vulkan/prores_raw.o
+OBJS-$(CONFIG_PRORES_RAW_VULKAN_HWACCEL) += vulkan/vulkan_source.o
 
 VULKAN = $(subst $(SRC_PATH)/,,$(wildcard $(SRC_PATH)/libavcodec/vulkan/*.comp))
 .SECONDARY: $(VULKAN:.comp=.c)
-- 
2.49.1


From 12548b1e6166631ddaf16c55fc1febaa7f8cce5f Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 14:20:17 +0000
Subject: [PATCH 115/118] Changing vulkan file directory

---
 libavcodec/Makefile | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 3d036de4b6..5463dc8b1d 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -276,7 +276,7 @@ OBJS-$(CONFIG_AV1_MEDIACODEC_ENCODER)  += mediacodecenc.o
 OBJS-$(CONFIG_AV1_NVENC_ENCODER)       += nvenc_av1.o nvenc.o
 OBJS-$(CONFIG_AV1_QSV_ENCODER)         += qsvenc_av1.o
 OBJS-$(CONFIG_AV1_VAAPI_ENCODER)       += vaapi_encode_av1.o av1_levels.o
-OBJS-$(CONFIG_AV1_VULKAN_ENCODER)      += vulkan_encode.o vulkan_encode_av1.o \
+OBJS-$(CONFIG_AV1_VULKAN_ENCODER)      += vulkan/vulkan_encode.o vulkan/vulkan_encode_av1.o \
                                           hw_base_encode.o av1_levels.o
 OBJS-$(CONFIG_AVRN_DECODER)            += avrndec.o
 OBJS-$(CONFIG_AVRP_DECODER)            += r210dec.o
@@ -378,7 +378,7 @@ OBJS-$(CONFIG_EXR_ENCODER)             += exrenc.o
 OBJS-$(CONFIG_FASTAUDIO_DECODER)       += fastaudio.o
 OBJS-$(CONFIG_FFV1_DECODER)            += ffv1dec.o ffv1_parse.o ffv1.o
 OBJS-$(CONFIG_FFV1_ENCODER)            += ffv1enc.o ffv1_parse.o ffv1.o
-OBJS-$(CONFIG_FFV1_VULKAN_ENCODER)     += ffv1enc.o ffv1.o ffv1_vulkan.o ffv1enc_vulkan.o
+OBJS-$(CONFIG_FFV1_VULKAN_ENCODER)     += ffv1enc.o ffv1.o vulkan/ffv1_vulkan.o vulkan/ffv1enc_vulkan.o
 OBJS-$(CONFIG_FFWAVESYNTH_DECODER)     += ffwavesynth.o
 OBJS-$(CONFIG_FIC_DECODER)             += fic.o
 OBJS-$(CONFIG_FITS_DECODER)            += fitsdec.o fits.o
@@ -442,7 +442,7 @@ OBJS-$(CONFIG_H264_QSV_ENCODER)        += qsvenc_h264.o
 OBJS-$(CONFIG_H264_RKMPP_DECODER)      += rkmppdec.o
 OBJS-$(CONFIG_H264_VAAPI_ENCODER)      += vaapi_encode_h264.o h264_levels.o \
                                           h2645data.o hw_base_encode_h264.o
-OBJS-$(CONFIG_H264_VULKAN_ENCODER)     += vulkan_encode.o vulkan_encode_h264.o \
+OBJS-$(CONFIG_H264_VULKAN_ENCODER)     += vulkan/vulkan_encode.o vulkan/vulkan_encode_h264.o \
                                           hw_base_encode.o hw_base_encode_h264.o \
                                           h264_levels.o h2645data.o
 OBJS-$(CONFIG_H264_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o
@@ -471,7 +471,7 @@ OBJS-$(CONFIG_HEVC_QSV_ENCODER)        += qsvenc_hevc.o hevc/ps_enc.o
 OBJS-$(CONFIG_HEVC_RKMPP_DECODER)      += rkmppdec.o
 OBJS-$(CONFIG_HEVC_VAAPI_ENCODER)      += vaapi_encode_h265.o h265_profile_level.o \
                                           h2645data.o hw_base_encode_h265.o
-OBJS-$(CONFIG_HEVC_VULKAN_ENCODER)     += vulkan_encode.o vulkan_encode_h265.o \
+OBJS-$(CONFIG_HEVC_VULKAN_ENCODER)     += vulkan/vulkan_encode.o vulkan/vulkan_encode_h265.o \
                                           hw_base_encode.o hw_base_encode_h265.o \
                                           h265_profile_level.o h2645data.o
 OBJS-$(CONFIG_HEVC_V4L2M2M_DECODER)    += v4l2_m2m_dec.o
@@ -1025,7 +1025,7 @@ OBJS-$(CONFIG_NVDEC)                      += nvdec.o
 OBJS-$(CONFIG_VAAPI)                      += vaapi_decode.o
 OBJS-$(CONFIG_VIDEOTOOLBOX)               += videotoolbox.o
 OBJS-$(CONFIG_VDPAU)                      += vdpau.o
-OBJS-$(CONFIG_VULKAN)                     += vulkan.o vulkan_video.o
+OBJS-$(CONFIG_VULKAN)                     += vulkan.o vulkan/vulkan_video.o
 
 OBJS-$(CONFIG_AV1_D3D11VA_HWACCEL)        += dxva2_av1.o
 OBJS-$(CONFIG_AV1_DXVA2_HWACCEL)          += dxva2_av1.o
@@ -1034,8 +1034,8 @@ OBJS-$(CONFIG_AV1_NVDEC_HWACCEL)          += nvdec_av1.o
 OBJS-$(CONFIG_AV1_VAAPI_HWACCEL)          += vaapi_av1.o
 OBJS-$(CONFIG_AV1_VDPAU_HWACCEL)          += vdpau_av1.o
 OBJS-$(CONFIG_AV1_VIDEOTOOLBOX_HWACCEL)   += videotoolbox_av1.o
-OBJS-$(CONFIG_AV1_VULKAN_HWACCEL)         += vulkan_decode.o vulkan_av1.o
-OBJS-$(CONFIG_FFV1_VULKAN_HWACCEL)        += vulkan_decode.o ffv1_vulkan.o vulkan_ffv1.o
+OBJS-$(CONFIG_AV1_VULKAN_HWACCEL)         += vulkan/vulkan_decode.o vulkan/vulkan_av1.o
+OBJS-$(CONFIG_FFV1_VULKAN_HWACCEL)        += vulkan/vulkan_decode.o vulkan/ffv1_vulkan.o vulkan/vulkan_ffv1.o
 OBJS-$(CONFIG_H263_VAAPI_HWACCEL)         += vaapi_mpeg4.o
 OBJS-$(CONFIG_H263_VIDEOTOOLBOX_HWACCEL)  += videotoolbox.o
 OBJS-$(CONFIG_H264_D3D11VA_HWACCEL)       += dxva2_h264.o
@@ -1046,7 +1046,7 @@ OBJS-$(CONFIG_H264_QSV_HWACCEL)           += qsvdec.o
 OBJS-$(CONFIG_H264_VAAPI_HWACCEL)         += vaapi_h264.o
 OBJS-$(CONFIG_H264_VDPAU_HWACCEL)         += vdpau_h264.o
 OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL)  += videotoolbox.o
-OBJS-$(CONFIG_H264_VULKAN_HWACCEL)        += vulkan_decode.o vulkan_h264.o
+OBJS-$(CONFIG_H264_VULKAN_HWACCEL)        += vulkan/vulkan_decode.o vulkan/vulkan_h264.o
 OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL)       += dxva2_hevc.o
 OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL)         += dxva2_hevc.o
 OBJS-$(CONFIG_HEVC_D3D12VA_HWACCEL)       += dxva2_hevc.o d3d12va_hevc.o
@@ -1054,7 +1054,7 @@ OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL)         += nvdec_hevc.o
 OBJS-$(CONFIG_HEVC_QSV_HWACCEL)           += qsvdec.o
 OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL)         += vaapi_hevc.o h265_profile_level.o
 OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL)         += vdpau_hevc.o h265_profile_level.o
-OBJS-$(CONFIG_HEVC_VULKAN_HWACCEL)        += vulkan_decode.o vulkan_hevc.o
+OBJS-$(CONFIG_HEVC_VULKAN_HWACCEL)        += vulkan/vulkan_decode.o vulkan/vulkan_hevc.o
 OBJS-$(CONFIG_MJPEG_NVDEC_HWACCEL)        += nvdec_mjpeg.o
 OBJS-$(CONFIG_MJPEG_VAAPI_HWACCEL)        += vaapi_mjpeg.o
 OBJS-$(CONFIG_MPEG1_NVDEC_HWACCEL)        += nvdec_mpeg12.o
@@ -1088,10 +1088,10 @@ OBJS-$(CONFIG_VP9_NVDEC_HWACCEL)          += nvdec_vp9.o
 OBJS-$(CONFIG_VP9_VAAPI_HWACCEL)          += vaapi_vp9.o
 OBJS-$(CONFIG_VP9_VDPAU_HWACCEL)          += vdpau_vp9.o
 OBJS-$(CONFIG_VP9_VIDEOTOOLBOX_HWACCEL)   += videotoolbox_vp9.o
-OBJS-$(CONFIG_VP9_VULKAN_HWACCEL)         += vulkan_decode.o vulkan_vp9.o
+OBJS-$(CONFIG_VP9_VULKAN_HWACCEL)         += vulkan/vulkan_decode.o vulkan/vulkan_vp9.o
 OBJS-$(CONFIG_VP8_QSV_HWACCEL)            += qsvdec.o
 OBJS-$(CONFIG_VVC_VAAPI_HWACCEL)          += vaapi_vvc.o
-OBJS-$(CONFIG_PRORES_RAW_VULKAN_HWACCEL)  += vulkan_decode.o vulkan_prores_raw.o
+OBJS-$(CONFIG_PRORES_RAW_VULKAN_HWACCEL)  += vulkan/vulkan_decode.o vulkan/vulkan_prores_raw.o
 
 # Objects duplicated from other libraries for shared builds
 SHLIBOBJS                              += log2_tab.o reverse.o
@@ -1334,8 +1334,8 @@ SKIPHEADERS-$(CONFIG_QSVENC)           += qsvenc.h
 SKIPHEADERS-$(CONFIG_VAAPI)            += vaapi_decode.h vaapi_hevc.h vaapi_encode.h
 SKIPHEADERS-$(CONFIG_VDPAU)            += vdpau.h vdpau_internal.h
 SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX)     += videotoolbox.h vt_internal.h
-SKIPHEADERS-$(CONFIG_VULKAN)           += ffv1_vulkan.h vulkan_video.h \
-                                          vulkan_encode.h vulkan_decode.h
+SKIPHEADERS-$(CONFIG_VULKAN)           += vulkan/ffv1_vulkan.h vulkan/vulkan_video.h \
+                                          vulkan/vulkan_encode.h vulkan/vulkan_decode.h
 SKIPHEADERS-$(CONFIG_V4L2_M2M)         += v4l2_buffers.h v4l2_context.h v4l2_m2m.h
 SKIPHEADERS-$(CONFIG_ZLIB)             += zlib_wrapper.h
 
-- 
2.49.1


From ac50d7bc58d1ef067ddd407fc52621306a609a2f Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 14:21:43 +0000
Subject: [PATCH 116/118] Changing vulkan file directory

---
 libavfilter/vulkan/Makefile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavfilter/vulkan/Makefile b/libavfilter/vulkan/Makefile
index c77aaf4f6b..6170982bda 100644
--- a/libavfilter/vulkan/Makefile
+++ b/libavfilter/vulkan/Makefile
@@ -3,8 +3,8 @@ GEN_CLEANSUFFIXES = *.o *.c *.d
 clean::
 	$(RM) $(GEN_CLEANSUFFIXES:%=libavfilter/vulkan/%)
 
-OBJS-$(CONFIG_BWDIF_VULKAN_FILTER) += vulkan/bwdif.o
-OBJS-$(CONFIG_SCALE_VULKAN_FILTER) += vulkan/debayer.o
+OBJS-$(CONFIG_BWDIF_VULKAN_FILTER) += vulkan/vulkan_source.o
+OBJS-$(CONFIG_SCALE_VULKAN_FILTER) += vulkan/vulkan_source.o
 
 VULKAN = $(subst $(SRC_PATH)/,,$(wildcard $(SRC_PATH)/libavfilter/vulkan/*.comp))
 .SECONDARY: $(VULKAN:.comp=.c)
-- 
2.49.1


From bfdd56ab328925bed2e7de0b1dd00ebf6f4c390a Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 14:27:32 +0000
Subject: [PATCH 117/118] Changing vulkan file directory

---
 libavfilter/Makefile | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 07fb4c3d6c..7d59fe9e56 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -202,7 +202,7 @@ OBJS-$(CONFIG_ATADENOISE_FILTER)             += vf_atadenoise.o
 OBJS-$(CONFIG_AVGBLUR_FILTER)                += vf_avgblur.o
 OBJS-$(CONFIG_AVGBLUR_OPENCL_FILTER)         += vf_avgblur_opencl.o opencl.o \
                                                 opencl/avgblur.o boxblur.o
-OBJS-$(CONFIG_AVGBLUR_VULKAN_FILTER)         += vf_avgblur_vulkan.o vulkan.o vulkan_filter.o
+OBJS-$(CONFIG_AVGBLUR_VULKAN_FILTER)         += vulkan/vf_avgblur_vulkan.o vulkan.o vulkan/vulkan_filter.o
 OBJS-$(CONFIG_BACKGROUNDKEY_FILTER)          += vf_backgroundkey.o
 OBJS-$(CONFIG_BBOX_FILTER)                   += bbox.o vf_bbox.o
 OBJS-$(CONFIG_BENCH_FILTER)                  += f_bench.o
@@ -210,10 +210,10 @@ OBJS-$(CONFIG_BILATERAL_FILTER)              += vf_bilateral.o
 OBJS-$(CONFIG_BILATERAL_CUDA_FILTER)         += vf_bilateral_cuda.o vf_bilateral_cuda.ptx.o
 OBJS-$(CONFIG_BITPLANENOISE_FILTER)          += vf_bitplanenoise.o
 OBJS-$(CONFIG_BLACKDETECT_FILTER)            += vf_blackdetect.o
-OBJS-$(CONFIG_BLACKDETECT_VULKAN_FILTER)     += vf_blackdetect_vulkan.o
+OBJS-$(CONFIG_BLACKDETECT_VULKAN_FILTER)     += vulkan/vf_blackdetect_vulkan.o
 OBJS-$(CONFIG_BLACKFRAME_FILTER)             += vf_blackframe.o
 OBJS-$(CONFIG_BLEND_FILTER)                  += vf_blend.o framesync.o
-OBJS-$(CONFIG_BLEND_VULKAN_FILTER)           += vf_blend_vulkan.o framesync.o vulkan.o vulkan_filter.o
+OBJS-$(CONFIG_BLEND_VULKAN_FILTER)           += vulkan/vf_blend_vulkan.o framesync.o vulkan.o vulkan/vulkan_filter.o
 OBJS-$(CONFIG_BLOCKDETECT_FILTER)            += vf_blockdetect.o
 OBJS-$(CONFIG_BLURDETECT_FILTER)             += vf_blurdetect.o edge_common.o
 OBJS-$(CONFIG_BM3D_FILTER)                   += vf_bm3d.o framesync.o
@@ -223,10 +223,10 @@ OBJS-$(CONFIG_BOXBLUR_OPENCL_FILTER)         += vf_avgblur_opencl.o opencl.o \
 OBJS-$(CONFIG_BWDIF_FILTER)                  += vf_bwdif.o bwdifdsp.o yadif_common.o
 OBJS-$(CONFIG_BWDIF_CUDA_FILTER)             += vf_bwdif_cuda.o vf_bwdif_cuda.ptx.o \
                                                 yadif_common.o
-OBJS-$(CONFIG_BWDIF_VULKAN_FILTER)           += vf_bwdif_vulkan.o yadif_common.o vulkan.o vulkan_filter.o
+OBJS-$(CONFIG_BWDIF_VULKAN_FILTER)           += vulkan/vf_bwdif_vulkan.o yadif_common.o vulkan.o vulkan/vulkan_filter.o
 OBJS-$(CONFIG_CAS_FILTER)                    += vf_cas.o
 OBJS-$(CONFIG_CCREPACK_FILTER)               += vf_ccrepack.o
-OBJS-$(CONFIG_CHROMABER_VULKAN_FILTER)       += vf_chromaber_vulkan.o vulkan.o vulkan_filter.o
+OBJS-$(CONFIG_CHROMABER_VULKAN_FILTER)       += vulkan/vf_chromaber_vulkan.o vulkan.o vulkan/vulkan_filter.o
 OBJS-$(CONFIG_CHROMAHOLD_FILTER)             += vf_chromakey.o
 OBJS-$(CONFIG_CHROMAKEY_FILTER)              += vf_chromakey.o
 OBJS-$(CONFIG_CHROMAKEY_CUDA_FILTER)         += vf_chromakey_cuda.o vf_chromakey_cuda.ptx.o
@@ -331,7 +331,7 @@ OBJS-$(CONFIG_FREI0R_FILTER)                 += vf_frei0r.o
 OBJS-$(CONFIG_FSPP_FILTER)                   += vf_fspp.o qp_table.o
 OBJS-$(CONFIG_FSYNC_FILTER)                  += vf_fsync.o
 OBJS-$(CONFIG_GBLUR_FILTER)                  += vf_gblur.o
-OBJS-$(CONFIG_GBLUR_VULKAN_FILTER)           += vf_gblur_vulkan.o vulkan.o vulkan_filter.o
+OBJS-$(CONFIG_GBLUR_VULKAN_FILTER)           += vulkan/vf_gblur_vulkan.o vulkan.o vulkan/vulkan_filter.o
 OBJS-$(CONFIG_GEQ_FILTER)                    += vf_geq.o
 OBJS-$(CONFIG_GRADFUN_FILTER)                += vf_gradfun.o
 OBJS-$(CONFIG_GRAPHMONITOR_FILTER)           += f_graphmonitor.o
@@ -340,7 +340,7 @@ OBJS-$(CONFIG_GREYEDGE_FILTER)               += vf_colorconstancy.o
 OBJS-$(CONFIG_GUIDED_FILTER)                 += vf_guided.o framesync.o
 OBJS-$(CONFIG_HALDCLUT_FILTER)               += vf_lut3d.o framesync.o
 OBJS-$(CONFIG_HFLIP_FILTER)                  += vf_hflip.o
-OBJS-$(CONFIG_HFLIP_VULKAN_FILTER)           += vf_flip_vulkan.o vulkan.o
+OBJS-$(CONFIG_HFLIP_VULKAN_FILTER)           += vulkan/vf_flip_vulkan.o vulkan.o
 OBJS-$(CONFIG_HISTEQ_FILTER)                 += vf_histeq.o
 OBJS-$(CONFIG_HISTOGRAM_FILTER)              += vf_histogram.o
 OBJS-$(CONFIG_HQDN3D_FILTER)                 += vf_hqdn3d.o
@@ -362,7 +362,7 @@ OBJS-$(CONFIG_IDET_FILTER)                   += vf_idet.o
 OBJS-$(CONFIG_IL_FILTER)                     += vf_il.o
 OBJS-$(CONFIG_INFLATE_FILTER)                += vf_neighbor.o
 OBJS-$(CONFIG_INTERLACE_FILTER)              += vf_tinterlace.o
-OBJS-$(CONFIG_INTERLACE_VULKAN_FILTER)       += vf_interlace_vulkan.o vulkan.o vulkan_filter.o
+OBJS-$(CONFIG_INTERLACE_VULKAN_FILTER)       += vulkan/vf_interlace_vulkan.o vulkan.o vulkan/vulkan_filter.o
 OBJS-$(CONFIG_INTERLEAVE_FILTER)             += f_interleave.o
 OBJS-$(CONFIG_KERNDEINT_FILTER)              += vf_kerndeint.o
 OBJS-$(CONFIG_KIRSCH_FILTER)                 += vf_convolution.o
@@ -371,7 +371,7 @@ OBJS-$(CONFIG_LCEVC_FILTER)                  += vf_lcevc.o
 OBJS-$(CONFIG_LATENCY_FILTER)                += f_latency.o
 OBJS-$(CONFIG_LENSCORRECTION_FILTER)         += vf_lenscorrection.o
 OBJS-$(CONFIG_LENSFUN_FILTER)                += vf_lensfun.o
-OBJS-$(CONFIG_LIBPLACEBO_FILTER)             += vf_libplacebo.o vulkan.o vulkan_filter.o
+OBJS-$(CONFIG_LIBPLACEBO_FILTER)             += vf_libplacebo.o vulkan.o vulkan/vulkan_filter.o
 OBJS-$(CONFIG_LIBVMAF_FILTER)                += vf_libvmaf.o framesync.o
 OBJS-$(CONFIG_LIBVMAF_CUDA_FILTER)           += vf_libvmaf.o framesync.o
 OBJS-$(CONFIG_LIMITDIFF_FILTER)              += vf_limitdiff.o framesync.o
@@ -406,7 +406,7 @@ OBJS-$(CONFIG_MULTIPLY_FILTER)               += vf_multiply.o framesync.o
 OBJS-$(CONFIG_NEGATE_FILTER)                 += vf_negate.o
 OBJS-$(CONFIG_NLMEANS_FILTER)                += vf_nlmeans.o
 OBJS-$(CONFIG_NLMEANS_OPENCL_FILTER)         += vf_nlmeans_opencl.o opencl.o opencl/nlmeans.o
-OBJS-$(CONFIG_NLMEANS_VULKAN_FILTER)         += vf_nlmeans_vulkan.o vulkan.o vulkan_filter.o
+OBJS-$(CONFIG_NLMEANS_VULKAN_FILTER)         += vulkan/vf_nlmeans_vulkan.o vulkan.o vulkan/vulkan_filter.o
 OBJS-$(CONFIG_NNEDI_FILTER)                  += vf_nnedi.o
 OBJS-$(CONFIG_NOFORMAT_FILTER)               += vf_format.o
 OBJS-$(CONFIG_NOISE_FILTER)                  += vf_noise.o
@@ -422,7 +422,7 @@ OBJS-$(CONFIG_OVERLAY_OPENCL_FILTER)         += vf_overlay_opencl.o opencl.o \
                                                 opencl/overlay.o framesync.o
 OBJS-$(CONFIG_OVERLAY_QSV_FILTER)            += vf_overlay_qsv.o framesync.o
 OBJS-$(CONFIG_OVERLAY_VAAPI_FILTER)          += vf_overlay_vaapi.o framesync.o vaapi_vpp.o
-OBJS-$(CONFIG_OVERLAY_VULKAN_FILTER)         += vf_overlay_vulkan.o vulkan.o vulkan_filter.o
+OBJS-$(CONFIG_OVERLAY_VULKAN_FILTER)         += vulkan/vf_overlay_vulkan.o vulkan.o vulkan/vulkan_filter.o
 OBJS-$(CONFIG_OWDENOISE_FILTER)              += vf_owdenoise.o
 OBJS-$(CONFIG_PAD_FILTER)                    += vf_pad.o
 OBJS-$(CONFIG_PAD_CUDA_FILTER)               += vf_pad_cuda.o vf_pad_cuda.ptx.o cuda/load_helper.o
@@ -473,11 +473,11 @@ OBJS-$(CONFIG_SCALE_NPP_FILTER)              += vf_scale_npp.o scale_eval.o
 OBJS-$(CONFIG_SCALE_QSV_FILTER)              += vf_vpp_qsv.o
 OBJS-$(CONFIG_SCALE_VAAPI_FILTER)            += vf_scale_vaapi.o scale_eval.o vaapi_vpp.o
 OBJS-$(CONFIG_SCALE_VT_FILTER)               += vf_scale_vt.o scale_eval.o
-OBJS-$(CONFIG_SCALE_VULKAN_FILTER)           += vf_scale_vulkan.o vulkan.o vulkan_filter.o
+OBJS-$(CONFIG_SCALE_VULKAN_FILTER)           += vulkan/vf_scale_vulkan.o vulkan.o vulkan/vulkan_filter.o
 OBJS-$(CONFIG_SCALE2REF_FILTER)              += vf_scale.o scale_eval.o framesync.o
 OBJS-$(CONFIG_SCALE2REF_NPP_FILTER)          += vf_scale_npp.o scale_eval.o
 OBJS-$(CONFIG_SCDET_FILTER)                  += vf_scdet.o
-OBJS-$(CONFIG_SCDET_VULKAN_FILTER)           += vf_scdet_vulkan.o
+OBJS-$(CONFIG_SCDET_VULKAN_FILTER)           += vulkan/vf_scdet_vulkan.o
 OBJS-$(CONFIG_SCHARR_FILTER)                 += vf_convolution.o
 OBJS-$(CONFIG_SCROLL_FILTER)                 += vf_scroll.o
 OBJS-$(CONFIG_SEGMENT_FILTER)                += f_segment.o
@@ -544,7 +544,7 @@ OBJS-$(CONFIG_TRANSPOSE_NPP_FILTER)          += vf_transpose_npp.o
 OBJS-$(CONFIG_TRANSPOSE_OPENCL_FILTER)       += vf_transpose_opencl.o opencl.o opencl/transpose.o
 OBJS-$(CONFIG_TRANSPOSE_VAAPI_FILTER)        += vf_transpose_vaapi.o vaapi_vpp.o
 OBJS-$(CONFIG_TRANSPOSE_VT_FILTER)           += vf_transpose_vt.o
-OBJS-$(CONFIG_TRANSPOSE_VULKAN_FILTER)       += vf_transpose_vulkan.o vulkan.o vulkan_filter.o
+OBJS-$(CONFIG_TRANSPOSE_VULKAN_FILTER)       += vulkan/vf_transpose_vulkan.o vulkan.o vulkan/vulkan_filter.o
 OBJS-$(CONFIG_TRIM_FILTER)                   += trim.o
 OBJS-$(CONFIG_UNPREMULTIPLY_FILTER)          += vf_premultiply.o framesync.o
 OBJS-$(CONFIG_UNSHARP_FILTER)                += vf_unsharp.o
@@ -557,7 +557,7 @@ OBJS-$(CONFIG_VAGUEDENOISER_FILTER)          += vf_vaguedenoiser.o
 OBJS-$(CONFIG_VARBLUR_FILTER)                += vf_varblur.o framesync.o
 OBJS-$(CONFIG_VECTORSCOPE_FILTER)            += vf_vectorscope.o
 OBJS-$(CONFIG_VFLIP_FILTER)                  += vf_vflip.o
-OBJS-$(CONFIG_VFLIP_VULKAN_FILTER)           += vf_flip_vulkan.o vulkan.o
+OBJS-$(CONFIG_VFLIP_VULKAN_FILTER)           += vulkan/vf_flip_vulkan.o vulkan.o
 OBJS-$(CONFIG_VFRDET_FILTER)                 += vf_vfrdet.o
 OBJS-$(CONFIG_VIBRANCE_FILTER)               += vf_vibrance.o
 OBJS-$(CONFIG_VIDSTABDETECT_FILTER)          += vidstabutils.o vf_vidstabdetect.o
@@ -575,7 +575,7 @@ OBJS-$(CONFIG_XBR_FILTER)                    += vf_xbr.o
 OBJS-$(CONFIG_XCORRELATE_FILTER)             += vf_convolve.o framesync.o
 OBJS-$(CONFIG_XFADE_FILTER)                  += vf_xfade.o
 OBJS-$(CONFIG_XFADE_OPENCL_FILTER)           += vf_xfade_opencl.o opencl.o opencl/xfade.o
-OBJS-$(CONFIG_XFADE_VULKAN_FILTER)           += vf_xfade_vulkan.o vulkan.o vulkan_filter.o
+OBJS-$(CONFIG_XFADE_VULKAN_FILTER)           += vulkan/vf_xfade_vulkan.o vulkan.o vulkan/vulkan_filter.o
 OBJS-$(CONFIG_XMEDIAN_FILTER)                += vf_xmedian.o framesync.o
 OBJS-$(CONFIG_XPSNR_FILTER)                  += vf_xpsnr.o framesync.o psnr.o
 OBJS-$(CONFIG_XSTACK_FILTER)                 += vf_stack.o framesync.o
@@ -624,7 +624,7 @@ OBJS-$(CONFIG_RGBTESTSRC_FILTER)             += vsrc_testsrc.o
 OBJS-$(CONFIG_SIERPINSKI_FILTER)             += vsrc_sierpinski.o
 OBJS-$(CONFIG_SMPTEBARS_FILTER)              += vsrc_testsrc.o
 OBJS-$(CONFIG_SMPTEHDBARS_FILTER)            += vsrc_testsrc.o
-OBJS-$(CONFIG_COLOR_VULKAN_FILTER)           += vsrc_testsrc_vulkan.o vulkan.o vulkan_filter.o
+OBJS-$(CONFIG_COLOR_VULKAN_FILTER)           += vulkan/vsrc_testsrc_vulkan.o vulkan.o vulkan/vulkan_filter.o
 OBJS-$(CONFIG_TESTSRC_FILTER)                += vsrc_testsrc.o
 OBJS-$(CONFIG_TESTSRC2_FILTER)               += vsrc_testsrc.o
 OBJS-$(CONFIG_YUVTESTSRC_FILTER)             += vsrc_testsrc.o
@@ -674,7 +674,7 @@ SKIPHEADERS-$(CONFIG_AMF)                    += vf_amf_common.h
 SKIPHEADERS-$(CONFIG_QSVVPP)                 += qsvvpp.h stack_internal.h
 SKIPHEADERS-$(CONFIG_OPENCL)                 += opencl.h
 SKIPHEADERS-$(CONFIG_VAAPI)                  += vaapi_vpp.h stack_internal.h
-SKIPHEADERS-$(CONFIG_VULKAN)                 += vulkan_filter.h
+SKIPHEADERS-$(CONFIG_VULKAN)                 += vulkan/vulkan_filter.h
 
 TOOLS     = graph2dot
 TESTPROGS = drawutils filtfmts formats integral
-- 
2.49.1


From cc103ac919c759c2d7514bf811548e520b7b3bac Mon Sep 17 00:00:00 2001
From: Jamaika1 <lukaszcz18@wp.pl>
Date: Wed, 3 Sep 2025 14:30:38 +0000
Subject: [PATCH 118/118] Changing vulkan file directory

---
 libavutil/Makefile | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/libavutil/Makefile b/libavutil/Makefile
index ee77e51c08..33b3c2cc9c 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -217,7 +217,7 @@ OBJS-$(CONFIG_QSV)                      += hwcontext_qsv.o
 OBJS-$(CONFIG_VAAPI)                    += hwcontext_vaapi.o
 OBJS-$(CONFIG_VIDEOTOOLBOX)             += hwcontext_videotoolbox.o
 OBJS-$(CONFIG_VDPAU)                    += hwcontext_vdpau.o
-OBJS-$(CONFIG_VULKAN)                   += hwcontext_vulkan.o vulkan.o
+OBJS-$(CONFIG_VULKAN)                   += vulkan/hwcontext_vulkan.o vulkan/vulkan.o
 
 OBJS-$(!CONFIG_VULKAN)                  += hwcontext_stub.o
 
@@ -247,11 +247,11 @@ SKIPHEADERS-$(CONFIG_OPENCL)           += hwcontext_opencl.h
 SKIPHEADERS-$(CONFIG_VAAPI)            += hwcontext_vaapi.h
 SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX)     += hwcontext_videotoolbox.h
 SKIPHEADERS-$(CONFIG_VDPAU)            += hwcontext_vdpau.h
-SKIPHEADERS-$(CONFIG_VULKAN)           += hwcontext_vulkan.h vulkan.h   \
-                                          vulkan_functions.h            \
-                                          vulkan_loader.h
-SKIPHEADERS-$(CONFIG_LIBSHADERC)       += vulkan_spirv.h
-SKIPHEADERS-$(CONFIG_LIBGLSLANG)       += vulkan_spirv.h
+SKIPHEADERS-$(CONFIG_VULKAN)           += vulkan/hwcontext_vulkan.h vulkan/vulkan.h   \
+                                          vulkan/vulkan_functions.h            \
+                                          vulkan/vulkan_loader.h
+SKIPHEADERS-$(CONFIG_LIBSHADERC)       += vulkan/vulkan_spirv.h
+SKIPHEADERS-$(CONFIG_LIBGLSLANG)       += vulkan/vulkan_spirv.h
 
 TESTPROGS = adler32                                                     \
             aes                                                         \
-- 
2.49.1

_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org

                 reply	other threads:[~2025-09-05 12:06 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=175691058908.25.12192413182319126055@463a07221176 \
    --to=ffmpeg-devel@ffmpeg.org \
    --cc=code@ffmpeg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git