swscale/vulkan/ops: decorate bit-exact linear ops with NoContraction inline

Instead of reserving space for the decorations up front and patching them
in later, based on a separately computed instruction count, decorate each
instruction as it is emitted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
This commit is contained in:
Niklas HaasandClaude Opus 5.5 authored and Niklas Haas committed 2026-10-24 19:10:48 +00:00
1 parent 46679b0626
commit c94ffc7432
2 files changed
+8 -57

No files matched your search

+8 -48
View File
@@ -325,8 +325,6 @@ typedef struct LinearIDs {
int mat; /* full matrix, only valid without SWS_BITEXACT */
int off[4]; /* offset coefficients */
int off_vec;
int deco_off; /* space reserved for NoContraction decorations */
int nb_deco;
} LinearIDs;
/* Constants and buffers used by a single op */
@@ -463,25 +461,8 @@ static int emit_convert(SPICtx *spi, SwsPixelType from, SwsPixelType to,
: spi_OpConvertUToF(spi, res_type, a);
}
/* Number of arithmetic instructions emitted by insert_bitexact_linear() */
static int bitexact_linear_nb_ops(const SwsLinearOp *lin)
{
int nb_ops = 0;
for (int j = 0; j < 4; j++) {
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;
}
/* Section 1: Function to define all shader header data, and decorations */
static void define_shader_header(SwsContext *sws, const SwsOpList *ops,
SPICtx *spi, SPIRVIDs *id)
static void define_shader_header(SPICtx *spi, SPIRVIDs *id)
{
spi_OpCapability(spi, SpvCapabilityShader); /* Shader type */
@@ -522,21 +503,6 @@ static void define_shader_header(SwsContext *sws, const SwsOpList *ops,
spi_OpDecorate(spi, f->id, SpvDecorationDescriptorSet, 1);
spi_OpDecorate(spi, f->id, SpvDecorationBinding, f->binding);
}
if (!(sws->flags & SWS_BITEXACT))
return;
/* All linear arithmetic ops must be decorated with NoContraction */
for (int n = 0; n < ops->num_ops; n++) {
const SwsOp *op = &ops->ops[n];
if (op->op != SWS_OP_LINEAR)
continue;
const int nb_ops = bitexact_linear_nb_ops(&op->lin);
LinearIDs *lin = &id->op[n].lin;
lin->deco_off = spi_reserve(spi, SPI_SECTION_DECORATIONS, nb_ops*4*3);
lin->nb_deco = nb_ops;
}
}
/* Section 2: Define all types and constants */
@@ -841,14 +807,6 @@ static int insert_bitexact_linear(const SwsOp *op, SPICtx *spi, SPIRVIDs *id,
tmp[2] = spi_OpCompositeExtract(spi, type_s, data, 2);
tmp[3] = spi_OpCompositeExtract(spi, type_s, data, 3);
SPISectionBuf *deco = &spi->sec[SPI_SECTION_DECORATIONS];
const int off = deco->off;
deco->off = lin->deco_off;
for (int i = 0; i < lin->nb_deco; i++)
spi_OpDecorate(spi, spi->id + i, SpvDecorationNoContraction);
deco->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];
@@ -860,14 +818,16 @@ static int insert_bitexact_linear(const SwsOp *op, SPICtx *spi, SPIRVIDs *id,
continue;
int v = spi_OpFMul(spi, type_s, tmp[i], lin->m[j][i]);
res[j] = acc ? spi_OpFAdd(spi, type_s, res[j], v) : v;
spi_OpDecorate(spi, v, SpvDecorationNoContraction);
if (acc) {
v = spi_OpFAdd(spi, type_s, res[j], v);
spi_OpDecorate(spi, v, SpvDecorationNoContraction);
}
res[j] = v;
acc = true;
}
}
/* The decorations above assume one ID per arithmetic op */
av_assert0(spi->id - first_id == lin->nb_deco);
return spi_OpCompositeConstruct(spi, type_v,
res[0], res[1], res[2], res[3]);
}
@@ -1087,7 +1047,7 @@ static int emit_shader(SwsContext *sws, VulkanPriv *p, FFVulkanOpsCtx *s,
nb_data_bufs, 1);
/* Define shader header sections */
define_shader_header(sws, ops, spi, id);
define_shader_header(spi, id);
define_shader_consts(sws, ops, spi, id);
define_shader_bindings(ops, spi, id, in_img_count, out_img_count);
-9
View File
@@ -200,15 +200,6 @@ static inline int spi_end(const SPICtx *spi, uint8_t **out)
return len;
}
/* Reserves space in the given section, returns its offset */
static inline int spi_reserve(SPICtx *spi, SPISection s, int len)
{
SPISectionBuf *sec = &spi->sec[s];
if (!spi_append(sec, len))
return 0;
return sec->off - len;
}
static inline void spi_OpCapability(SPICtx *spi, SpvCapability capability)
{
SPISectionBuf *sec = spi_begin(spi, 2, 17);