This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit bd24abfb6cb691c42388c4649fac71589431a01c Author: Lynne <[email protected]> AuthorDate: Mon Feb 23 22:11:44 2026 +0100 Commit: Lynne <[email protected]> CommitDate: Thu Feb 26 14:10:22 2026 +0100 swscale/vulkan: initialize GLSL compilation and shader execution Sponsored-by: Sovereign Tech Fund --- configure | 2 +- libswscale/vulkan/Makefile | 2 + libswscale/vulkan/ops.c | 222 ++++++++++++++++++++- libswscale/vulkan/ops.h | 7 + .../vulkan}/vulkan_glslang.c | 0 .../vulkan}/vulkan_shaderc.c | 0 6 files changed, 230 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 6d3c36bf61..a64a73eea8 100755 --- a/configure +++ b/configure @@ -4289,7 +4289,7 @@ avutil_suggest="clock_gettime ffnvcodec gcrypt libm zlib libdrm libmfx opencl op swresample_deps="avutil" swresample_suggest="libm libsoxr stdatomic" swscale_deps="avutil" -swscale_suggest="libm stdatomic" +swscale_suggest="libm stdatomic spirv_library" shader_compression_suggest="zlib" avcodec_extralibs="pthreads_extralibs iconv_extralibs dxva2_extralibs liblcevc_dec_extralibs lcms2_extralibs" diff --git a/libswscale/vulkan/Makefile b/libswscale/vulkan/Makefile index 396cdeb936..e899f35955 100644 --- a/libswscale/vulkan/Makefile +++ b/libswscale/vulkan/Makefile @@ -2,3 +2,5 @@ clean:: $(RM) $(CLEANSUFFIXES:%=libswscale/vulkan/%) OBJS-$(CONFIG_VULKAN) += vulkan/ops.o vulkan/vulkan.o +OBJS-$(CONFIG_LIBSHADERC) += vulkan/vulkan_shaderc.o +OBJS-$(CONFIG_LIBGLSLANG) += vulkan/vulkan_glslang.o diff --git a/libswscale/vulkan/ops.c b/libswscale/vulkan/ops.c index 0b39e08830..b77eb924c7 100644 --- a/libswscale/vulkan/ops.c +++ b/libswscale/vulkan/ops.c @@ -30,6 +30,10 @@ void ff_sws_vk_uninit(SwsContext *sws) if (!s) return; +#if CONFIG_LIBSHADERC || CONFIG_LIBGLSLANG + if (s->spvc) + s->spvc->uninit(&s->spvc); +#endif ff_vk_exec_pool_free(&s->vkctx, &s->e); ff_vk_uninit(&s->vkctx); av_freep(&c->hw_priv); @@ -70,23 +74,80 @@ int ff_sws_vk_init(SwsContext *sws, AVBufferRef *dev_ref) if (err < 0) return err; +#if CONFIG_LIBSHADERC || CONFIG_LIBGLSLANG + if (!s->spvc) { + s->spvc = ff_vk_spirv_init(); + if (!s->spvc) + return AVERROR(ENOMEM); + } +#endif + return 0; } typedef struct VulkanPriv { FFVulkanOpsCtx *s; FFVulkanShader shd; + enum FFVkShaderRepFormat src_rep; + enum FFVkShaderRepFormat dst_rep; } VulkanPriv; static void process(const SwsOpExec *exec, const void *priv, int x_start, int y_start, int x_end, int y_end) { - const VulkanPriv *p = priv; + VulkanPriv *p = (VulkanPriv *)priv; FFVkExecContext *ec = ff_vk_exec_get(&p->s->vkctx, &p->s->e); + FFVulkanFunctions *vk = &p->s->vkctx.vkfn; ff_vk_exec_start(&p->s->vkctx, ec); + AVFrame *src_f = (AVFrame *)exec->src_frame_ptr; + AVFrame *dst_f = (AVFrame *)exec->dst_frame_ptr; + ff_vk_exec_add_dep_frame(&p->s->vkctx, ec, src_f, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT); + ff_vk_exec_add_dep_frame(&p->s->vkctx, ec, dst_f, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT); + + VkImageView src_views[AV_NUM_DATA_POINTERS]; + VkImageView dst_views[AV_NUM_DATA_POINTERS]; + ff_vk_create_imageviews(&p->s->vkctx, ec, src_views, src_f, p->src_rep); + ff_vk_create_imageviews(&p->s->vkctx, ec, dst_views, dst_f, p->dst_rep); + + ff_vk_shader_update_img_array(&p->s->vkctx, ec, &p->shd, src_f, src_views, + 0, 0, VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE); + ff_vk_shader_update_img_array(&p->s->vkctx, ec, &p->shd, dst_f, dst_views, + 0, 1, VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE); + + int nb_img_bar = 0; + VkImageMemoryBarrier2 img_bar[8]; + ff_vk_frame_barrier(&p->s->vkctx, ec, src_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, + VK_IMAGE_LAYOUT_GENERAL, + VK_QUEUE_FAMILY_IGNORED); + ff_vk_frame_barrier(&p->s->vkctx, ec, dst_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); + vk->CmdPipelineBarrier2(ec->buf, &(VkDependencyInfo) { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pImageMemoryBarriers = img_bar, + .imageMemoryBarrierCount = nb_img_bar, + }); + + ff_vk_exec_bind_shader(&p->s->vkctx, ec, &p->shd); + + vk->CmdDispatch(ec->buf, + FFALIGN(src_f->width, p->shd.lg_size[0])/p->shd.lg_size[0], + FFALIGN(src_f->height, p->shd.lg_size[1])/p->shd.lg_size[1], + 1); ff_vk_exec_submit(&p->s->vkctx, ec); + ff_vk_exec_wait(&p->s->vkctx, ec); } static void free_fn(void *priv) @@ -96,17 +157,174 @@ static void free_fn(void *priv) av_free(priv); } +#if CONFIG_LIBSHADERC || CONFIG_LIBGLSLANG +static int add_ops_glsl(VulkanPriv *p, FFVulkanOpsCtx *s, + SwsOpList *ops, FFVulkanShader *shd) +{ + int err; + uint8_t *spv_data; + size_t spv_len; + void *spv_opaque = NULL; + + /* Interlaced formats are not currently supported */ + if (ops->src.interlaced || ops->src.interlaced) + return AVERROR(ENOTSUP); + + err = ff_vk_shader_init(&s->vkctx, shd, "sws_pass", + VK_SHADER_STAGE_COMPUTE_BIT, + NULL, 0, 32, 32, 1, 0); + if (err < 0) + return err; + + int nb_desc = 0; + FFVulkanDescriptorSetBinding buf_desc[8]; + + for (int n = 0; n < ops->num_ops; n++) { + const SwsOp *op = &ops->ops[n]; + /* Set initial type */ + if (op->op == SWS_OP_READ || op->op == SWS_OP_WRITE || + op->op == SWS_OP_CLEAR) { + if (op->rw.frac) + return AVERROR(ENOTSUP); + } + if (op->op == SWS_OP_READ || op->op == SWS_OP_WRITE) { + const char *img_type = op->type == SWS_PIXEL_F32 ? "rgba32f" : + op->type == SWS_PIXEL_U32 ? "rgba32ui" : + op->type == SWS_PIXEL_U16 ? "rgba16ui" : + "rgba8ui"; + buf_desc[nb_desc++] = (FFVulkanDescriptorSetBinding) { + .name = op->op == SWS_OP_WRITE ? "dst_img" : "src_img", + .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .mem_layout = img_type, + .mem_quali = op->op == SWS_OP_WRITE ? "writeonly" : "readonly", + .dimensions = 2, + .elems = (op->rw.packed ? 1 : op->rw.elems), + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + }; + if (op->op == SWS_OP_READ) + p->src_rep = op->type == SWS_PIXEL_F32 ? FF_VK_REP_FLOAT : + FF_VK_REP_UINT; + else + p->dst_rep = op->type == SWS_PIXEL_F32 ? FF_VK_REP_FLOAT : + FF_VK_REP_UINT; + } + } + + ff_vk_shader_add_descriptor_set(&s->vkctx, shd, buf_desc, nb_desc, 0, 0); + + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + GLSLC(1, ivec2 size = imageSize(src_img[0]); ); + GLSLC(1, if (any(greaterThanEqual(pos, size))) ); + GLSLC(2, return; ); + GLSLC(0, ); + GLSLC(1, u8vec4 u8; ); + GLSLC(1, u16vec4 u16; ); + GLSLC(1, u32vec4 u32; ); + GLSLC(1, f32vec4 f32; ); + GLSLC(0, ); + + const char *type_name = ff_sws_pixel_type_name(ops->ops[0].type); + for (int n = 0; n < ops->num_ops; n++) { + const SwsOp *op = &ops->ops[n]; + const char *type_v = op->type == SWS_PIXEL_F32 ? "f32vec4" : + op->type == SWS_PIXEL_U32 ? "u32vec4" : + op->type == SWS_PIXEL_U16 ? "u16vec4" : "u8vec4"; + const char *type_s = op->type == SWS_PIXEL_F32 ? "float" : + op->type == SWS_PIXEL_U32 ? "uint32_t" : + op->type == SWS_PIXEL_U16 ? "uint16_t" : "uint8_t"; + switch (op->op) { + case SWS_OP_READ: { + if (op->rw.packed) { + GLSLF(1, %s = %s(imageLoad(src_img[0], pos)); , + type_name, type_v); + } else { + for (int i = 0; i < (op->rw.packed ? 1 : op->rw.elems); i++) + GLSLF(1, %s.%c = %s(imageLoad(src_img[%i], pos)[0]); , + type_name, "xyzw"[i], type_s, i); + } + break; + } + case SWS_OP_WRITE: { + if (op->rw.packed) { + GLSLF(1, imageStore(dst_img[0], pos, %s(%s)); , + type_v, type_name); + } else { + for (int i = 0; i < (op->rw.packed ? 1 : op->rw.elems); i++) + GLSLF(1, imageStore(dst_img[%i], pos, %s(%s[%i])); , + i, type_v, type_name, i); + } + break; + } + case SWS_OP_SWIZZLE: { + av_bprintf(&shd->src, " %s = %s.", type_name, type_name); + for (int i = 0; i < 4; i++) + av_bprintf(&shd->src, "%c", "xyzw"[op->swizzle.in[i]]); + av_bprintf(&shd->src, ";\n"); + break; + } + case SWS_OP_CLEAR: { + for (int i = 0; i < 4; i++) { + if (!op->c.q4[i].den) + continue; + av_bprintf(&shd->src, " %s.%c = %s(%i/%i%s);\n", type_name, + "xyzw"[i], type_s, op->c.q4[i].num, op->c.q4[i].den, + op->type == SWS_PIXEL_F32 ? ".0f" : ""); + } + break; + } + default: + return AVERROR(ENOTSUP); + } + } + + GLSLC(0, } ); + + err = s->spvc->compile_shader(&s->vkctx, s->spvc, shd, + &spv_data, &spv_len, "main", + &spv_opaque); + if (err < 0) + return err; + + err = ff_vk_shader_link(&s->vkctx, shd, spv_data, spv_len, "main"); + + if (spv_opaque) + s->spvc->free_shader(s->spvc, &spv_opaque); + + if (err < 0) + return err; + + return 0; +} +#endif + static int compile(SwsContext *sws, SwsOpList *ops, SwsCompiledOp *out) { + int err; SwsInternal *c = sws_internal(sws); FFVulkanOpsCtx *s = c->hw_priv; if (!s) return AVERROR(ENOTSUP); VulkanPriv p = { - .s = c->hw_priv, + .s = s, }; +#if CONFIG_LIBSHADERC || CONFIG_LIBGLSLANG + { + err = add_ops_glsl(&p, s, ops, &p.shd); + if (err < 0) + return err; + } +#else + return AVERROR(ENOTSUP); +#endif + + err = ff_vk_shader_register_exec(&s->vkctx, &s->e, &p.shd); + if (err < 0) + return err; + *out = (SwsCompiledOp) { .slice_align = 0, .block_size = 1, diff --git a/libswscale/vulkan/ops.h b/libswscale/vulkan/ops.h index 55aaea12ed..73813bf4fa 100644 --- a/libswscale/vulkan/ops.h +++ b/libswscale/vulkan/ops.h @@ -24,10 +24,17 @@ #include "libavutil/vulkan.h" #include "../swscale.h" +#if CONFIG_LIBSHADERC || CONFIG_LIBGLSLANG +#include "libavutil/vulkan_spirv.h" +#endif + typedef struct FFVulkanOpsCtx { FFVulkanContext vkctx; AVVulkanDeviceQueueFamily *qf; FFVkExecPool e; +#if CONFIG_LIBSHADERC || CONFIG_LIBGLSLANG + FFVkSPIRVCompiler *spvc; +#endif } FFVulkanOpsCtx; int ff_sws_vk_init(SwsContext *sws, AVBufferRef *dev_ref); diff --git a/libavfilter/vulkan_glslang.c b/libswscale/vulkan/vulkan_glslang.c similarity index 100% copy from libavfilter/vulkan_glslang.c copy to libswscale/vulkan/vulkan_glslang.c diff --git a/libavfilter/vulkan_shaderc.c b/libswscale/vulkan/vulkan_shaderc.c similarity index 100% copy from libavfilter/vulkan_shaderc.c copy to libswscale/vulkan/vulkan_shaderc.c _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
