swscale/uops_macros: also generate op lists involving 3DLUTs

These may differ from the regular op lists in nontrivial ways, due to e.g.
different optimization steps being taken.

In practice, it seems this just adds the extra LUT_3D uops, but we don't
know that for sure, so better to brute force the list. That said, I do
think we can safely skip the extra backend flags in this case, at least.

Even in the worst case scenario, that would just force a fallback to the
C reference backend.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
This commit is contained in:
Niklas Haas
2026-07-24 17:12:48 +02:00
committed by Niklas Haas
parent 05d8891a20
commit 3df239e113
5 changed files with 43 additions and 10 deletions

View File

@@ -29,7 +29,7 @@
#define DUMMY_SIZE 16
static int enum_ops_fmt(SwsContext *ctx, void *opaque,
static int enum_ops_fmt(SwsContext *ctx, void *opaque, const SwsLut3D *lut3d,
enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt,
int (*cb)(SwsContext *ctx, void *opaque, SwsOpList *ops))
{
@@ -52,7 +52,7 @@ static int enum_ops_fmt(SwsContext *ctx, void *opaque,
dst.width = dst_sizes[i][0];
dst.height = dst_sizes[i][1];
ret = ff_sws_op_list_generate(ctx, &src, &dst, NULL, &ops, &incomplete);
ret = ff_sws_op_list_generate(ctx, &src, &dst, lut3d, &ops, &incomplete);
if (ret == AVERROR(ENOTSUP))
return 0; /* silently skip unsupported formats */
else if (ret < 0)
@@ -86,7 +86,7 @@ fail:
* @note `ops` belongs to sws_enum_op_lists(), but may be mutated by `cb`.
*/
static inline
int ff_sws_enum_op_lists(SwsContext *ctx, void *opaque,
int ff_sws_enum_op_lists(SwsContext *ctx, void *opaque, const SwsLut3D *lut3d,
enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt,
int (*cb)(SwsContext *ctx, void *opaque, SwsOpList *ops))
{
@@ -102,7 +102,7 @@ int ff_sws_enum_op_lists(SwsContext *ctx, void *opaque,
const enum AVPixelFormat src_f = av_pix_fmt_desc_get_id(src);
for (dst = dst_start; dst; dst = av_pix_fmt_desc_next(dst)) {
const enum AVPixelFormat dst_f = av_pix_fmt_desc_get_id(dst);
int ret = enum_ops_fmt(ctx, opaque, src_f, dst_f, cb);
int ret = enum_ops_fmt(ctx, opaque, lut3d, src_f, dst_f, cb);
if (ret < 0)
return ret;
if (dst_fmt != AV_PIX_FMT_NONE)

View File

@@ -173,7 +173,7 @@ bad_option:
av_log_set_callback(log_stdout);
ret = ff_sws_enum_op_lists(ctx, graph, src_fmt, dst_fmt, print_passes);
ret = ff_sws_enum_op_lists(ctx, graph, NULL, src_fmt, dst_fmt, print_passes);
if (ret < 0)
goto fail;

View File

@@ -460,7 +460,7 @@ int main(int argc, char *argv[])
graph->ctx = ctx;
ctx->opaque = &root;
ret = ff_sws_enum_op_lists(ctx, graph, AV_PIX_FMT_NONE, AV_PIX_FMT_NONE,
ret = ff_sws_enum_op_lists(ctx, graph, NULL, AV_PIX_FMT_NONE, AV_PIX_FMT_NONE,
register_op);
/**

View File

@@ -1163,7 +1163,15 @@
MACRO(__VA_ARGS__, f32_dither_xyzw_3_2_0_5_16x16 , .type = SWS_PIXEL_F32, .uop = SWS_UOP_DITHER , .mask = 0xf, .par.dither = { .y_offset = {3, 2, 0, 5}, .size_log2 = 4 }) \
MACRO(__VA_ARGS__, f32_dither_xyzw_5_0_3_2_16x16 , .type = SWS_PIXEL_F32, .uop = SWS_UOP_DITHER , .mask = 0xf, .par.dither = { .y_offset = {5, 0, 3, 2}, .size_log2 = 4 }) \
MACRO(__VA_ARGS__, f32_dither_xyzw_5_2_3_0_16x16 , .type = SWS_PIXEL_F32, .uop = SWS_UOP_DITHER , .mask = 0xf, .par.dither = { .y_offset = {5, 2, 3, 0}, .size_log2 = 4 })
#define SWS_FOR_F32_LUT_3D(MACRO, ...)
#define SWS_FOR_STRUCT_F32_LUT_3D(MACRO, ...)
#define SWS_FOR_F32_LUT_3D(MACRO, ...) \
MACRO(__VA_ARGS__, f32_lut_3d_xyz_static , SWS_PIXEL_F32, SWS_UOP_LUT_3D , 0x7, 0) \
MACRO(__VA_ARGS__, f32_lut_3d_xyz_dynamic , SWS_PIXEL_F32, SWS_UOP_LUT_3D , 0x7, 1) \
MACRO(__VA_ARGS__, f32_lut_3d_xyzw_static , SWS_PIXEL_F32, SWS_UOP_LUT_3D , 0xf, 0) \
MACRO(__VA_ARGS__, f32_lut_3d_xyzw_dynamic , SWS_PIXEL_F32, SWS_UOP_LUT_3D , 0xf, 1)
#define SWS_FOR_STRUCT_F32_LUT_3D(MACRO, ...) \
MACRO(__VA_ARGS__, f32_lut_3d_xyz_static , .type = SWS_PIXEL_F32, .uop = SWS_UOP_LUT_3D , .mask = 0x7, .par.lut3d.dynamic = 0) \
MACRO(__VA_ARGS__, f32_lut_3d_xyz_dynamic , .type = SWS_PIXEL_F32, .uop = SWS_UOP_LUT_3D , .mask = 0x7, .par.lut3d.dynamic = 1) \
MACRO(__VA_ARGS__, f32_lut_3d_xyzw_static , .type = SWS_PIXEL_F32, .uop = SWS_UOP_LUT_3D , .mask = 0xf, .par.lut3d.dynamic = 0) \
MACRO(__VA_ARGS__, f32_lut_3d_xyzw_dynamic , .type = SWS_PIXEL_F32, .uop = SWS_UOP_LUT_3D , .mask = 0xf, .par.lut3d.dynamic = 1)
#endif /* SWSCALE_UOPS_MACROS_H */

View File

@@ -117,6 +117,9 @@ static int generate_entry_struct(void *opaque, void *key)
par->dither.y_offset[2], par->dither.y_offset[3],
par->dither.size_log2);
break;
case SWS_UOP_LUT_3D:
av_bprintf(bp, ", .par.lut3d.dynamic = %d", par->lut3d.dynamic);
break;
}
av_bprintf(bp, ")");
@@ -179,6 +182,9 @@ static int generate_entry_args(void *opaque, void *key)
par->dither.y_offset[2], par->dither.y_offset[3],
par->dither.size_log2);
break;
case SWS_UOP_LUT_3D:
av_bprintf(bp, ", %d", par->lut3d.dynamic);
break;
}
av_bprintf(bp, ")");
@@ -301,6 +307,7 @@ static int sws_uops_macros_gen(char **out_str)
{
int ret;
struct AVTreeNode *root = NULL;
SwsLut3D *lut3d = NULL;
AVBPrint bprint, *const bp = &bprint;
av_bprint_init(bp, 0, AV_BPRINT_SIZE_UNLIMITED);
@@ -320,11 +327,28 @@ static int sws_uops_macros_gen(char **out_str)
ctx->opaque = &root;
ctx->scaler = SWS_SCALE_BILINEAR; /* cheaper to generate filter kernels */
/* Allocate dummy 3DLUT to force generation of SWS_UOP_LUT_3D */
lut3d = ff_sws_lut3d_alloc();
if (!lut3d) {
ret = AVERROR(ENOMEM);
goto fail;
}
ret = ff_sws_enum_op_lists(ctx, graph, lut3d, AV_PIX_FMT_NONE,
AV_PIX_FMT_NONE, register_all_uops);
if (ret < 0)
goto fail;
lut3d->dynamic = true;
ret = ff_sws_enum_op_lists(ctx, graph, lut3d, AV_PIX_FMT_NONE,
AV_PIX_FMT_NONE, register_all_uops);
if (ret < 0)
goto fail;
/* Register all unique uops over every relevant combination of flags */
for (int i = 0; i < FF_ARRAY_ELEMS(flags_list); i++) {
ctx->flags = flags_list[i];
ret = ff_sws_enum_op_lists(ctx, graph, AV_PIX_FMT_NONE, AV_PIX_FMT_NONE,
register_all_uops);
ret = ff_sws_enum_op_lists(ctx, graph, NULL, AV_PIX_FMT_NONE,
AV_PIX_FMT_NONE, register_all_uops);
if (ret < 0)
goto fail;
}
@@ -371,6 +395,7 @@ static int sws_uops_macros_gen(char **out_str)
ret = av_bprint_finalize(bp, out_str);
fail:
av_refstruct_unref(&lut3d);
av_bprint_finalize(bp, NULL);
av_tree_enumerate(root, NULL, NULL, free_uop_key);
av_tree_destroy(root);