Commit 12bd74dcd5 for ffmpeg

commit 12bd74dcd508af124553116baa9aa2e8dc86bd29
Author: Niklas Haas <git@haasn.dev>
Date:   Wed Oct 21 23:25:33 2026 +0200

    swscale/vulkan/ops: support linear ops on integers

    Matrix instructions are only defined for floats, so evaluate integer
    matrices row by row using the typed arithmetic helpers, as is already
    done in bit-exact mode. This allows e.g. yuva444p -> yuva444p16le, which
    expands the components using an integer linear op.

    As required by SwsLinearOp, U8 and U16 results are reduced modulo their
    bit depth.

    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 1478073645..5492a9390e 100644
--- a/libswscale/vulkan/ops.c
+++ b/libswscale/vulkan/ops.c
@@ -382,6 +382,12 @@ static void define_pack_consts(SPICtx *spi, const SPIRVIDs *id, const SwsOp *op,
 }

 /* Arithmetic on operands of the given pixel type */
+static int emit_add(SPICtx *spi, SwsPixelType type, int res_type, int a, int b)
+{
+    return ff_sws_pixel_type_is_int(type) ? spi_OpIAdd(spi, res_type, a, b)
+                                          : spi_OpFAdd(spi, res_type, a, b);
+}
+
 static int emit_mul(SPICtx *spi, SwsPixelType type, int res_type, int a, int b)
 {
     return ff_sws_pixel_type_is_int(type) ? spi_OpIMul(spi, res_type, a, b)
@@ -601,10 +607,10 @@ static int insert_bitexact_linear(const SwsOp *op, SPICtx *spi, SPIRVIDs *id,
                 continue;

             int k = const_pixel(spi, id, op_type, op->lin.m[j][i]);
-            int v = spi_OpFMul(spi, type_s, tmp[i], k);
+            int v = emit_mul(spi, op_type, type_s, tmp[i], k);
             spi_OpDecorate(spi, v, SpvDecorationNoContraction);
             if (acc) {
-                v = spi_OpFAdd(spi, type_s, res[j], v);
+                v = emit_add(spi, op_type, type_s, res[j], v);
                 spi_OpDecorate(spi, v, SpvDecorationNoContraction);
             }
             res[j] = v;
@@ -612,8 +618,16 @@ static int insert_bitexact_linear(const SwsOp *op, SPICtx *spi, SPIRVIDs *id,
         }
     }

-    return spi_OpCompositeConstruct(spi, type_v,
-                                    res[0], res[1], res[2], res[3]);
+    int result = spi_OpCompositeConstruct(spi, type_v,
+                                          res[0], res[1], res[2], res[3]);
+
+    /* Integer results are defined modulo the bit depth of the pixel type */
+    if (op_type == SWS_PIXEL_U8 || op_type == SWS_PIXEL_U16) {
+        const unsigned mask = op_type == SWS_PIXEL_U8 ? UINT8_MAX : UINT16_MAX;
+        result = spi_OpBitwiseAnd(spi, type_v, result,
+                                  const_splat(spi, id, op_type, Q(mask)));
+    }
+    return result;
 }

 /* Registers the last created buffer in descriptor set 1, returns its binding */
@@ -920,9 +934,9 @@ static int emit_dither(SPICtx *spi, SPIRVIDs *id, const SwsOp *op, int *data)

 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)
+    /* Matrix operations are only defined for floats */
+    const SwsPixelType type = ff_sws_op_input_type(op);
+    if (id->bitexact || ff_sws_pixel_type_is_int(type))
         *data = insert_bitexact_linear(op, spi, id, *data);
     else
         *data = insert_vmat_linear(op, spi, id, *data);