This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit a6391168f2310941f2c021d257747de1103a0f4c
Author:     Lynne <[email protected]>
AuthorDate: Fri Jan 2 10:00:10 2026 +0100
Commit:     Lynne <[email protected]>
CommitDate: Mon Jan 12 17:28:42 2026 +0100

    bwdif_vulkan: use compile-time SPIR-V
---
 configure                                          |  4 +-
 libavfilter/vf_bwdif_vulkan.c                      | 97 ++--------------------
 libavfilter/vulkan/Makefile                        |  2 +-
 libavfilter/vulkan/{bwdif.comp => bwdif.comp.glsl} | 49 ++++++++++-
 4 files changed, 57 insertions(+), 95 deletions(-)

diff --git a/configure b/configure
index 5a4fa45cf7..9cf4c5cf9b 100755
--- a/configure
+++ b/configure
@@ -4045,7 +4045,7 @@ boxblur_opencl_filter_deps="opencl gpl"
 bs2b_filter_deps="libbs2b"
 bwdif_cuda_filter_deps="ffnvcodec"
 bwdif_cuda_filter_deps_any="cuda_nvcc cuda_llvm"
-bwdif_vulkan_filter_deps="vulkan spirv_library"
+bwdif_vulkan_filter_deps="vulkan"
 chromaber_vulkan_filter_deps="vulkan spirv_library"
 color_vulkan_filter_deps="vulkan spirv_library"
 colorkey_opencl_filter_deps="opencl"
@@ -4243,7 +4243,7 @@ avcodec_suggest="libm stdatomic spirv_library"
 avdevice_deps="avformat avcodec avutil"
 avdevice_suggest="libm stdatomic"
 avfilter_deps="avutil"
-avfilter_suggest="libm stdatomic spirv_library"
+avfilter_suggest="libm stdatomic zlib spirv_library"
 avformat_deps="avcodec avutil"
 avformat_suggest="libm network zlib stdatomic"
 avutil_suggest="clock_gettime ffnvcodec gcrypt libm zlib libdrm libmfx opencl 
openssl user32 vaapi vulkan videotoolbox corefoundation corevideo coremedia 
bcrypt stdatomic"
diff --git a/libavfilter/vf_bwdif_vulkan.c b/libavfilter/vf_bwdif_vulkan.c
index 549e814886..c6fb6abe9c 100644
--- a/libavfilter/vf_bwdif_vulkan.c
+++ b/libavfilter/vf_bwdif_vulkan.c
@@ -22,7 +22,6 @@
 
 #include "libavutil/random_seed.h"
 #include "libavutil/opt.h"
-#include "libavutil/vulkan_spirv.h"
 #include "vulkan_filter.h"
 #include "yadif.h"
 #include "filters.h"
@@ -43,27 +42,17 @@ typedef struct BWDIFParameters {
     int current_field;
 } BWDIFParameters;
 
-extern const char *ff_source_bwdif_comp;
+extern const unsigned char ff_bwdif_comp_spv_data[];
+extern const unsigned int ff_bwdif_comp_spv_len;
 
 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");
@@ -73,119 +62,49 @@ static av_cold int init_filter(AVFilterContext *ctx)
 
     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;
+    ff_vk_shader_load(&s->shd, VK_SHADER_STAGE_COMPUTE_BIT, NULL,
+                      (uint32_t [3]) { 1, 64, planes }, 0);
 
     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_descriptor_set(vkctx, &s->shd, desc, 4, 0, 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_link(vkctx, &s->shd,
+                          ff_bwdif_comp_spv_data,
+                          ff_bwdif_comp_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;
 }
 
diff --git a/libavfilter/vulkan/Makefile b/libavfilter/vulkan/Makefile
index 911cb1015e..851e3e0cbf 100644
--- a/libavfilter/vulkan/Makefile
+++ b/libavfilter/vulkan/Makefile
@@ -1,7 +1,7 @@
 clean::
        $(RM) $(CLEANSUFFIXES:%=libavfilter/vulkan/%)
 
-OBJS-$(CONFIG_BWDIF_VULKAN_FILTER) += vulkan/bwdif.o
+OBJS-$(CONFIG_BWDIF_VULKAN_FILTER) += vulkan/bwdif.comp.spv.o
 OBJS-$(CONFIG_SCALE_VULKAN_FILTER) += vulkan/debayer.o
 
 VULKAN = $(subst $(SRC_PATH)/,,$(wildcard 
$(SRC_PATH)/libavfilter/vulkan/*.comp))
diff --git a/libavfilter/vulkan/bwdif.comp b/libavfilter/vulkan/bwdif.comp.glsl
similarity index 75%
rename from libavfilter/vulkan/bwdif.comp
rename to libavfilter/vulkan/bwdif.comp.glsl
index 5152464823..043ded0d24 100644
--- a/libavfilter/vulkan/bwdif.comp
+++ b/libavfilter/vulkan/bwdif.comp.glsl
@@ -18,6 +18,26 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#version 460
+#pragma shader_stage(compute)
+
+#extension GL_EXT_shader_image_load_formatted : require
+#extension GL_EXT_nonuniform_qualifier : require
+#extension GL_EXT_scalar_block_layout : require
+
+layout (local_size_x_id = 253, local_size_y_id = 254, local_size_z_id = 255) 
in;
+
+layout (set = 0, binding = 0) uniform readonly  image2D prev[];
+layout (set = 0, binding = 1) uniform readonly  image2D  cur[];
+layout (set = 0, binding = 2) uniform readonly  image2D next[];
+layout (set = 0, binding = 3) uniform writeonly image2D  dst[];
+
+layout (push_constant, scalar) uniform pushConstants {
+    int parity;
+    int tff;
+    int current_field;
+};
+
 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), };
@@ -27,8 +47,10 @@ 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)
+void process_plane_intra(ivec2 pos)
 {
+    nonuniformEXT uint idx = gl_LocalInvocationID.z;
+
     vec4 dcur[4];
     dcur[0] = imageLoad(cur[idx], pos - ivec2(0, 3));
     dcur[1] = imageLoad(cur[idx], pos - ivec2(0, 1));
@@ -72,9 +94,11 @@ vec4 process_line(vec4 prev2[5], vec4 prev1[2], vec4 cur[4], 
vec4 next1[2], vec4
    return mix(interpol, fd, diff_mask);
 }
 
-void process_plane(int idx, const ivec2 pos, bool filter_field,
-                   bool is_intra, bool field_parity)
+void process_plane(const ivec2 pos)
 {
+    nonuniformEXT uint idx = gl_LocalInvocationID.z;
+    bool field_parity = (parity ^ tff) != 0;
+
     vec4 dcur[4];
     vec4 prev1[2];
     vec4 next1[2];
@@ -120,3 +144,22 @@ void process_plane(int idx, const ivec2 pos, bool 
filter_field,
 
     imageStore(dst[idx], pos, process_line(prev2, prev1, dcur, next1, next2));
 }
+
+void main()
+{
+    const ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
+    bool filter_field = ((pos.y ^ parity) & 1) == 1;
+    bool is_intra = filter_field && (current_field == 0);
+
+#define IS_WITHIN(v1, v2) ((v1.x < v2.x) && (v1.y < v2.y))
+    if (!IS_WITHIN(pos, 
imageSize(dst[nonuniformEXT(gl_LocalInvocationID.z)]))) {
+        return;
+    } else if (is_intra) {
+        process_plane_intra(pos);
+    } else if (filter_field) {
+        process_plane(pos);
+    } else {
+        imageStore(dst[nonuniformEXT(gl_LocalInvocationID.z)], pos,
+                   imageLoad(cur[nonuniformEXT(gl_LocalInvocationID.z)], pos));
+    }
+}

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to