Add runtime-dispatched SSSE3 and AVX2 implementations for packed
10-bit YUV 4:2:2. The SSSE3 loop follows the negative-width output-offset
pattern used by v210. The AVX2 loop processes 16 pixels at a time and has
an internal eight-pixel tail.
Both implementations use exact-width input loads and therefore do not
rely on padded input or legal overread. They passed 300 consecutive checkasm
seeds.
Benchmark command:
./tests/checkasm/checkasm --bench --test=bitpackeddec \
--duration=1000000 51000
Intel Xeon E-2356G, GCC 8.5, NASM 2.15.03:
bitpacked_unpack_yuv422p10_c: 13516.7
bitpacked_unpack_yuv422p10_ssse3: 3415.8 (3.96x)
bitpacked_unpack_yuv422p10_avx2: 2183.1 (6.19x)
Unpack packed 10-bit YUV 4:2:2 in 16-pixel NEON blocks and unroll the
main loop to 32 pixels. Keep exact-width source loads and use the scalar
implementation for decoder tails smaller than eight pixels.
Enable the optimized implementation on little-endian AArch64. Retain the
C fallback on big-endian AArch64, where the byte layout expected by this
implementation does not apply.
The implementation passed 300 consecutive checkasm repetitions and
produced bit-exact output in a 100-frame UHD decode.
Thanks to Martin Storsjö for feedback and suggestions for improvement.
Correctness command:
./tests/checkasm/checkasm --test=bitpackeddec --repeat=300 66000
Benchmark command:
./tests/checkasm/checkasm --bench --test=bitpackeddec \
--function=bitpacked_unpack_yuv422p10 --duration=1000000 95000
Apple M4 Mac mini, Apple clang 17.0.0:
bitpacked_unpack_yuv422p10_c: 876.8 ns
bitpacked_unpack_yuv422p10_neon: 227.2 ns (3.86x)
Clang auto-vectorizes the C reference with NEON, so the result measures
the hand-written implementation against compiler-generated SIMD rather than
against purely scalar machine code.
Move the packed YUV422P10 unpacking loop behind a function pointer and keep the existing C implementation as the default.
Process multiples of eight through the DSP-style interface while retaining the C path for any remaining pixels. This provides a directly testable interface for later architecture-specific implementations without changing decoded output.