Commit Graph

151 Commits

Author SHA1 Message Date
Niklas Haas
09c0cd6837 swscale/tests/sws_ops: split passes when printing ops lists
This affects a large number of conversions across the board, either:

1. Lifting a constant alpha/chroma clear out from the conversion pass:

 rgb24 16x16 -> yuva444p 16x16:
+  [ u8 $XXX] SWS_OP_CLEAR        : {255 _ _ _}
+  [ u8 XXXX] SWS_OP_WRITE        : 1 elem(s) planar >> 0, via {3}
+    ('X' unused, 'z' byteswapped, '=' copied, '$' const, '+' integer, '0' zero)
+ translated micro-ops:
+    u8_clear_x_1
+    u8_write_planar_x
+ Sub-pass #1:
   [ u8 +++X] SWS_OP_READ         : 3 elem(s) packed >> 0
   [ u8 +++X] SWS_OP_CONVERT      : u8 -> f32
   [f32 ...X] SWS_OP_LINEAR       : matrix3+off3 [...]
   [f32 ...X] SWS_OP_DITHER       : 16x16 matrix + {0 3 2 -1}
   [f32 +++X] SWS_OP_CONVERT      : f32 -> u8
-  [ u8 +++$] SWS_OP_CLEAR        : {_ _ _ 255}
-  [ u8 XXXX] SWS_OP_WRITE        : 4 elem(s) planar >> 0
+  [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) planar >> 0
     ('X' unused, 'z' byteswapped, '=' copied, '$' const, '+' integer, '0' zero)

 gray 16x16 -> yuv444p 16x16:
+  [ u8 $$XX] SWS_OP_CLEAR        : {128 128 _ _}
+  [ u8 XXXX] SWS_OP_WRITE        : 2 elem(s) planar >> 0, via {2, 1}
+    ('X' unused, 'z' byteswapped, '=' copied, '$' const, '+' integer, '0' zero)
+ translated micro-ops:
+    u8_clear_xy_xx
+    u8_write_planar_xy
+ Sub-pass #1:
   [ u8 =XXX] SWS_OP_READ         : 1 elem(s) planar >> 0
   [ u8 =XXX] SWS_OP_CONVERT      : u8 -> f32
   [f32 .XXX] SWS_OP_LINEAR       : luma [...]
   [f32 .XXX] SWS_OP_DITHER       : 16x16 matrix + {0 -1 -1 -1}
   [f32 +XXX] SWS_OP_CONVERT      : f32 -> u8
-  [ u8 +$$X] SWS_OP_CLEAR        : {_ 128 128 _}
-  [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) planar >> 0
+  [ u8 XXXX] SWS_OP_WRITE        : 1 elem(s) planar >> 0
     ('X' unused, 'z' byteswapped, '=' copied, '$' const, '+' integer, '0' zero)
  translated micro-ops:
     u8_read_planar_x
     u8_to_f32_x
     f32_linear_x_x000x
     f32_dither_x_0_16x16
     f32_to_u8_x
-    u8_clear_yz_xx
-    u8_write_planar_xyz
+    u8_write_planar_x

or

2. Passing through a plane that was previously unmodified by an ops chain:

 gbrap 16x16 -> yuva444p 16x16:
-  [ u8 ====] SWS_OP_READ         : 4 elem(s) planar >> 0, via {2, 0, 1, 3}
-  [ u8 ====] SWS_OP_CONVERT      : u8 -> f32
-  [f32 ...=] SWS_OP_LINEAR       : matrix3+off3 [...]
-  [f32 ...=] SWS_OP_DITHER       : 16x16 matrix + {0 3 2 -1}
-  [f32 +++=] SWS_OP_CONVERT      : f32 -> u8
-  [ u8 XXXX] SWS_OP_WRITE        : 4 elem(s) planar >> 0
+  [ u8 =XXX] SWS_OP_READ         : 1 elem(s) planar >> 0, via {3}
+  [ u8 XXXX] SWS_OP_WRITE        : 1 elem(s) planar >> 0, via {3}
     ('X' unused, 'z' byteswapped, '=' copied, '$' const, '+' integer, '0' zero)
  translated micro-ops:
-    u8_read_planar_xyzw
-    u8_to_f32_xyzw
+    u8_read_planar_x
+    u8_write_planar_x
+ Sub-pass #1:
+  [ u8 ===X] SWS_OP_READ         : 3 elem(s) planar >> 0, via {2, 0, 1}
+  [ u8 ===X] SWS_OP_CONVERT      : u8 -> f32
+  [f32 ...X] SWS_OP_LINEAR       : matrix3+off3 [...]
+  [f32 ...X] SWS_OP_DITHER       : 16x16 matrix + {0 3 2 -1}
+  [f32 +++X] SWS_OP_CONVERT      : f32 -> u8
+  [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) planar >> 0
+    ('X' unused, 'z' byteswapped, '=' copied, '$' const, '+' integer, '0' zero)
+ translated micro-ops:
+    u8_read_planar_xyz
+    u8_to_f32_xyz
     f32_linear_xyz_xxx0x_xxx0x_xxx0x
     f32_dither_xyz_0_3_2_16x16
-    f32_to_u8_xyzw
-    u8_write_planar_xyzw
+    f32_to_u8_xyz
+    u8_write_planar_xyz

(Op lists are abridged slightly for brevity)

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
409b870bd6 swscale/tests/sws_ops: only print actually compiled ops lists
We already have the unoptimized reference ops; printing each intermediate
stage here is just noise that makes this file harder to scroll through IMO.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
27ff50f6ab swscale/ops_dispatch: add SWS_OP_FLAG_DRY_RUN
Avoids us having to write awkward code like `output ? &pass : NULL`.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-23 11:48:13 +00:00
Niklas Haas
8cc6b2ddaf swscale/tests/swscale: fix unscaled subsampled chroma format check
This should be matching against the *chroma* scaler, not the main scaler.
Of course, under normal circumstances, scaler_sub matches scaler, but this
allows users to explicitly override this defaulting by setting e.g.

-scaler none -scaler_sub bicubic

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-20 03:08:33 +02:00
Ramiro Polla
f523577512 swscale/aarch64: convert generation of ops_entries.c to a fate test
This serves two purposes:
- there is a test to check that the file is always up-to-date
- it can easily be regenerated using fate's own infrastructure
2026-06-19 14:33:28 +00:00
Ramiro Polla
b532f4a6ce swscale/tests/sws_ops_aarch64: remove on-stack copy of const data
It doesn't get modified, so there's no need to create a copy.
2026-06-19 14:31:27 +00:00
Ramiro Polla
3c6c6388b0 swscale/aarch64/ops: skip filtering ops lists when generating ops_entries.c
sws_ops_aarch64 would still register operations that came before the
filtering ops (which are unsupported).
2026-06-18 14:50:13 +00:00
Michael Niedermayer
d3a56ed37b swscale/tests/sws_ops: fix uops leak on translate success path
Fall through to the existing cleanup so uops is freed on both the success
and failure paths.

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
2026-06-10 07:48:37 +00:00
Ramiro Polla
2576e09434 swscale/aarch64/ops: simplify process function generation
There was no good reason to have it as an SwsAArch64OpType.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
2026-06-10 01:47:11 +02:00
Ramiro Polla
19250a1846 swscale/aarch64/ops: use plain ret instruction
Use a call/ret pair instead of awkwardly exporting and then jumping
back to the return label.

This is similar to c29465bcb6, but for aarch64.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
2026-06-10 01:47:10 +02:00
Ramiro Polla
692951d1c2 swscale/tests/sws_ops_aarch64: fix skipping of scaling ops
Scaling ops were add to ff_sws_enum_op_lists() in 1d841635. But the
code that skipped scaling ops in convert_to_aarch64_impl() wasn't
taking into consideration that, in sws_ops_aarch64, the scaling ops
aren't folded into read ops.

Also updates libswscale/aarch64/ops_entries.c with the new entries.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
2026-06-10 01:46:29 +02:00
Niklas Haas
228ef8d97b swscale/ops: make compile() take const SwsOpList *
The old x86 backend was the only backend that actually mutated the ops list.
With this gone, we can constify this parameter.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-09 18:27:20 +02:00
Niklas Haas
157f586e5c swscale/uops: thread SwsContext through ff_sws_ops_translate()
Needed to access ctx->flags, in particular SWS_BITEXACT.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-09 18:27:20 +02:00
Niklas Haas
3f9219d605 swscale/uops: add SwsUOpFlags to ff_sws_ops_translate()
These will be used to e.g. enable extra uops during translation.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-09 18:27:20 +02:00
Niklas Haas
adaf142647 swscale/uops: generate uop helper macros
This follows the same approach as is used currently by ops_entries_aarch64,
except I decided to have the generation logic live directly in uops.c
to allow re-using internal helpers and move it closer to the other helpers
that depend on the exact set of uops and their fields.

Unlike libswscale/tests/sws_ops.c, we make an effort to actually test all
relevant flag combinations, since these can affect the generated op lists.

I will use these macros to auto-generate both the C template-based kernels,
as well as the entire x86 backend, in the near future, hence their excessive
flexibility.

Re-use the libswscale/tests/sws_ops.c that we already compile. We could put it
in its own file but this is just as convenient, and it's easily moved anyways.
Having it be a FATE test ensures that it is always up-to-date.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-09 18:27:20 +02:00
Niklas Haas
8ad7cc6ccd swscale/tests/sws_ops: also print/test micro-op list
Tests for changes or regressions in the generated micro-ops. This will be
instrumental in my development of the micro-ops optimizer, and my plans to
phase out some of the macro-op optimization passes in favor of doing those
optimizations on the uop level instead.

 rgb24 16x16 -> rgb24 16x32:
   [ u8 +++X] SWS_OP_READ         : 3 elem(s) packed >> 0
     min: {0 0 0 _}, max: {255 255 255 _}
   [ u8 ...X] SWS_OP_FILTER_V     : 16 -> 32 bilinear (2 taps)
     min: {0 0 0 _}, max: {255 255 255 _}
   [f32 ...X] SWS_OP_DITHER       : 16x16 matrix + {0 3 2 -1}
     min: {1/512 1/512 1/512 _}, max: {255.998047 255.998047 255.998047 _}
   [f32 ...X] SWS_OP_MIN          : x <= {255 255 255 _}
     min: {1/512 1/512 1/512 _}, max: {255 255 255 _}
   [f32 +++X] SWS_OP_CONVERT      : f32 -> u8
     min: {0 0 0 _}, max: {255 255 255 _}
   [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) packed >> 0
     (X = unused, z = byteswapped, + = exact, 0 = zero)
  Retrying with split passes:
   [ u8 +++X] SWS_OP_READ         : 3 elem(s) packed >> 0
     min: {0 0 0 _}, max: {255 255 255 _}
   [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) planar >> 0
     (X = unused, z = byteswapped, + = exact, 0 = zero)
+ translated micro-ops:
+    u8_read_packed_xyz
+    u8_write_planar_xyz
  Sub-pass #1:
   [ u8 ...X] SWS_OP_READ         : 3 elem(s) planar >> 0 + 2 tap bilinear filter (V)
     min: {0 0 0 _}, max: {255 255 255 _}
   [f32 ...X] SWS_OP_DITHER       : 16x16 matrix + {0 3 2 -1}
     min: {1/512 1/512 1/512 _}, max: {255.998047 255.998047 255.998047 _}
   [f32 ...X] SWS_OP_MIN          : x <= {255 255 255 _}
     min: {1/512 1/512 1/512 _}, max: {255 255 255 _}
   [f32 +++X] SWS_OP_CONVERT      : f32 -> u8
     min: {0 0 0 _}, max: {255 255 255 _}
   [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) packed >> 0
     (X = unused, z = byteswapped, + = exact, 0 = zero)
+ translated micro-ops:
+    u8_read_planar_fv_xyz
+    f32_dither_xyz_0_3_2_16x16
+    f32_min_xyz
+    f32_to_u8_xyz
+    u8_write_packed_xyz
...

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-09 01:11:01 +02:00
Niklas Haas
6b75166758 swscale/tests/sws_ops: minor cleanup / consistency
Clean up after the previous revert.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-09 01:10:54 +02:00
Niklas Haas
dcfe3d3b90 Revert "swscale/tests/sws_ops: add option for summarizing all operation patterns"
This reverts commit f76aa4e408.

This is no longer needed once we switch to uops_macros.h, which will do the
same thing except better.
2026-06-09 01:10:49 +02:00
Niklas Haas
5a6bf8d4f4 swscale/tests/swscale: allow all backends for auxiliary conversions
This enables testing all internally supported pixel formats.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-05 22:32:51 +02:00
Niklas Haas
8366d5f8d6 swscale/tests/swscale: refactor format testing logic
Uses the internal ff_sws_test_pixfmt_backend() to test for format support
on the concrete backend that's in-use for the auxiliary/main conversions,
respectively, while taking into account the -backends and -api options.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-05 22:22:27 +02:00
Ramiro Polla
fcaafd2c11 swscale/tests/swscale: add -scaler/-scaler_sub parameters to set scaler algorithm
The -unscaled parameter has been removed in favour of "-scaler none".

Some legacy scalers cannot be selected with these options (i.e.: SWS_X
and SWS_FAST_BILINEAR). To test these, the -flags parameter shoule be
used instead.

This option sets the scaler/scaler_sub fields in SwsContext. There is a
comment about these fields in struct SwsContext:

  Note: Does not affect the legacy (stateful) API.

This comment is not entirely correct, since scaler/scaler_sub are taken
into consideration to select the algorithm, but that doesn't update the
flags field, which is still used to select implementations:

libswscale/x86/swscale.c:574:            if (c->opts.flags & SWS_FAST_BILINEAR && c->canMMXEXTBeUsed) {
libswscale/ppc/swscale_vsx.c:2033:            if (c->opts.flags & SWS_FAST_BILINEAR && c->opts.dst_w >= c->opts.src_w && c->chrDstW >= c->chrSrcW) {
libswscale/swscale_unscaled.c:2465:        && (!needsDither || (c->opts.flags&(SWS_FAST_BILINEAR|SWS_POINT))))
libswscale/swscale_unscaled.c:2650:    if (c->opts.flags&(SWS_FAST_BILINEAR|SWS_POINT)) {
libswscale/utils.c:1279:            && !(sws->flags & SWS_FAST_BILINEAR)
libswscale/utils.c:1388:         (flags & SWS_FAST_BILINEAR)))
libswscale/utils.c:1417:            && (flags & SWS_FAST_BILINEAR)) {
libswscale/utils.c:1437:    if (flags & SWS_FAST_BILINEAR) {
libswscale/utils.c:1648:        if (c->canMMXEXTBeUsed && (flags & SWS_FAST_BILINEAR)) {
libswscale/swscale.c:678:            if (c->opts.flags & SWS_FAST_BILINEAR) {

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
2026-06-05 03:00:31 +02:00
Ramiro Polla
a16e674f7f swscale/tests/swscale: add -api parameter (supersedes -legacy parameter)
The "-legacy 1" option was added in 101a2f6fc6 to run the main
conversion with the legacy scaler. This was done by forcing the use of
the legacy API. This way, it was possible to pass "-flags unstable" and
still ensure the legacy scaler path was being taken.

New legacy-related parameters will be added to the test tool, so it
makes sense to rename the -legacy option to reflect what it was
actually doing.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
2026-06-04 22:55:30 +02:00
Ramiro Polla
c458346de2 swscale/tests/swscale: reuse init_frame() for src
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
2026-06-04 22:54:33 +02:00
Ramiro Polla
b9968758ab swscale/tests/swscale: add optional destination size to -s option
This lets us test specific scaling operations, for example:
$ ./libswscale/tests/swscale -s 96x96:128x128 -src yuva444p -dst rgb24 -flags unstable+neighbor
yuva444p 96x96 -> rgb24 128x128, flags=0x100010 dither=1, SSIM={Y=0.999932 U=0.999957 V=0.999937 A=1.000000} loss=6.514788e-05

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
2026-06-04 22:54:30 +02:00
Ramiro Polla
2e50831755 swscale/tests/swscale: propagate ret out of parse_options()
This will make it easier to keep function-scoped variables.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
2026-06-04 22:54:27 +02:00
Ramiro Polla
cc0d904795 Revert "swscale/tests/swscale: check if formats require the legacy path with -hw"
This reverts commit ac611d3120.
2026-06-04 22:54:23 +02:00
Niklas Haas
ef182f2289 swscale/tests/sws_ops: avoid confusing double label
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-03 23:53:15 +02:00
Niklas Haas
945151851e swscale/tests/swscale: add -backends option
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-03 21:39:55 +00:00
Niklas Haas
a00db63da7 swscale/tests/swscale: add option to force specific buffer alignment
Useful to make sure the memcpy_in/out paths work as expected.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-06-02 15:35:00 +02:00
Lynne
ac611d3120 swscale/tests/swscale: check if formats require the legacy path with -hw
The issue is the legacy path does not support hardware frames, so falling
back means erroring with ENOTSUP, which would fail the tests.

Sponsored-by: Sovereign Tech Fund
2026-05-31 01:14:08 +09:00
Niklas Haas
812b5654ae swscale/tests/sws_ops: use SWS_SCALE_BILINEAR for printing ops lists
This actually changes the behavior vs SWS_SCALE_POINT, because point scaling
is bit-exact and thus implies a different set of optimizations.

Ideally, we would still try and somehow merge this with tests/swscale.c to
allow testing a different set of scalers; but I still don't have a good idea
for how to accomplish that here.

As it stands, results in additional extra dithering steps in almost all
filters involving scaling, e.g.:

 rgb24 16x16 -> rgb24 16x32:
   [ u8 +++X] SWS_OP_READ         : 3 elem(s) packed >> 0
     min: {0 0 0 _}, max: {255 255 255 _}
-  [ u8 +++X] SWS_OP_FILTER_V     : 16 -> 32 point (1 taps)
+  [ u8 ...X] SWS_OP_FILTER_V     : 16 -> 32 bilinear (2 taps)
     min: {0 0 0 _}, max: {255 255 255 _}
+  [f32 ...X] SWS_OP_DITHER       : 16x16 matrix + {0 3 2 -1}
+    min: {1/512 1/512 1/512 _}, max: {255.998047 255.998047 255.998047 _}
+  [f32 ...X] SWS_OP_MIN          : x <= {255 255 255 _}
+    min: {1/512 1/512 1/512 _}, max: {255 255 255 _}
   [f32 +++X] SWS_OP_CONVERT      : f32 -> u8
     min: {0 0 0 _}, max: {255 255 255 _}
   [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) packed >> 0
     (X = unused, z = byteswapped, + = exact, 0 = zero)

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-05-17 10:41:34 +00:00
Niklas Haas
2dfe055ddd swscale/tests/sws_ops: print split sub-passes for lists with filters
This allows us to inspect exactly the logic that is going on inside the CPU
backends (which don't support bare filter passes).

 rgb24 16x16 -> rgb24 16x32:
   [ u8 +++X] SWS_OP_READ         : 3 elem(s) packed >> 0
     min: {0 0 0 _}, max: {255 255 255 _}
   [ u8 +++X] SWS_OP_FILTER_V     : 16 -> 32 point (1 taps)
     min: {0 0 0 _}, max: {255 255 255 _}
   [f32 +++X] SWS_OP_CONVERT      : f32 -> u8
     min: {0 0 0 _}, max: {255 255 255 _}
   [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) packed >> 0
     (X = unused, z = byteswapped, + = exact, 0 = zero)
+ Retrying with split passes:
+  [ u8 +++X] SWS_OP_READ         : 3 elem(s) packed >> 0
+    min: {0 0 0 _}, max: {255 255 255 _}
+  [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) planar >> 0
+    (X = unused, z = byteswapped, + = exact, 0 = zero)
+ Sub-pass #1:
+  [ u8 +++X] SWS_OP_READ         : 3 elem(s) planar >> 0 + 1 tap point filter (V)
+    min: {0 0 0 _}, max: {255 255 255 _}
+  [f32 +++X] SWS_OP_CONVERT      : f32 -> u8
+    min: {0 0 0 _}, max: {255 255 255 _}
+  [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) packed >> 0
+    (X = unused, z = byteswapped, + = exact, 0 = zero)
 rgb24 16x16 -> rgb24 32x16:
   [ u8 +++X] SWS_OP_READ         : 3 elem(s) packed >> 0
     min: {0 0 0 _}, max: {255 255 255 _}
   [ u8 +++X] SWS_OP_FILTER_H     : 16 -> 32 point (1 taps)
     min: {0 0 0 _}, max: {255 255 255 _}
   [f32 +++X] SWS_OP_CONVERT      : f32 -> u8
     min: {0 0 0 _}, max: {255 255 255 _}
   [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) packed >> 0
     (X = unused, z = byteswapped, + = exact, 0 = zero)
+ Retrying with split passes:
+  [ u8 +++X] SWS_OP_READ         : 3 elem(s) packed >> 0
+    min: {0 0 0 _}, max: {255 255 255 _}
+  [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) planar >> 0
+    (X = unused, z = byteswapped, + = exact, 0 = zero)
+ Sub-pass #1:
+  [ u8 +++X] SWS_OP_READ         : 3 elem(s) planar >> 0 + 1 tap point filter (H)
+    min: {0 0 0 _}, max: {255 255 255 _}
+  [f32 +++X] SWS_OP_CONVERT      : f32 -> u8
+    min: {0 0 0 _}, max: {255 255 255 _}
+  [ u8 XXXX] SWS_OP_WRITE        : 3 elem(s) packed >> 0
+    (X = unused, z = byteswapped, + = exact, 0 = zero)

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-05-17 10:41:34 +00:00
Niklas Haas
369a301669 swscale/tests/sws_ops: use a dummy ops backend for printing
This ensures that the ops printing path goes through the same code as the
actual ops dispatch backend, including all sub-passes etc.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-05-17 10:41:34 +00:00
Niklas Haas
1d841635a4 swscale/ops: also include scaling ops in ff_sws_enum_op_lists()
Using the configured scaler from the SwsContext implicitly. This does affect
the output of libswscale/tests/sws_ops.c, which now prints about 4x as much
data (taking roughly 4x as long, but still within a second on my machine).

We can make this process a lot faster by forcing SWS_SCALE_POINT as the
scaler, which skips calculating any actual filter weights in favor of
generating a trivial 1-tap filter.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-05-15 18:53:05 +02:00
Ramiro Polla
d812c8b0eb swscale/tests/swscale: log test parameters on loss error
When running with "-v 0", the test parameters were not being printed,
which made it hard to track down which conversion the error referred
to.

Now the test parameters are logged with av_log() when a loss error
happens.
2026-05-15 14:12:48 +00:00
Ramiro Polla
1cc9b15bab swscale/tests/swscale: fix -p option when -flags and/or -unscaled are used
The -p, -flags, and -unscaled options all affected the decision to
select a subsample of the tests to run. When specifying -p 0.1, about
57% of the tests would run instead of the expect 10%.

This commit fixes this by separating -p from -flags and -unscaled.
2026-05-15 14:12:48 +00:00
Ramiro Polla
24d432e227 swscale/tests/swscale: improve help text for -p option 2026-05-15 14:12:48 +00:00
Niklas Haas
cf2d40f65d swscale/ops: add explicit clear mask to SwsClearOp
Instead of implicitly testing for NaN values. This is mostly a straightforward
translation, but we need some slight extra boilerplate to ensure the mask
is correctly updated when e.g. commuting past a swizzle.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-04-16 23:23:36 +02:00
Niklas Haas
953d278a01 tests/swscale: fix input pattern generation for very small sizes
This currently completely fails for images smaller than 12x12; and even in that
case, the limited resolution makes these tests a bit useless.

At the risk of triggering a lot of spurious SSIM regressions for very
small sizes (due to insufficiently modelling the effects of low resolution on
the expected noise), this patch allows us to at least *run* such tests.

Incidentally, 8x8 is the smallest size that passes the SSIM check.
2026-04-16 20:59:39 +00:00
Lynne
990768080e tests/swscale: add support for testing Vulkan hardware acceleration
Sponsored-by: Sovereign Tech Fund

Co-authored-by: Ramiro Polla <ramiro.polla@gmail.com>
2026-04-02 21:15:06 +02:00
Niklas Haas
85bef2c2bc swscale/ops: split SwsConst up into op-specific structs
It was a bit clunky, lacked semantic contextual information, and made it
harder to reason about the effects of extending this struct. There should be
zero runtime overhead as a result of the fact that this is already a big
union.

I made the changes in this commit by hand, but due to the length and noise
level of the commit, I used Opus 4.6 to verify that I did not accidentally
introduce any bugs or typos.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-04-02 11:48:15 +00:00
Andreas Rheinhardt
f56d073d7e swscale/tests/.gitignore: Add sws_ops_aarch64
Forgotten in a1bfaa0e78.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2026-03-30 14:31:25 +02:00
Ramiro Polla
a1bfaa0e78 swscale/aarch64: introduce tool to enumerate sws_ops for NEON backend
The NEON sws_ops backend will use a build-time code generator for the
various operation functions it needs to implement. This build time code
generator (ops_asmgen) will need a list of the operations that must be
implemented. This commit adds a tool (sws_ops_aarch64) that generates
such a list (ops_entries.c).

The list is generated by iterating over all possible conversion
combinations and collecting the parameters for each NEON assembly
function that has to be implemented, defined by an unique set of
parameters derived from SwsOp. Whenever swscale evolves, with improved
optimization passes, new pixel formats, or improvements to the backend
itself, this file (ops_entries.c) should be regenerated by running:
    $ make sws_ops_entries_aarch64

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
2026-03-30 11:38:35 +00:00
Niklas Haas
13388c0cac swscale/ops: test for SWS_COMP_GARBAGE instead of next->comps.unused
When printing/describing operations.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-03-29 09:39:09 +00:00
Niklas Haas
7b6170a9a5 tests/swscale: don't hard-error on low bit depth SSIM loss
This is an expected consequence of the fact that the new ops code does not
yet do error diffusion, which only really affects formats like rgb4 and monow.

Specifically, this avoids erroring out with the following error:

 loss 0.214988 is WORSE by 0.0111071, ref loss 0.203881
 SSIM {Y=0.745148 U=1.000000 V=1.000000 A=1.000000}

When scaling monow -> monow from 96x96 to 128x96.

We can remove this hack again in the future when error diffusion is implemented,
but for now, this check prevents me from easily testing the scaling code.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-03-28 18:50:14 +01:00
Niklas Haas
f76aa4e408 swscale/tests/sws_ops: add option for summarizing all operation patterns
This can be used to either manually verify, or perhaps programmatically
generate, the list of operation patterns that need to be supported by a
backend to be feature-complete.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-03-28 16:48:13 +00:00
Niklas Haas
d7a079279f swscale/tests/sws_ops: refactor argument parsing
To allow for argumentless options in the future.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-03-28 16:48:13 +00:00
Ramiro Polla
b6e470467e swscale/tests/sws_ops: add -v option to set log verbosity
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
2026-03-28 16:48:13 +00:00
Niklas Haas
d3db2dc518 swscale/tests/sws_ops: simplify using ff_sws_enum_op_lists()
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-03-28 16:48:13 +00:00
Ramiro Polla
5640bd3a4f swscale/tests/swscale: require reference file to perform comparisons
The legacy scaler is no longer implicitly used to generate a reference
to perform comparisons for every conversion. It is now up to the user
to generate a reference file and use it as input for a separate run to
perform comparisons.

It is now possible to compare against previous runs of the graph-based
scaler, for example to test for newer optimizations.

This reduces the overall time necessary to obtain speedup numbers from
the legacy scaler to the graph-based scaler (or any other comparison,
for that matter) since the reference must only be run once.

For example, to check the speedup between the legacy scaler and the
graph-based scaler:
  ./libswscale/tests/swscale [...] -bench 50 -legacy 1 > legacy_ref.txt
  ./libswscale/tests/swscale [...] -bench 50 -ref legacy_ref.txt

If no -ref file is specified, we are assuming that we are generating a
reference file, and therefore all information is printed (including
ssim/loss, and benchmarks if -bench is used).

If a -ref file is specified, the output printed depends on whether we
are testing for correctness (ssim/loss only) or benchmarking (time/
speedup only, along with overall speedup).

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
2026-03-14 06:13:19 +00:00