This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 117807510a8b2b60585a01066eb18a88a49c1c51 Author: Lynne <[email protected]> AuthorDate: Tue Apr 21 16:11:24 2026 +0200 Commit: Lynne <[email protected]> CommitDate: Wed Apr 22 12:45:45 2026 +0200 vf_overlay_vulkan: port to compile-time SPIR-V generation --- configure | 2 +- libavfilter/vf_overlay_vulkan.c | 135 ++++++++--------------------------- libavfilter/vulkan/Makefile | 1 + libavfilter/vulkan/overlay.comp.glsl | 81 +++++++++++++++++++++ 4 files changed, 112 insertions(+), 107 deletions(-) diff --git a/configure b/configure index d68cc3cea8..f4e1f13589 100755 --- a/configure +++ b/configure @@ -4233,7 +4233,7 @@ overlay_opencl_filter_deps="opencl" overlay_qsv_filter_deps="libmfx" overlay_qsv_filter_select="qsvvpp" overlay_vaapi_filter_deps="vaapi VAProcPipelineCaps_blend_flags" -overlay_vulkan_filter_deps="vulkan spirv_library" +overlay_vulkan_filter_deps="vulkan spirv_compiler" owdenoise_filter_deps="gpl" pad_opencl_filter_deps="opencl" pan_filter_deps="swresample" diff --git a/libavfilter/vf_overlay_vulkan.c b/libavfilter/vf_overlay_vulkan.c index e1a07e4bfd..67b372a6f1 100644 --- a/libavfilter/vf_overlay_vulkan.c +++ b/libavfilter/vf_overlay_vulkan.c @@ -18,15 +18,16 @@ * 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" +extern const unsigned char ff_overlay_comp_spv_data[]; +extern const unsigned int ff_overlay_comp_spv_len; + typedef struct OverlayVulkanContext { FFVulkanContext vkctx; FFFrameSync fs; @@ -38,8 +39,8 @@ typedef struct OverlayVulkanContext { /* Push constants / options */ struct { - int32_t o_offset[2*3]; - int32_t o_size[2*3]; + int32_t o_offset[2*4]; + int32_t o_size[2*4]; } opts; int overlay_x; @@ -48,57 +49,15 @@ typedef struct OverlayVulkanContext { 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) { @@ -108,70 +67,39 @@ 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, "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, ); + + SPEC_LIST_CREATE(sl, 2, 2*sizeof(uint32_t)) + SPEC_LIST_ADD(sl, 0, 32, planes); + SPEC_LIST_ADD(sl, 1, 32, ialpha); + + ff_vk_shader_load(&s->shd, VK_SHADER_STAGE_COMPUTE_BIT, sl, + (int []) { 32, 32, 1 }, 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, + const FFVulkanDescriptorSetBinding desc[] = { + { /* main_img */ + .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .elems = planes, }, - { - .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, + { /* overlay_img */ + .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .elems = planes, }, - { - .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, + { /* output_img */ + .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .elems = planes, }, }; + ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 3, 0, 0); - 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_link(vkctx, shd, + ff_overlay_comp_spv_data, + ff_overlay_comp_spv_len, "main")); RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd)); @@ -192,11 +120,6 @@ static av_cold int init_filter(AVFilterContext *ctx) 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 d45a6d173d..6d25cf8a50 100644 --- a/libavfilter/vulkan/Makefile +++ b/libavfilter/vulkan/Makefile @@ -9,6 +9,7 @@ OBJS-$(CONFIG_COLOR_VULKAN_FILTER) += vulkan/color.comp.spv.o OBJS-$(CONFIG_GBLUR_VULKAN_FILTER) += vulkan/gblur.comp.spv.o OBJS-$(CONFIG_SCALE_VULKAN_FILTER) += vulkan/debayer.comp.spv.o OBJS-$(CONFIG_SCDET_VULKAN_FILTER) += vulkan/scdet.comp.spv.o +OBJS-$(CONFIG_OVERLAY_VULKAN_FILTER) += vulkan/overlay.comp.spv.o OBJS-$(CONFIG_FLIP_VULKAN_FILTER) += vulkan/flip.comp.spv.o OBJS-$(CONFIG_TRANSPOSE_VULKAN_FILTER) += vulkan/transpose.comp.spv.o OBJS-$(CONFIG_V360_VULKAN_FILTER) += vulkan/v360.comp.spv.o diff --git a/libavfilter/vulkan/overlay.comp.glsl b/libavfilter/vulkan/overlay.comp.glsl new file mode 100644 index 0000000000..a7d55a8c01 --- /dev/null +++ b/libavfilter/vulkan/overlay.comp.glsl @@ -0,0 +1,81 @@ +/* + * 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 + */ + +#pragma shader_stage(compute) + +#extension GL_EXT_shader_image_load_formatted : require +#extension GL_EXT_scalar_block_layout : require +#extension GL_EXT_nonuniform_qualifier : require + +layout (constant_id = 0) const uint planes = 0; +layout (constant_id = 1) const bool has_alpha = false; + +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 main_img[]; +layout (set = 0, binding = 1) uniform readonly image2D overlay_img[]; +layout (set = 0, binding = 2) uniform writeonly image2D output_img[]; + +layout (push_constant, scalar) uniform pushConstants { + ivec2 o_offset[4]; + ivec2 o_size[4]; +}; + +void overlay_noalpha(uint i, ivec2 pos) +{ + 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))) { + vec4 res = imageLoad(overlay_img[i], pos - o_offset[i]); + imageStore(output_img[i], pos, res); + } else { + vec4 res = imageLoad(main_img[i], pos); + imageStore(output_img[i], pos, res); + } +} + +void overlay_alpha_opaque(uint i, ivec2 pos) +{ + vec4 res = imageLoad(main_img[i], pos); + 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))) { + vec4 ovr = imageLoad(overlay_img[i], pos - o_offset[i]); + res = ovr * ovr.a + res * (1.0f - ovr.a); + res.a = 1.0f; + imageStore(output_img[i], pos, res); + } + imageStore(output_img[i], pos, res); +} + +void main() +{ + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + + for (uint i = 0; i < planes; i++) { + if (any(greaterThanEqual(pos, imageSize(output_img[i])))) + return; + + if (has_alpha) + overlay_alpha_opaque(i, pos); + else + overlay_noalpha(i, pos); + } +} _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
