Commit a10c52b5cd for ffmpeg

commit a10c52b5cd34d81ad5dcb1cb4ac8f55967d1968a
Author: Niklas Haas <git@haasn.dev>
Date:   Wed Oct 21 18:34:25 2026 +0200

    swscale/vulkan/ops: move larger op implementations into functions

    Keeps the main switch/case small. The bit-exact flag is kept in SPIRVIDs,
    so that all of these share the same signature.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Signed-off-by: Niklas Haas <git@haasn.dev>

diff --git a/libswscale/vulkan/ops.c b/libswscale/vulkan/ops.c
index f805f32e7f..32c3556a4a 100644
--- a/libswscale/vulkan/ops.c
+++ b/libswscale/vulkan/ops.c
@@ -322,6 +322,7 @@ typedef struct SPIRVIDs {
     VulkanPriv *priv;
     FFVulkanDescriptorSetBinding buf_desc[MAX_DATA_BUFS]; /* set 1 */
     const SwsOpList *ops;
+    int bitexact;

     /* Per-invocation state of the main function */
     int in_img[4], out_img[4];  /* image handles, indexed by plane */
@@ -777,6 +778,86 @@ static int rw_op_img_count(const SwsOp *op, const uint8_t *planes)
     return count;
 }

+static int emit_read(SPICtx *spi, SPIRVIDs *id, const SwsOp *op, int *data)
+{
+    const SwsOpList *ops = id->ops;
+    const SwsPixelType type = ff_sws_op_output_type(op);
+    const int type_v = type_vec4(id, type);
+    const int type_s = type_scalar(id, type);
+    const int zero = const_zero(id, type);
+
+    if (op->rw.frac) {
+        return AVERROR(ENOTSUP);
+    } else if (op->rw.filter.op) {
+        if (op->rw.mode != SWS_RW_PLANAR ||
+            op->rw.filter.type != SWS_PIXEL_F32)
+            return AVERROR(ENOTSUP);
+        return emit_read_filtered(spi, id, op, data);
+    } else if (op->rw.mode == SWS_RW_PACKED) {
+        *data = spi_OpImageRead(spi, type_v, id->in_img[ops->plane_src[0]],
+                                id->src_gid, SpvImageOperandsMaskNone);
+    } else if (op->rw.mode == SWS_RW_PLANAR) {
+        int tmp[4] = { zero, zero, zero, zero };
+        for (int i = 0; i < op->rw.elems; i++) {
+            tmp[i] = spi_OpImageRead(spi, type_v,
+                                     id->in_img[ops->plane_src[i]], id->src_gid,
+                                     SpvImageOperandsMaskNone);
+            tmp[i] = spi_OpCompositeExtract(spi, type_s, tmp[i], 0);
+        }
+        *data = spi_OpCompositeConstruct(spi, type_v,
+                                         tmp[0], tmp[1], tmp[2], tmp[3]);
+    } else {
+        return AVERROR(ENOTSUP);
+    }
+
+    return 0;
+}
+
+static int emit_write(SPICtx *spi, SPIRVIDs *id, const SwsOp *op, int *data)
+{
+    const SwsOpList *ops = id->ops;
+    const SwsPixelType type = ff_sws_op_input_type(op);
+    const int type_v = type_vec4(id, type);
+    const int type_s = type_scalar(id, type);
+
+    if (op->rw.frac || op->rw.filter.op) {
+        return AVERROR(ENOTSUP);
+    } else if (op->rw.mode == SWS_RW_PACKED) {
+        spi_OpImageWrite(spi, id->out_img[ops->plane_dst[0]], id->dst_gid, *data,
+                         SpvImageOperandsMaskNone);
+    } else {
+        for (int i = 0; i < op->rw.elems; i++) {
+            int tmp = spi_OpCompositeExtract(spi, type_s, *data, i);
+            tmp = spi_OpCompositeConstruct(spi, type_v, tmp, tmp, tmp, tmp);
+            spi_OpImageWrite(spi, id->out_img[ops->plane_dst[i]], id->dst_gid, tmp,
+                             SpvImageOperandsMaskNone);
+        }
+    }
+
+    return 0;
+}
+
+static int emit_clamp(SPICtx *spi, SPIRVIDs *id, const SwsOp *op, int *data)
+{
+    const SwsPixelType type = ff_sws_op_input_type(op);
+    const int type_v = type_vec4(id, type);
+    const int type_s = type_scalar(id, type);
+
+    for (int i = 0; i < 4; i++) {
+        if (!op->clamp.limit[i].den)
+            continue;
+        int lim = const_pixel(spi, id, type, op->clamp.limit[i]);
+        int tmp = spi_OpCompositeExtract(spi, type_s, *data, i);
+        if (op->op == SWS_OP_MIN)
+            tmp = emit_min(spi, id, type, type_s, tmp, lim);
+        else
+            tmp = emit_max(spi, id, type, type_s, tmp, lim);
+        *data = spi_OpCompositeInsert(spi, type_v, tmp, *data, i);
+    }
+
+    return 0;
+}
+
 static int emit_dither(SPICtx *spi, SPIRVIDs *id, const SwsOp *op, int *data)
 {
     if (ff_sws_op_input_type(op) != SWS_PIXEL_F32)
@@ -837,12 +918,42 @@ static int emit_dither(SPICtx *spi, SPIRVIDs *id, const SwsOp *op, int *data)
     return 0;
 }

+static int emit_linear(SPICtx *spi, SPIRVIDs *id, const SwsOp *op, int *data)
+{
+    if (ff_sws_op_input_type(op) != SWS_PIXEL_F32)
+        return AVERROR(ENOTSUP);
+    if (id->bitexact)
+        *data = insert_bitexact_linear(op, spi, id, *data);
+    else
+        *data = insert_vmat_linear(op, spi, id, *data);
+    return 0;
+}
+
+static int emit_pack(SPICtx *spi, SPIRVIDs *id, const SwsOp *op, int *data)
+{
+    const int type_v = id->u32vec4_type;
+    const int type_s = id->u32_type;
+
+    int shift, mask;
+    define_pack_consts(spi, id, op, &shift, &mask);
+    *data = spi_OpBitwiseAnd(spi, type_v, *data, mask);
+    *data = spi_OpShiftLeftLogical(spi, type_v, *data, shift);
+    int val = spi_OpCompositeExtract(spi, type_s, *data, 0);
+    for (int i = 1; i < 4; i++) {
+        int tmp = spi_OpCompositeExtract(spi, type_s, *data, i);
+        val = spi_OpBitwiseOr(spi, type_s, val, tmp);
+    }
+    *data = spi_OpCompositeConstruct(spi, type_v, val, val, val, val);
+    return 0;
+}
+
 static int emit_shader(SwsContext *sws, VulkanPriv *p, FFVulkanOpsCtx *s,
                        const SwsOpList *ops, FFVulkanShader *shd, SPICtx *spi)
 {
     SPIRVIDs spid_data = { 0 }, *id = &spid_data;
     id->priv = p;
     id->ops = ops;
+    id->bitexact = !!(sws->flags & SWS_BITEXACT);

     if (ops->num_ops > MAX_OPS)
         return AVERROR(ENOTSUP);
@@ -984,51 +1095,13 @@ static int emit_shader(SwsContext *sws, VulkanPriv *p, FFVulkanOpsCtx *s,
         if (op->op == SWS_OP_WRITE)
             type_out = type_in;
         int type_v = type_vec4(id, type_out);
-        int type_s = type_scalar(id, type_out);
-        int uid = const_zero(id, type_out);

         switch (op->op) {
         case SWS_OP_READ:
-            if (op->rw.frac) {
-                return AVERROR(ENOTSUP);
-            } else if (op->rw.filter.op) {
-                if (op->rw.mode != SWS_RW_PLANAR ||
-                    op->rw.filter.type != SWS_PIXEL_F32)
-                    return AVERROR(ENOTSUP);
-                err = emit_read_filtered(spi, id, op, &data);
-                if (err < 0)
-                    return err;
-            } else if (op->rw.mode == SWS_RW_PACKED) {
-                data = spi_OpImageRead(spi, type_v, id->in_img[ops->plane_src[0]],
-                                       id->src_gid, SpvImageOperandsMaskNone);
-            } else if (op->rw.mode == SWS_RW_PLANAR) {
-                int tmp[4] = { uid, uid, uid, uid };
-                for (int i = 0; i < op->rw.elems; i++) {
-                    tmp[i] = spi_OpImageRead(spi, type_v,
-                                             id->in_img[ops->plane_src[i]], id->src_gid,
-                                             SpvImageOperandsMaskNone);
-                    tmp[i] = spi_OpCompositeExtract(spi, type_s, tmp[i], 0);
-                }
-                data = spi_OpCompositeConstruct(spi, type_v,
-                                                tmp[0], tmp[1], tmp[2], tmp[3]);
-            } else {
-                return AVERROR(ENOTSUP);
-            }
+            err = emit_read(spi, id, op, &data);
             break;
         case SWS_OP_WRITE:
-            if (op->rw.frac || op->rw.filter.op) {
-                return AVERROR(ENOTSUP);
-            } else if (op->rw.mode == SWS_RW_PACKED) {
-                spi_OpImageWrite(spi, id->out_img[ops->plane_dst[0]], id->dst_gid, data,
-                                 SpvImageOperandsMaskNone);
-            } else {
-                for (int i = 0; i < op->rw.elems; i++) {
-                    int tmp = spi_OpCompositeExtract(spi, type_s, data, i);
-                    tmp = spi_OpCompositeConstruct(spi, type_v, tmp, tmp, tmp, tmp);
-                    spi_OpImageWrite(spi, id->out_img[ops->plane_dst[i]], id->dst_gid, tmp,
-                                     SpvImageOperandsMaskNone);
-                }
-            }
+            err = emit_write(spi, id, op, &data);
             break;
         case SWS_OP_CLEAR:
             for (int i = 0; i < 4; i++) {
@@ -1065,32 +1138,14 @@ static int emit_shader(SwsContext *sws, VulkanPriv *p, FFVulkanOpsCtx *s,
             break;
         case SWS_OP_MIN:
         case SWS_OP_MAX:
-            for (int i = 0; i < 4; i++) {
-                if (!op->clamp.limit[i].den)
-                    continue;
-                int lim = const_pixel(spi, id, type_in, op->clamp.limit[i]);
-                int tmp = spi_OpCompositeExtract(spi, type_s, data, i);
-                if (op->op == SWS_OP_MIN)
-                    tmp = emit_min(spi, id, type_in, type_s, tmp, lim);
-                else
-                    tmp = emit_max(spi, id, type_in, type_s, tmp, lim);
-                data = spi_OpCompositeInsert(spi, type_v, tmp, data, i);
-            }
+            err = emit_clamp(spi, id, op, &data);
             break;
         case SWS_OP_DITHER:
             err = emit_dither(spi, id, op, &data);
-            if (err < 0)
-                return err;
             break;
-        case SWS_OP_LINEAR: {
-            if (type_in != SWS_PIXEL_F32)
-                return AVERROR(ENOTSUP);
-            if (sws->flags & SWS_BITEXACT)
-                data = insert_bitexact_linear(op, spi, id, data);
-            else
-                data = insert_vmat_linear(op, spi, id, data);
+        case SWS_OP_LINEAR:
+            err = emit_linear(spi, id, op, &data);
             break;
-        }
         case SWS_OP_UNPACK: {
             int shift, mask;
             define_pack_consts(spi, id, op, &shift, &mask);
@@ -1099,22 +1154,15 @@ static int emit_shader(SwsContext *sws, VulkanPriv *p, FFVulkanOpsCtx *s,
             data = spi_OpBitwiseAnd(spi, type_v, data, mask);
             break;
         }
-        case SWS_OP_PACK: {
-            int shift, mask;
-            define_pack_consts(spi, id, op, &shift, &mask);
-            data = spi_OpBitwiseAnd(spi, type_v, data, mask);
-            data = spi_OpShiftLeftLogical(spi, type_v, data, shift);
-            int val = spi_OpCompositeExtract(spi, type_s, data, 0);
-            for (int i = 1; i < 4; i++) {
-                int tmp = spi_OpCompositeExtract(spi, type_s, data, i);
-                val = spi_OpBitwiseOr(spi, type_s, val, tmp);
-            }
-            data = spi_OpCompositeConstruct(spi, type_v, val, val, val, val);
+        case SWS_OP_PACK:
+            err = emit_pack(spi, id, op, &data);
             break;
-        }
         default:
             return AVERROR(ENOTSUP);
         }
+
+        if (err < 0)
+            return err;
     }

     /* Return and finalize */