PR #22928 opened by Lynne URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22928 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22928.patch
Passes tests. Just curious about it. >From 11bf4bf480ed524b696823cbb964d1083694f0fe Mon Sep 17 00:00:00 2001 From: Lynne <[email protected]> Date: Sun, 26 Apr 2026 15:47:17 +0200 Subject: [PATCH 1/6] swscale/graph: support allocating hardware intermediate frames Sponsored-by: Sovereign Tech Fund --- libswscale/graph.c | 52 +++++++++++++++++++++++++++++++++++++++-- libswscale/vulkan/ops.c | 7 ++++++ libswscale/vulkan/ops.h | 6 +++++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/libswscale/graph.c b/libswscale/graph.c index 2020fcf8c7..3a9bf68d70 100644 --- a/libswscale/graph.c +++ b/libswscale/graph.c @@ -21,6 +21,7 @@ #include "libavutil/avassert.h" #include "libavutil/cpu.h" #include "libavutil/error.h" +#include "libavutil/hwcontext.h" #include "libavutil/imgutils.h" #include "libavutil/macros.h" #include "libavutil/mem.h" @@ -37,6 +38,9 @@ #include "swscale_internal.h" #include "graph.h" #include "ops.h" +#if CONFIG_VULKAN +#include "vulkan/ops.h" +#endif int ff_sws_pass_aligned_width(const SwsPass *pass, int width) { @@ -85,6 +89,31 @@ static int frame_alloc_planes(AVFrame *dst) return 0; } +#if CONFIG_VULKAN +static int pass_alloc_output_hw(SwsPass *pass, AVFrame *avframe, + AVBufferRef *dev_ref) +{ + SwsPassBuffer *buffer = pass->output; + AVBufferRef *frames_ref = av_hwframe_ctx_alloc(dev_ref); + if (!frames_ref) + return AVERROR(ENOMEM); + + AVHWFramesContext *hwfc = (AVHWFramesContext *)frames_ref->data; + hwfc->format = AV_PIX_FMT_VULKAN; + hwfc->sw_format = pass->format; + hwfc->width = buffer->width; + hwfc->height = buffer->height; + + int ret = av_hwframe_ctx_init(frames_ref); + if (ret >= 0) { + avframe->format = AV_PIX_FMT_VULKAN; + ret = av_hwframe_get_buffer(frames_ref, avframe, 0); + } + av_buffer_unref(&frames_ref); + return ret; +} +#endif + static int pass_alloc_output(SwsPass *pass) { if (!pass || pass->output->avframe) @@ -94,16 +123,35 @@ static int pass_alloc_output(SwsPass *pass) AVFrame *avframe = av_frame_alloc(); if (!avframe) return AVERROR(ENOMEM); - avframe->format = pass->format; avframe->width = buffer->width; avframe->height = buffer->height; - int ret = frame_alloc_planes(avframe); + int ret; + +#if CONFIG_VULKAN + const SwsGraph *graph = pass->graph; + if (graph->src.hw_format == AV_PIX_FMT_VULKAN && + graph->dst.hw_format == AV_PIX_FMT_VULKAN) { + AVBufferRef *dev_ref = ff_sws_vk_device_ref(graph->ctx); + if (dev_ref) { + ret = pass_alloc_output_hw(pass, avframe, dev_ref); + if (ret >= 0) + goto done; + av_frame_unref(avframe); + } + } +#endif + + avframe->format = pass->format; + ret = frame_alloc_planes(avframe); if (ret < 0) { av_frame_free(&avframe); return ret; } +#if CONFIG_VULKAN +done: +#endif buffer->avframe = avframe; ff_sws_frame_from_avframe(&buffer->frame, avframe); return 0; diff --git a/libswscale/vulkan/ops.c b/libswscale/vulkan/ops.c index cf128b00c1..f06352883b 100644 --- a/libswscale/vulkan/ops.c +++ b/libswscale/vulkan/ops.c @@ -82,6 +82,13 @@ int ff_sws_vk_init(SwsContext *sws, AVBufferRef *dev_ref) return 0; } +AVBufferRef *ff_sws_vk_device_ref(SwsContext *sws) +{ + SwsInternal *c = sws_internal(sws); + FFVulkanOpsCtx *s = c->hw_priv; + return s ? s->vkctx.device_ref : NULL; +} + #define MAX_DITHER_BUFS 4 typedef struct VulkanPriv { diff --git a/libswscale/vulkan/ops.h b/libswscale/vulkan/ops.h index 0421dba446..6c9ae6c7fd 100644 --- a/libswscale/vulkan/ops.h +++ b/libswscale/vulkan/ops.h @@ -38,4 +38,10 @@ typedef struct FFVulkanOpsCtx { int ff_sws_vk_init(SwsContext *sws, AVBufferRef *dev_ref); +/** + * Returns the Vulkan device reference associated with `sws`, or NULL if + * Vulkan has not been initialized for this context. + */ +AVBufferRef *ff_sws_vk_device_ref(SwsContext *sws); + #endif /* SWSCALE_VULKAN_OPS_H */ -- 2.52.0 >From 332ba56e4eed967530015c88324e59b054672393 Mon Sep 17 00:00:00 2001 From: Lynne <[email protected]> Date: Sun, 26 Apr 2026 12:23:03 +0200 Subject: [PATCH 2/6] swscale/vulkan: base dispatch size on output image size, rather than input Sponsored-by: Sovereign Tech Fund --- libswscale/vulkan/ops.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libswscale/vulkan/ops.c b/libswscale/vulkan/ops.c index f06352883b..5ef4667051 100644 --- a/libswscale/vulkan/ops.c +++ b/libswscale/vulkan/ops.c @@ -151,8 +151,8 @@ static void process(const SwsFrame *dst, const SwsFrame *src, int y, int h, 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], + FFALIGN(dst_f->width, p->shd.lg_size[0])/p->shd.lg_size[0], + FFALIGN(dst_f->height, p->shd.lg_size[1])/p->shd.lg_size[1], 1); ff_vk_exec_submit(&p->s->vkctx, ec); @@ -985,7 +985,7 @@ static int add_ops_glsl(VulkanPriv *p, FFVulkanOpsCtx *s, GLSLC(0, void main() ); GLSLC(0, { ); GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); - GLSLC(1, ivec2 size = imageSize(src_img[0]); ); + GLSLC(1, ivec2 size = imageSize(dst_img[0]); ); GLSLC(1, if (any(greaterThanEqual(pos, size))) ); GLSLC(2, return; ); GLSLC(0, ); -- 2.52.0 >From 2a595cb254a06a816523940b252341f6fdcda2ea Mon Sep 17 00:00:00 2001 From: Lynne <[email protected]> Date: Sun, 26 Apr 2026 12:21:09 +0200 Subject: [PATCH 3/6] swscale/vulkan: make dither buffer allocation path generic Just a simple rename. Sponsored-by: Sovereign Tech Fund --- libswscale/vulkan/ops.c | 99 ++++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 42 deletions(-) diff --git a/libswscale/vulkan/ops.c b/libswscale/vulkan/ops.c index 5ef4667051..2a0cd78530 100644 --- a/libswscale/vulkan/ops.c +++ b/libswscale/vulkan/ops.c @@ -90,13 +90,14 @@ AVBufferRef *ff_sws_vk_device_ref(SwsContext *sws) } #define MAX_DITHER_BUFS 4 +#define MAX_DATA_BUFS (MAX_DITHER_BUFS) typedef struct VulkanPriv { FFVulkanOpsCtx *s; FFVkExecPool e; FFVulkanShader shd; - FFVkBuffer dither_buf[MAX_DITHER_BUFS]; - int nb_dither_buf; + FFVkBuffer data_bufs[MAX_DATA_BUFS]; + int nb_data_bufs; enum FFVkShaderRepFormat src_rep; enum FFVkShaderRepFormat dst_rep; } VulkanPriv; @@ -164,54 +165,68 @@ static void free_fn(void *priv) VulkanPriv *p = priv; ff_vk_exec_pool_free(&p->s->vkctx, &p->e); ff_vk_shader_free(&p->s->vkctx, &p->shd); - for (int i = 0; i < p->nb_dither_buf; i++) - ff_vk_free_buf(&p->s->vkctx, &p->dither_buf[i]); + for (int i = 0; i < p->nb_data_bufs; i++) + ff_vk_free_buf(&p->s->vkctx, &p->data_bufs[i]); av_refstruct_unref(&p->s); av_free(priv); } -static int create_dither_bufs(FFVulkanOpsCtx *s, VulkanPriv *p, SwsOpList *ops) +static int create_dither_buf(FFVulkanOpsCtx *s, VulkanPriv *p, + const SwsDitherOp *dd, FFVkBuffer *buf) { int err; - p->nb_dither_buf = 0; + + int size = (1 << dd->size_log2); + err = ff_vk_create_buf(&s->vkctx, buf, + size*size*sizeof(float), NULL, NULL, + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); + if (err < 0) + return err; + + float *dither_data; + err = ff_vk_map_buffer(&s->vkctx, buf, (uint8_t **)&dither_data, 0); + if (err < 0) + goto fail; + + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + const AVRational r = dd->matrix[i*size + j]; + dither_data[i*size + j] = r.num/(float)r.den; + } + } + + ff_vk_unmap_buffer(&s->vkctx, buf, 1); + + return 0; + +fail: + ff_vk_free_buf(&p->s->vkctx, buf); + return err; +} + +static int create_bufs(FFVulkanOpsCtx *s, VulkanPriv *p, SwsOpList *ops) +{ + int err; + p->nb_data_bufs = 0; for (int n = 0; n < ops->num_ops; n++) { const SwsOp *op = &ops->ops[n]; - if (op->op != SWS_OP_DITHER) - continue; - av_assert0(p->nb_dither_buf + 1 <= MAX_DITHER_BUFS); - - int size = (1 << op->dither.size_log2); - int idx = p->nb_dither_buf; - err = ff_vk_create_buf(&s->vkctx, &p->dither_buf[idx], - size*size*sizeof(float), NULL, NULL, - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - if (err < 0) - goto fail; - p->nb_dither_buf++; - - float *dither_data; - err = ff_vk_map_buffer(&s->vkctx, &p->dither_buf[idx], - (uint8_t **)&dither_data, 0); - if (err < 0) - goto fail; - - for (int i = 0; i < size; i++) { - for (int j = 0; j < size; j++) { - const AVRational r = op->dither.matrix[i*size + j]; - dither_data[i*size + j] = r.num/(float)r.den; - } + if (op->op == SWS_OP_DITHER) { + av_assert0(p->nb_data_bufs + 1 <= FF_ARRAY_ELEMS(p->data_bufs)); + err = create_dither_buf(s, p, &op->dither, + &p->data_bufs[p->nb_data_bufs]); + if (err < 0) + goto fail; + p->nb_data_bufs++; } - - ff_vk_unmap_buffer(&s->vkctx, &p->dither_buf[idx], 1); } return 0; fail: - for (int i = 0; i < p->nb_dither_buf; i++) - ff_vk_free_buf(&p->s->vkctx, &p->dither_buf[i]); + for (int i = 0; i < p->nb_data_bufs; i++) + ff_vk_free_buf(&p->s->vkctx, &p->data_bufs[i]); return err; } @@ -227,7 +242,7 @@ struct DitherData { }; typedef struct SPIRVIDs { - int in_vars[3 + MAX_DITHER_BUFS]; + int in_vars[3 + MAX_DATA_BUFS]; int glfn; int ep; @@ -598,7 +613,7 @@ static int add_ops_spirv(VulkanPriv *p, FFVulkanOpsCtx *s, if (op_r) p->src_rep = op_r->type == SWS_PIXEL_F32 ? FF_VK_REP_FLOAT : FF_VK_REP_UINT; - FFVulkanDescriptorSetBinding desc_set[MAX_DITHER_BUFS] = { + FFVulkanDescriptorSetBinding desc_set[MAX_DATA_BUFS] = { { .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, .stages = VK_SHADER_STAGE_COMPUTE_BIT, @@ -613,7 +628,7 @@ static int add_ops_spirv(VulkanPriv *p, FFVulkanOpsCtx *s, ff_vk_shader_add_descriptor_set(&s->vkctx, shd, desc_set, 2, 0, 0); /* Create dither buffers */ - int err = create_dither_bufs(s, p, ops); + int err = create_bufs(s, p, ops); if (err < 0) return err; @@ -953,7 +968,7 @@ static int add_ops_glsl(VulkanPriv *p, FFVulkanOpsCtx *s, add_desc_read_write(&buf_desc[nb_desc++], &p->dst_rep, write); ff_vk_shader_add_descriptor_set(&s->vkctx, shd, buf_desc, nb_desc, 0, 0); - err = create_dither_bufs(s, p, ops); + err = create_bufs(s, p, ops); if (err < 0) return err; @@ -1191,9 +1206,9 @@ static int compile(SwsContext *sws, SwsOpList *ops, SwsCompiledOp *out, int glsl if (err < 0) goto fail; - for (int i = 0; i < p->nb_dither_buf; i++) + for (int i = 0; i < p->nb_data_bufs; i++) ff_vk_shader_update_desc_buffer(&s->vkctx, &p->e.contexts[0], &p->shd, - 1, i, 0, &p->dither_buf[i], + 1, i, 0, &p->data_bufs[i], 0, VK_WHOLE_SIZE, VK_FORMAT_UNDEFINED); *out = (SwsCompiledOp) { -- 2.52.0 >From 7abac315b0a8df466c785cb9ec7216d3e59cff0e Mon Sep 17 00:00:00 2001 From: Lynne <[email protected]> Date: Sun, 26 Apr 2026 12:26:04 +0200 Subject: [PATCH 4/6] swscale/vulkan: make buffer descriptor generation generic Again, simple rename. Sponsored-by: Sovereign Tech Fund --- libswscale/vulkan/ops.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/libswscale/vulkan/ops.c b/libswscale/vulkan/ops.c index 2a0cd78530..4c2301a192 100644 --- a/libswscale/vulkan/ops.c +++ b/libswscale/vulkan/ops.c @@ -973,25 +973,25 @@ static int add_ops_glsl(VulkanPriv *p, FFVulkanOpsCtx *s, return err; nb_desc = 0; - char dither_buf_name[MAX_DITHER_BUFS][64]; - char dither_mat_name[MAX_DITHER_BUFS][64]; + char data_buf_name[MAX_DATA_BUFS][256]; + char data_str_name[MAX_DATA_BUFS][256]; for (int n = 0; n < ops->num_ops; n++) { const SwsOp *op = &ops->ops[n]; - if (op->op != SWS_OP_DITHER) - continue; - int size = (1 << op->dither.size_log2); - av_assert0(size < 8192); - snprintf(dither_buf_name[nb_desc], 64, "dither_buf%i", n); - snprintf(dither_mat_name[nb_desc], 64, "float dither_mat%i[%i][%i];", - n, size, size); - buf_desc[nb_desc] = (FFVulkanDescriptorSetBinding) { - .name = dither_buf_name[nb_desc], - .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .stages = VK_SHADER_STAGE_COMPUTE_BIT, - .mem_layout = "scalar", - .buf_content = dither_mat_name[nb_desc], - }; - nb_desc++; + if (op->op == SWS_OP_DITHER) { + int size = (1 << op->dither.size_log2); + av_assert0(size < 8192); + snprintf(data_buf_name[nb_desc], 256, "dither_buf%i", n); + snprintf(data_str_name[nb_desc], 256, "float dither_mat%i[%i][%i];", + n, size, size); + buf_desc[nb_desc] = (FFVulkanDescriptorSetBinding) { + .name = data_buf_name[nb_desc], + .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .mem_layout = "scalar", + .buf_content = data_str_name[nb_desc], + }; + nb_desc++; + } } if (nb_desc) ff_vk_shader_add_descriptor_set(&s->vkctx, shd, buf_desc, -- 2.52.0 >From e205c9f7e9653bf3ae6c065ad6d7e62f59164d1a Mon Sep 17 00:00:00 2001 From: Lynne <[email protected]> Date: Sun, 26 Apr 2026 12:22:04 +0200 Subject: [PATCH 5/6] swscale/vulkan: allocate buffers for scaling filters Simply allocates buffers to hold filter data. Sponsored-by: Sovereign Tech Fund --- libswscale/vulkan/ops.c | 73 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/libswscale/vulkan/ops.c b/libswscale/vulkan/ops.c index 4c2301a192..ee16457752 100644 --- a/libswscale/vulkan/ops.c +++ b/libswscale/vulkan/ops.c @@ -90,7 +90,8 @@ AVBufferRef *ff_sws_vk_device_ref(SwsContext *sws) } #define MAX_DITHER_BUFS 4 -#define MAX_DATA_BUFS (MAX_DITHER_BUFS) +#define MAX_FILT_BUFS 4 +#define MAX_DATA_BUFS (MAX_DITHER_BUFS + MAX_FILT_BUFS*4) typedef struct VulkanPriv { FFVulkanOpsCtx *s; @@ -171,6 +172,41 @@ static void free_fn(void *priv) av_free(priv); } +static int create_filter_buf(FFVulkanOpsCtx *s, VulkanPriv *p, + const SwsFilterWeights *wd, FFVkBuffer *buf) +{ + int err; + + /* Weights */ + err = ff_vk_create_buf(&s->vkctx, buf, + wd->num_weights*sizeof(float) + + wd->dst_size*sizeof(int32_t), NULL, NULL, + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); + if (err < 0) + goto fail; + + float *weights_data; + err = ff_vk_map_buffer(&s->vkctx, buf, + (uint8_t **)&weights_data, 0); + if (err < 0) + goto fail; + for (int i = 0; i < wd->num_weights; i++) + weights_data[i] = (float) wd->weights[i] / SWS_FILTER_SCALE; + + memcpy(weights_data + wd->num_weights, + wd->offsets, wd->dst_size*sizeof(int32_t)); + + ff_vk_unmap_buffer(&s->vkctx, buf, 1); + + return 0; + +fail: + ff_vk_free_buf(&p->s->vkctx, buf); + return 0; +} + static int create_dither_buf(FFVulkanOpsCtx *s, VulkanPriv *p, const SwsDitherOp *dd, FFVkBuffer *buf) { @@ -219,6 +255,21 @@ static int create_bufs(FFVulkanOpsCtx *s, VulkanPriv *p, SwsOpList *ops) if (err < 0) goto fail; p->nb_data_bufs++; + } else if (op->op == SWS_OP_FILTER_H || op->op == SWS_OP_FILTER_V) { + av_assert0(p->nb_data_bufs + 1 <= FF_ARRAY_ELEMS(p->data_bufs)); + err = create_filter_buf(s, p, op->filter.kernel, + &p->data_bufs[p->nb_data_bufs]); + if (err < 0) + goto fail; + p->nb_data_bufs++; + } else if ((op->op == SWS_OP_READ || + op->op == SWS_OP_WRITE) && op->rw.filter) { + av_assert0(p->nb_data_bufs + 1 <= FF_ARRAY_ELEMS(p->data_bufs)); + err = create_filter_buf(s, p, op->rw.kernel, + &p->data_bufs[p->nb_data_bufs]); + if (err < 0) + goto fail; + p->nb_data_bufs++; } } @@ -991,6 +1042,26 @@ static int add_ops_glsl(VulkanPriv *p, FFVulkanOpsCtx *s, .buf_content = data_str_name[nb_desc], }; nb_desc++; + } else if (op->op == SWS_OP_FILTER_H || op->op == SWS_OP_FILTER_V || + ((op->op == SWS_OP_READ || op->op == SWS_OP_WRITE) && + op->rw.filter)) { + const SwsFilterWeights *wd = (op->op == SWS_OP_READ || + op->op == SWS_OP_WRITE) ? + op->rw.kernel : op->filter.kernel; + snprintf(data_buf_name[nb_desc], 256, "filter_buf%i", n); + snprintf(data_str_name[nb_desc], 256, + "float filter_w%i[%i][%i];\n" + " int filter_o%i[%i];", + n, wd->dst_size, wd->filter_size, + n, wd->dst_size); + buf_desc[nb_desc] = (FFVulkanDescriptorSetBinding) { + .name = data_buf_name[nb_desc], + .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .mem_layout = "scalar", + .buf_content = data_str_name[nb_desc], + }; + nb_desc++; } } if (nb_desc) -- 2.52.0 >From 1137c848872123ea24e41258ec676b9c908cdcab Mon Sep 17 00:00:00 2001 From: Lynne <[email protected]> Date: Sun, 26 Apr 2026 12:54:05 +0200 Subject: [PATCH 6/6] swscale/vulkan: add support for filtering on SWS_OP_READ Sponsored-by: Sovereign Tech Fund --- libswscale/vulkan/ops.c | 49 +++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/libswscale/vulkan/ops.c b/libswscale/vulkan/ops.c index ee16457752..3fd7b0b2b8 100644 --- a/libswscale/vulkan/ops.c +++ b/libswscale/vulkan/ops.c @@ -991,6 +991,44 @@ static void add_desc_read_write(FFVulkanDescriptorSetBinding *out_desc, #define QSTR "(%i/%i%s)" #define QTYPE(Q) (Q).num, (Q).den, cur_type == SWS_PIXEL_F32 ? ".0f" : "" +static void read_glsl(SwsOpList *ops, const SwsOp *op, FFVulkanShader *shd, + int idx, const char *type_name, + const char *type_v, const char *type_s) +{ + const SwsFilterWeights *wd = op->rw.kernel; + if (op->rw.filter) { + const char *axis = op->rw.filter == SWS_OP_FILTER_H ? "pos.x" : "pos.y"; + const char *coord_x = op->rw.filter == SWS_OP_FILTER_H ? "o + i" : "pos.x"; + const char *coord_y = op->rw.filter == SWS_OP_FILTER_H ? "pos.y" : "o + i"; + GLSLC(1, tmp = vec4(0); ); + av_bprintf(&shd->src, " int o = filter_o%i[%s];\n", idx, axis); + av_bprintf(&shd->src, " for (int i = 0; i < %i; i++) {\n", + wd->filter_size); + av_bprintf(&shd->src, " float w = filter_w%i[%s][i];\n", + idx, axis); + if (op->rw.packed) { + GLSLF(2, tmp += w * %s(imageLoad(src_img[%i], ivec2(%s, %s))); , + type_v, ops->plane_src[0], coord_x, coord_y); + } else { + for (int i = 0; i < op->rw.elems; i++) + GLSLF(2, + tmp.%c += w * %s(imageLoad(src_img[%i], ivec2(%s, %s))[0]); , + "xyzw"[i], type_s, ops->plane_src[i], coord_x, coord_y); + } + GLSLC(1, } ); + GLSLC(1, f32 = tmp; ); + } else { + if (op->rw.packed) { + GLSLF(1, %s = %s(imageLoad(src_img[%i], pos)); , + type_name, type_v, ops->plane_src[0]); + } else { + for (int i = 0; i < op->rw.elems; i++) + GLSLF(1, %s.%c = %s(imageLoad(src_img[%i], pos)[0]); , + type_name, "xyzw"[i], type_s, ops->plane_src[i]); + } + } +} + static int add_ops_glsl(VulkanPriv *p, FFVulkanOpsCtx *s, SwsOpList *ops, FFVulkanShader *shd) { @@ -1097,16 +1135,9 @@ static int add_ops_glsl(VulkanPriv *p, FFVulkanOpsCtx *s, switch (op->op) { case SWS_OP_READ: { - if (op->rw.frac || op->rw.filter) { + if (op->rw.frac) return AVERROR(ENOTSUP); - } else if (op->rw.packed) { - GLSLF(1, %s = %s(imageLoad(src_img[%i], pos)); , - type_name, type_v, ops->plane_src[0]); - } else { - for (int i = 0; i < op->rw.elems; i++) - GLSLF(1, %s.%c = %s(imageLoad(src_img[%i], pos)[0]); , - type_name, "xyzw"[i], type_s, ops->plane_src[i]); - } + read_glsl(ops, op, shd, n, type_name, type_v, type_s); break; } case SWS_OP_WRITE: { -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
