Commit bba7e80f08 for ffmpeg
commit bba7e80f08210bbaef0a2607960c9374c88b6fd3
Author: Niklas Haas <git@haasn.dev>
Date: Tue Oct 20 23:47:50 2026 +0200
swscale/vulkan/ops: simplify bit-exact linear op generation
To match the C backend bit-exactly, each row must be evaluated in the same
order: starting from the offset, then adding the product of each nonzero
coefficient from left to right. The existing code unrolled this by special
casing the first coefficient and the offset, and then assumed that an
accumulated value existed for every further coefficient iff either of
those was nonzero. This was wrong for rows with more than one nonzero
coefficient besides those, e.g. a row of [0 a b 0 0] evaluated to b*z
instead of a*y + b*z.
Simplify this to start the accumulator from the offset and loop over all
coefficients, which fixes the bug. The generated code is otherwise
unchanged.
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 e651a6c5b6..be3be0621b 100644
--- a/libswscale/vulkan/ops.c
+++ b/libswscale/vulkan/ops.c
@@ -463,12 +463,12 @@ static int bitexact_linear_nb_ops(const SwsLinearOp *lin)
{
int nb_ops = 0;
for (int j = 0; j < 4; j++) {
- nb_ops += !!lin->m[j][0].num;
- nb_ops += lin->m[j][0].num && lin->m[j][4].num;
- for (int i = 1; i < 4; i++) {
- nb_ops += !!lin->m[j][i].num;
- nb_ops += lin->m[j][i].num &&
- (lin->m[j][0].num || lin->m[j][4].num);
+ bool acc = lin->m[j][4].num;
+ for (int i = 0; i < 4; i++) {
+ if (!lin->m[j][i].num)
+ continue;
+ nb_ops += 1 + acc; /* multiplication, and addition if needed */
+ acc = true;
}
}
return nb_ops;
@@ -843,26 +843,19 @@ static int insert_bitexact_linear(const SwsOp *op, SPICtx *spi, SPIRVIDs *id,
spi->off = off;
const int first_id = spi->id;
+ /* Same evaluation order as the C backend: offset first, then each column
+ * from left to right, skipping zero coefficients */
int res[4];
for (int j = 0; j < 4; j++) {
- res[j] = const_zero(id, op_type);
- if (op->lin.m[j][0].num)
- res[j] = spi_OpFMul(spi, type_s, tmp[0], lin->m[j][0]);
-
- if (op->lin.m[j][0].num && op->lin.m[j][4].num)
- res[j] = spi_OpFAdd(spi, type_s, lin->off[j], res[j]);
- else if (op->lin.m[j][4].num)
- res[j] = lin->off[j];
-
- for (int i = 1; i < 4; i++) {
+ bool acc = op->lin.m[j][4].num;
+ res[j] = acc ? lin->off[j] : const_zero(id, op_type);
+ for (int i = 0; i < 4; i++) {
if (!op->lin.m[j][i].num)
continue;
int v = spi_OpFMul(spi, type_s, tmp[i], lin->m[j][i]);
- if (op->lin.m[j][0].num || op->lin.m[j][4].num)
- res[j] = spi_OpFAdd(spi, type_s, res[j], v);
- else
- res[j] = v;
+ res[j] = acc ? spi_OpFAdd(spi, type_s, res[j], v) : v;
+ acc = true;
}
}