318 Commits

Author SHA1 Message Date
Frank Barchard
63e54f7374 [libyuv] Add NEON implementations for all remaining C row functions
Implement 32-bit and 64-bit Arm NEON versions (in row_neon.cc and
row_neon64.cc) for the 12 remaining row functions that previously fell
back to C on Arm:
- AR30ToAB30Row_NEON (and AR30ToAB30Row_Any_NEON)
- AR30ToABGRRow_NEON (and AR30ToABGRRow_Any_NEON)
- AR30ToARGBRow_NEON (and AR30ToARGBRow_Any_NEON)
- ARGBAffineRow_NEON
- ARGBColorTableRow_NEON
- ARGBCopyAlphaRow_NEON (and ARGBCopyAlphaRow_Any_NEON)
- ARGBLumaColorTableRow_NEON
- ARGBPolynomialRow_NEON (and ARGBPolynomialRow_Any_NEON)
- ARGBUnattenuateRow_NEON (and ARGBUnattenuateRow_Any_NEON)
- CopyRow_16_NEON (and CopyRow_16_Any_NEON)
- MirrorRow_16_NEON (and MirrorRow_16_Any_NEON)
- RGBColorTableRow_NEON

Add HAS_*_NEON macros, prototypes, _Any wrappers, NEON dispatches in
convert.cc, convert_argb.cc, and planar_functions.cc, and enable unit
tests in planar_test.cc. Arm row function SIMD coverage is now 164/164
(100%).

ARM64 (Apple M6) Benchmark (1280 width, 10000 iterations):
----------------------------------------------------------------
Function                 Before C (ms) After NEON (ms)  Improvement
----------------------------------------------------------------
AR30ToAB30Row                    1.20           0.70        1.72x
AR30ToABGRRow                    1.88           1.03        1.83x
AR30ToARGBRow                    1.88           0.87        2.17x
ARGBAffineRow                    7.96           2.31        3.44x
ARGBColorTableRow                8.17           7.43        1.10x
ARGBCopyAlphaRow                 1.37           0.53        2.58x
ARGBLumaColorTableRow            8.18           5.24        1.56x
ARGBPolynomialRow                8.73           7.55        1.16x
ARGBUnattenuateRow               6.00           2.05        2.93x
CopyRow_16                       0.18           0.18        1.00x
MirrorRow_16                     0.34           0.20        1.73x
RGBColorTableRow                 6.15           5.58        1.10x
----------------------------------------------------------------

Maximum SIMD ISA supported per C row function:
----------------------------------------------------------------
C Row Function              arm32   arm64    x86        riscv
----------------------------------------------------------------
AB64ToARGBRow_C             NEON    NEON     AVX2       RVV
ABGRToAR30Row_C             -       NEON     AVX512BW   -
AR30ToAB30Row_C             NEON    NEON     AVX512BW   -
AR30ToABGRRow_C             NEON    NEON     AVX512BW   -
AR30ToARGBRow_C             NEON    NEON     AVX512BW   -
AR64ShuffleRow_C            NEON    NEON     AVX512BW   RVV
AR64ToAB64Row_C             NEON    NEON     AVX512BW   RVV
AR64ToARGBRow_C             NEON    NEON     AVX2       RVV
ARGB1555ToARGBRow_C         NEON    SVE2     AVX2       -
ARGB1555ToUVMatrixRow_C     NEON    NEON     AVX2       -
ARGB1555ToUVRow_C           NEON    NEON     -          -
ARGB1555ToYMatrixRow_C      NEON    NEON     AVX2       -
ARGB1555ToYRow_C            NEON    NEON     -          -
ARGB4444ToARGBRow_C         NEON    NEON     AVX2       -
ARGB4444ToUVMatrixRow_C     NEON    NEON     AVX2       -
ARGB4444ToUVRow_C           NEON    NEON     -          -
ARGB4444ToYMatrixRow_C      NEON    NEON     AVX2       -
ARGB4444ToYRow_C            NEON    NEON     -          -
ARGBAddRow_C                NEON    NEON     AVX2       -
ARGBAffineRow_C             NEON    NEON     SSE2       -
ARGBAlphaBlendRow_C         NEON    SME      AVX512BW   RVV
ARGBAttenuateRow_C          NEON    NEON     AVX512BW   RVV
ARGBBlendRow_C              NEON    NEON     AVX512BW   RVV
ARGBColorMatrixRow_C        NEON    I8MM     SSSE3      -
ARGBColorTableRow_C         NEON    NEON     X86        -
ARGBCopyAlphaRow_C          NEON    NEON     AVX2       -
ARGBCopyYToAlphaRow_C       NEON    NEON     AVX512BW   RVV
ARGBExtractAlphaRow_C       NEON    NEON     AVX512BW   RVV
ARGBGrayRow_C               NEON    DOTPROD  AVX512VNNI -
ARGBLumaColorTableRow_C     NEON    NEON     SSSE3      -
ARGBMirrorRow_C             NEON    NEON     AVX512BW   RVV
ARGBMultiplyRow_C           NEON    SME      AVX512BW   RVV
ARGBOrRow_C                 NEON    SME      AVX512BW   RVV
ARGBPolynomialRow_C         NEON    NEON     AVX2       -
ARGBQuantizeRow_C           NEON    NEON     SSE2       -
ARGBSepiaRow_C              NEON    DOTPROD  SSSE3      -
ARGBSetRow_C                NEON    NEON     X86        RVV
ARGBShadeRow_C              NEON    NEON     SSE2       -
ARGBShuffleRow_C            NEON    NEON     AVX512BW   RVV
ARGBSubtractRow_C           NEON    NEON     AVX2       -
ARGBToAB64Row_C             NEON    NEON     AVX2       RVV
ARGBToABGRRow_C             NEON    NEON     AVX512BW   RVV
ARGBToAR30Row_C             -       NEON     AVX512BW   -
ARGBToAR64Row_C             NEON    NEON     AVX2       RVV
ARGBToARGB1555Row_C         NEON    NEON     AVX2       -
ARGBToARGB4444Row_C         NEON    NEON     AVX2       -
ARGBToBGRARow_C             NEON    NEON     AVX512BW   RVV
ARGBToRAWRow_C              NEON    SVE2     AVX512BW   RVV
ARGBToRGB24Row_C            NEON    SVE2     AVX512BW   RVV
ARGBToRGB565DitherRow_C     NEON    SVE2     AVX2       -
ARGBToRGB565Row_C           NEON    SVE2     AVX2       -
ARGBToRGBARow_C             NEON    NEON     AVX512BW   RVV
ARGBToUV444MatrixRow_C      NEON    I8MM     AVX512VNNI RVV
ARGBToUVMatrixRow_C         NEON    SME      AVX512VNNI RVV
ARGBToYMatrixRow_C          NEON    SME      AVX512VNNI RVV
ARGBUnattenuateRow_C        NEON    NEON     AVX2       -
AYUVToUVRow_C               NEON    SVE2     AVX512VBMI -
AYUVToVURow_C               NEON    SVE2     AVX512VBMI -
AYUVToYRow_C                NEON    NEON     AVX512VBMI -
BlendPlaneRow_C             NEON    NEON     AVX512BW   RVV
ByteToFloatRow_C            NEON    NEON     -          -
ComputeCumulativeSumRow_C   -       NEON     AVX2       -
Convert16To8Row_C           NEON    SME      AVX512BW   RVV
Convert8To16Row_C           NEON    SME      AVX512BW   RVV
Convert8To8Row_C            NEON    SME      AVX2       -
CopyRow_C                   NEON    SME      AVX512BW   RVV
CopyRow_16_C                NEON    NEON     -          -
CumulativeSumToAverageRow_C -       NEON     AVX2       -
DetileRow_C                 NEON    NEON     SSE2       -
DetileRow_16_C              NEON    NEON     AVX        -
DetileSplitUVRow_C          NEON    NEON     SSSE3      -
DivideRow_16_C              NEON    SVE2     AVX2       -
GaussRow_C                  NEON    NEON     -          -
GaussRow_F32_C              -       NEON     -          -
HalfFloatRow_C              NEON    SVE2     AVX2       -
HalfMergeUVRow_C            NEON    SVE2     AVX512BW   -
HalfRow_16To8_C             NEON    SME      AVX512BW   RVV
HalfWidthRow_16To8_C        NEON    SME      AVX512BW   RVV
I210AlphaToARGBRow_C        -       SME      AVX2       -
I210ToAR30Row_C             -       SME      AVX2       -
I210ToARGBRow_C             -       SME      AVX2       -
I212ToAR30Row_C             -       SME      AVX2       -
I212ToARGBRow_C             -       SME      AVX2       -
I400ToARGBRow_C             NEON    SME      AVX512BW   RVV
I410AlphaToARGBRow_C        -       SME      AVX2       -
I410ToAR30Row_C             -       SME      AVX2       -
I410ToARGBRow_C             -       SME      AVX2       -
I422AlphaToARGBRow_C        NEON    SME      AVX512BW   RVV
I422ToAR30Row_C             -       SME      AVX512BW   RVV
I422ToARGB1555Row_C         NEON    SME      AVX2       -
I422ToARGB4444Row_C         NEON    SME      AVX2       -
I422ToARGBRow_C             NEON    SME      AVX512BW   RVV
I422ToRGB24Row_C            NEON    SME      AVX512VBMI RVV
I422ToRGB565Row_C           NEON    SME      AVX2       -
I422ToRGBARow_C             NEON    SME      AVX2       RVV
I422ToUYVYRow_C             NEON    NEON     AVX2       -
I422ToYUY2Row_C             NEON    NEON     AVX2       -
I444AlphaToARGBRow_C        NEON    SME      AVX2       RVV
I444ToARGBRow_C             NEON    SME      AVX2       RVV
I444ToRGB24Row_C            NEON    SME      AVX2       RVV
InterpolateRow_C            NEON    SME      AVX512BW   RVV
InterpolateRow_16_C         NEON    SME      AVX512BW   -
J400ToARGBRow_C             NEON    NEON     AVX512BW   RVV
MergeAR64Row_C              NEON    NEON     AVX2       -
MergeARGB16To8Row_C         NEON    NEON     AVX2       -
MergeARGBRow_C              NEON    NEON     AVX2       RVV
MergeRGBRow_C               NEON    NEON     AVX512VBMI RVV
MergeUVRow_C                NEON    SME      AVX512BW   RVV
MergeUVRow_16_C             NEON    SME      AVX2       -
MergeXR30Row_C              NEON    NEON     AVX512BW   -
MergeXR64Row_C              NEON    NEON     AVX2       -
MergeXRGB16To8Row_C         NEON    NEON     AVX2       -
MergeXRGBRow_C              NEON    NEON     AVX2       RVV
MirrorRow_C                 NEON    NEON     AVX512BW   -
MirrorRow_16_C              NEON    NEON     AVX512BW   -
MirrorSplitUVRow_C          NEON    NEON     AVX512BW   -
MirrorUVRow_C               NEON    NEON     AVX512BW   RVV
MultiplyRow_16_C            NEON    SME      AVX512BW   RVV
NV12ToARGBRow_C             NEON    SME      AVX512BW   RVV
NV12ToRGB24Row_C            NEON    SME      AVX512VBMI RVV
NV12ToRGB565Row_C           NEON    NEON     AVX2       -
NV21ToARGBRow_C             NEON    SME      AVX512BW   RVV
NV21ToRGB24Row_C            NEON    SME      AVX512VBMI RVV
NV21ToYUV24Row_C            NEON    NEON     AVX2       -
P210ToAR30Row_C             -       SME      AVX2       -
P210ToARGBRow_C             -       SME      AVX2       -
P410ToAR30Row_C             -       SME      AVX2       -
P410ToARGBRow_C             -       SME      AVX2       -
RAWToARGBRow_C              NEON    SVE2     AVX512BW   RVV
RAWToRGB24Row_C             NEON    SVE2     AVX512VBMI RVV
RAWToRGBARow_C              NEON    SVE2     AVX512VBMI RVV
RGB24MirrorRow_C            NEON    NEON     AVX512VBMI -
RGB24ToARGBRow_C            NEON    SVE2     AVX512BW   RVV
RGB565ToARGBRow_C           NEON    NEON     AVX2       -
RGB565ToUVMatrixRow_C       NEON    NEON     AVX2       -
RGB565ToUVRow_C             NEON    NEON     -          -
RGB565ToYMatrixRow_C        NEON    NEON     AVX2       -
RGB565ToYRow_C              NEON    NEON     -          -
RGBAToARGBRow_C             NEON    NEON     AVX512BW   RVV
RGBColorTableRow_C          NEON    NEON     X86        -
RGBToUV444MatrixRow_C       NEON    NEON     AVX512BW   RVV
RGBToUVMatrixRow_C          NEON    NEON     AVX512BW   RVV
RGBToYMatrixRow_C           NEON    DOTPROD  AVX512BW   RVV
SetRow_C                    NEON    NEON     ERMS       -
SobelRow_C                  NEON    NEON     SSE2       -
SobelToPlaneRow_C           NEON    NEON     SSE2       -
SobelXRow_C                 NEON    NEON     SSE2       -
SobelXYRow_C                NEON    NEON     SSE2       -
SobelYRow_C                 NEON    NEON     SSE2       -
SplitARGBRow_C              NEON    NEON     AVX2       RVV
SplitRGBRow_C               NEON    NEON     AVX2       RVV
SplitUVRow_C                NEON    SVE2     AVX512BW   RVV
SplitUVRow_16_C             NEON    NEON     AVX2       -
SplitXRGBRow_C              NEON    NEON     AVX2       RVV
SwapUVRow_C                 NEON    NEON     AVX512BW   RVV
UYVYToARGBRow_C             NEON    SME      AVX2       -
UYVYToUV422Row_C            NEON    NEON     AVX2       -
UYVYToUVRow_C               NEON    SVE2     AVX2       -
UYVYToYRow_C                NEON    SVE2     AVX2       -
YUY2ToARGBRow_C             NEON    SME      AVX2       -
YUY2ToNVUVRow_C             NEON    NEON     AVX2       -
YUY2ToUV422Row_C            NEON    NEON     AVX2       -
YUY2ToUVRow_C               NEON    SVE2     AVX2       -
YUY2ToYRow_C                NEON    SVE2     AVX2       -
----------------------------------------------------------------
SIMD (164/164 100%)         146 89% 164 100% 154 94%    64 39%
----------------------------------------------------------------

Test: libyuv_unittest --gtest_filter=*AR30*:*Affine*:*ColorTable*:*CopyAlpha*:*Polynomial*:*Unattenuate*:*MirrorPlane_16*
Bug: None
Change-Id: Ib8b68beb77b47de6b996d41fd080397c61539ffb
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8666404
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Commit-Queue: Frank Barchard <fbarchard@google.com>
2026-10-27 16:51:21 -07:00
Frank Barchard
205022c08c [libyuv] Add AVX-512 VNNI row functions for ARGB to YUV and Gray
Add AVX-512 VNNI (VPDPBUSD / _mm512_dpbusd_epi32) row kernels for 64-bit
x86 targets alongside existing AVX-512BW implementations in both
row_gcc.cc (inline assembly) and row_win.cc (C++ intrinsics):

- ARGBToYMatrixRow_AVX512VNNI and ARGBToYMatrixRow_Any_AVX512VNNI:
  Pre-computes the 32-bit signed-pixel bias once per row and replaces
  vpmaddubsw + vpmaddwd + vpaddw with a single vpdpbusd per 16 pixels.
- ARGBToUV444MatrixRow_AVX512VNNI and
  ARGBToUV444MatrixRow_Any_AVX512VNNI: Loads 64 ARGB pixels once instead
  of twice and computes 32-bit U and V dot products directly via
  vpdpbusd with signed UV matrix coefficients.
- ARGBToUVMatrixRow_AVX512VNNI: Computes 2x2 box-filtered ARGB to U and
  V conversion using vpdpbusd with k-masked tail handling for arbitrary
  widths.
- ARGBGrayRow_AVX512VNNI: Computes BT.601 grayscale luminance using a
  single vpdpbusd per 16 pixels, broadcasts Y to RGB via vpshufb, and
  preserves alpha via vpternlogd with k-masked tail handling.
- Wire runtime dispatch via TestCpuFlag(kCpuHasAVX512VNNI) across
  convert.cc, convert_from_argb.cc, and planar_functions.cc.

Add AVX512VNNIVBMI variants of the Y, UV444 and UV kernels. These use
both AVX-512 VNNI (vpdpbusd) and AVX-512 VBMI (vpermt2b) and are only
selected when the CPU has both features; there are no VBMI versions
without VNNI. The AVX512VNNI kernels remain for CPUs with VNNI but no
VBMI (Cascade Lake, Cooper Lake).

- The 32-bit sums are always in [0, 65535], so Y, U and V are byte 1 of
  each int32. Two vpermt2b gather 64 results from 4 accumulators,
  replacing vpackusdw/vpackssdw + vpsrlw + vpackuswb + vpermd.
- U and V accumulators start at ~kAddUV so they hold ~(kAddUV - dot).
  The inverse is folded into the vpternlogd that merges the two
  256-bit halves. kAddUV is loaded from ArgbConstants rather than
  hard coded as 0x8000.
- Y folds the source loads into vpxorq.
- row_win.cc hides the vpermt2b indices from clang, which otherwise
  constant folds them into a longer vpshufb + vpor + vpermd sequence.

Performance (1280x720, 5000 iterations, AVX512BW -> AVX512VNNI):
uArch / Benchmark            AVX512BW  AVX512VNNI  Speedup
---------------------------  --------  ----------  -------
Intel Ice Lake ARGBToI420      941 ms      862 ms   +9.2%
Intel Ice Lake ARGBToI422     1059 ms      947 ms  +11.8%
Intel Ice Lake ARGBToI444     1140 ms     1038 ms   +9.8%
Intel Ice Lake ARGBGray        357 ms      273 ms  +30.8%
Intel Sapphire Rapids GrayTo   317 ms      218 ms  +45.4%
Intel Emerald Rapids GrayTo    310 ms      213 ms  +45.5%
Intel Granite Rapids GrayTo    349 ms      241 ms  +44.8%
AMD Zen 4 ARGBToI420           648 ms      517 ms  +25.3%
AMD Zen 4 ARGBToI444           695 ms      526 ms  +32.1%
AMD Zen 4 ARGBGray             403 ms      227 ms  +77.5%
AMD Zen 5 ARGBToI422           460 ms      403 ms  +14.1%
AMD Zen 5 ARGBToI444           382 ms      321 ms  +19.0%

Performance (row_gcc, AVX512VNNI -> AVX512VNNIVBMI):
uArch / Benchmark             AVX512VNNI  VNNIVBMI  Speedup
----------------------------  ----------  --------  -------
AMD Zen 6 ARGBToI420 1280x720     327 ms    284 ms   +15.1%
AMD Zen 6 ARGBToI422 1280x720     372 ms    330 ms   +12.7%
AMD Zen 6 ARGBToI444 1280x720     357 ms    334 ms    +6.9%
AMD Zen 6 ARGBToI400 256x24        94 ms     76 ms   +23.7%
AMD Zen 5 ARGBToI422 1280x720     406 ms    350 ms   +16.0%
AMD Zen 5 ARGBToI444 1280x720     330 ms    301 ms    +9.6%
AMD Zen 5 ARGBToI400 256x24       100 ms     90 ms   +11.1%
AMD Zen 4 ARGBToI420 1280x720     631 ms    540 ms   +16.9%
AMD Zen 4 ARGBToI422 1280x720     993 ms    825 ms   +20.4%
AMD Zen 4 ARGBToI400 256x24       245 ms    218 ms   +12.4%
Intel GNR ARGBToI422 256x24       654 ms    616 ms    +6.2%
Intel SPR ARGBToI422 256x24       653 ms    613 ms    +6.5%
Intel GNR, EMR, SPR and Ice Lake are within +/-3% at 1280x720.

R=rrwinterton@gmail.com

Bug: none
Test: out/Release/libyuv_unittest --gtest_filter=*ARGBToI4*:*ARGBGray*
Test: LIBYUV_DISABLE_AVX512VBMI=1 out/Release/libyuv_unittest
Test: sde64 -gnr / -clx with is_msan=true (row_win.cc)
Change-Id: Ia7a37b39dd2948fe4055a8a7694dd1ff8ac3e55c
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8647811
Reviewed-by: richard winterton <rrwinterton@gmail.com>
2026-10-26 14:07:50 -07:00
Frank Barchard
f249eaa72f [libyuv] Fix top 20 bugs and performance issues
1. Fix multi-bit TestCpuFlag(A | B) checks in AYUVToNV12, AYUVToNV21,
   RAWToRGBA, NV12ToRGB24Matrix, NV21ToRGB24Matrix, MergeRGBPlane, and
   MergeXR30Plane to compare == (A | B) so AVX-512 VBMI/BW kernels are
   not dispatched when AVX512VBMI or AVX512VL is absent.
2. Fix 2-byte SVE2 heap buffer overflow on odd widths in
   I422ToARGB1555Row_SVE_SC and I422ToARGB4444Row_SVE_SC using
   trn1/trn2 + st2b under .b predicates.
3. Fix ARGBPolynomialRow_SSE2 to use packssdw before packuswb, and add
   missing vzeroupper to SplitRGBRow_AVX2.
4. Fix CalcFrameSsim to return 0.0 instead of 0.0 / 0 (NaN) when
   width <= 8 || height <= 8 so I420Ssim stays finite on small frames.
5. Fix negative-height vertical inversion in ConvertFromI420,
   SplitARGBPlane (when dst_a is NULL), I422Rotate, I010Rotate, and
   I210Rotate.
6. Fix horizontal flip (negative x/dx) in ScaleFilterCols_NEON (signed
   sbfx #16, #16 offset extraction) and ScaleAddCols1_16_C (shift
   x >>= 16 before indexing src_ptr).
7. Fix ConvertToARGB odd crop_x chroma alignment in NV12/NV21, src_u
   offset in I420/YV12/J420/H420/U420, and FOURCC_U422 calling
   U422ToARGB instead of H422ToARGB.
8. Remove dead 14-instruction block in ScaleRowUp2_Bilinear_16_SSE2.
9. Fix UVScale_16 for src_width == 1 (P010ToP410/P210ToP410), enable
   and fix column order in TransposeWx4_32_SVE2, fix ByteToFloatRow
   NEON Any BPP (3 -> 4), fix AB64ToARGBRow_Any_*, ScaleColsUp2_SSE2,
   ScaleUVRowDown2Box_SME, and UYVYToARGBRow_SME macro guards, fix SVE2
   loop tail branches (b.lt/b.ge), and remove duplicate HAS_* macros.
10. Fix ConvertFP16ToFP32Column_NEON loop condition and unsigned b.lo
    underflow on widths < 8 or not multiples of 8.
11. Fix UYVYToNV12 IS_ALIGNED(awidth, ...) checks and WASM SIMD
    IS_ALIGNED(width, 16) checks in I420ToRGB24Matrix /
    I422ToRGB24Matrix.
12. Wire SplitUVRow_SVE2, SplitUVRow_LSX, and SplitUVRow_LASX in
    NV24ToARGB.
13. Fix MJpegDecoder heap buffer overflows in LoadFrame (reallocate
    databuf_[i] when scanlines_size changes), DecodeToBuffers, and
    DecodeToCallback (clamp scanlines_to_copy to lines_left and align
    skip to max_v_samp_factor).
14. Replace width & (vl - 1) tail calculations with post-loop remainder
    across 18 SVE2 functions in row_sve.h for non-power-of-2 SVE VL,
    and remove duplicate label 2: in UYVYToARGBRow_SVE_SC.
15. Handle width & 15 tail pixels in DetileToYUY2_C and validate
    IS_POWEROFTWO(tile_height) in DetileSplitUVPlane and DetileToYUY2.
16. Avoid signed 32-bit overflow in DivideRow_16_C and C16TO8, fix
    ClampFloatToZero_SSE2 pointer increment (lea 0x4) and loop counter
    (sub $0x1), and initialize xmm3 in ARGBCopyYToAlphaRow_SSE2.
17. Check max leaf 7 subleaf and max extended CPUID leaf in GetCpuFlags
    before querying subleaf 7:1 and extended leaf 0x80000021.
18. Free plane_u on error in I422ToNV21, and fix 4x/2x scratch row
    over-allocation in ScaleARGBBilinearDown and ScaleUVBilinearDown.
19. Add ARGBSetRow_RVV and ARGBShuffleRow_RVV in row_rvv.cc.
20. Fix NEON mask (15 -> 7) in ScaleUVRowUp2_Linear_Any_NEON /
    _16_Any_NEON, use SIMD InterpolateRow + SplitUVRow in NV16ToI420,
    wire SSSE3/SSE2 in ARGBToI400Matrix / ARGBToYUY2Matrix /
    ARGBToUYVYMatrix and RGB24Mirror, and split HalfFloatRow multiply
    into (src * scale) * 2^-112 to avoid 50x Intel denormal stalls.

Bug: b/574714081
Test: libyuv_unittest
Change-Id: Iec3ae5c58d52bee3ef13cf9b765ac84b733aa576
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8601931
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Commit-Queue: Frank Barchard <fbarchard@google.com>
2026-10-19 16:46:40 -07:00
Frank Barchard
700f153cb8 [libyuv] Add Qualcomm Hexagon HVX SIMD support
Implement Qualcomm Hexagon Vector Extensions (HVX) 128-byte SIMD
optimizations and runtime CPU detection for Hexagon DSP targets:
- CPU detection: Add kCpuHasHexagon and kCpuHasHVX flags,
  LIBYUV_DISABLE_HVX environment variable support, and Hexagon
  unit_test mmap/munmap shims.
- Rotate/Transpose (rotate_hvx.cc): Implement TransposeWxH_HVX,
  TransposeUVWxH_HVX, TransposeWxH_16_HVX, and TransposeWxH_32_HVX
  using power-of-2 vdeal/vshuff butterfly networks.
- Compare (compare_hvx.cc): Implement HammingDistance_HVX,
  SumSquareError_HVX, HashDjb2_HVX, and Ssim4x4Row_HVX.
- Scale (scale_hvx.cc): Implement 16 scale row kernels including
  ScaleAddRow_HVX, ScaleRowDown2*_HVX (8-bit and 16-bit),
  ScaleRowDown4*_HVX, ScaleARGBRowDown2*_HVX, and
  ScaleUVRowDown2*_HVX.
- Row functions (row_hvx.cc): Implement 58 row kernels covering
  copy/set/mirror, split/merge, 8/16-bit conversions, YUV-to-ARGB,
  ARGB-to-YUV, ARGB channel swizzles, blend, attenuate, and
  interpolate using hardware-predicated partial loads/stores.

R=rrwinterton@gmail.com

Bug: None
Test: libyuv_unittest on Hexagon v81 simulator and Snapdragon 8 Elite
Change-Id: Ib6713de51f6246d95e58c95e629ff03f18e3b91e
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8604586
Reviewed-by: richard winterton <rrwinterton@gmail.com>
2026-10-19 14:16:18 -07:00
Frank Barchard
2404f9730e [libyuv] Rewrite LoongArch LSX/LASX kernels in compact inline asm
Reduce loop unrolling across LoongArch LSX (128-bit) and LASX (256-bit)
compare, row, rotate, and scale kernels to match SSE2/SSSE3 and AVX2
(1-2 vectors per iteration), rewrite intrinsics/macro implementations
into GCC/Clang inline assembly, update all _Any wrapper masks and
IS_ALIGNED dispatch checks, and port all remaining LSX Convert (+19) and
Rotate (+2) kernels to LASX for full parity:

ISA              | Compare | Convert | Rotate  | Scale
-----------------|---------|---------|---------|--------
MIPS/Loong (Any) |    1    |    68   |    4    |   20
  LSX            |    1    |    68   |    4    |   20
  LASX           |    1    |    68   |    4    |    0

Removes 1,935 macro/helper lines from loongson_intrinsics.h (-99.3%) and
reduces total LoongArch compiled .text size by 9,799 bytes (-25.1%
overall, -37.4% row_lsx.cc, -52.3% scale_lsx.cc, -31.2% rotate_lsx.cc,
-4.9% row_lasx.cc while adding +25 LASX functions):

File               | Before   | After    | Change
-------------------|----------|----------|--------
scale_lsx.cc.o     | 6,055 B  | 2,888 B  | -52.3%
row_lsx.cc.o       | 17,252 B | 10,792 B | -37.4%
rotate_lsx.cc.o    | 1,488 B  | 1,024 B  | -31.2%
row_lasx.cc.o      | 13,740 B | 13,072 B |  -4.9%
rotate_lasx.cc.o   |   544 B  | 1,504 B  | +176.5%
TOTAL .text        | 39,079 B | 29,280 B | -25.1%

R=wtc@google.com, yuanhecai@loongson.cn

Test: qemu-loongarch64 -cpu la464 libyuv_unittest (LASX and LIBYUV_DISABLE_LASX=1)
Change-Id: I11c1143ad2aad0399f10b2c3fc9bc4c02c740c59
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8564659
Reviewed-by: richard winterton <rrwinterton@gmail.com>
2026-10-16 17:25:23 -07:00
Frank Barchard
b9d572cc63 Add 25 native k-masked AVX-512 row kernels
R=rrwinterton@gmail.com

Bug: None
Change-Id: I2ee9b2c2d939f63f49d2f951f2d552ca6863d78b
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8564927
Commit-Queue: Frank Barchard <fbarchard@google.com>
Reviewed-by: richard winterton <rrwinterton@gmail.com>
2026-10-12 18:14:41 -07:00
Frank Barchard
63b56324de [libyuv] Replace AVX-512 _Any wrappers with k-mask tail handling
Replace stack-buffer memcpy _Any wrappers with native AVX-512 k-mask
tail handling across 8 AVX-512 row kernels (unlocking composite
RGBToUVMatrixRow_AVX512BW as well) and remove IS_ALIGNED dispatch
constraints:
- MirrorSplitUVRow_AVX512BW: Masked 16-bit load (vmovdqu16 %{k1%}%{z%}),
  dynamic reverse index (vpsubw + vpermw via kMirrorUVPermute_AVX512),
  and vpmovwb %{k1%} U/V stores; unlocks unaligned SplitRotateUV180.
- ARGBToUVMatrixRow_AVX512BW: Fix MASK=63 vs 32-pixel loop bug;
  zero-load tail dwords per row, duplicate odd final pixel via knotw +
  vpshufd, and store masked U/V bytes.
- I422ToARGBRow_AVX512BW & I422ToAR30Row_AVX512BW: Add masked Y/U/V
  loads (READYUV422_MASK_AVX512BW) and masked ARGB/AR30 stores.
- CopyRow_AVX512BW: Add 64-byte full vector step + bzhi masked tail.
- BlendPlaneRow_AVX512BW, ARGBShuffleRow_AVX512BW, RGBToARGBRow_AVX512BW
  (RAWToARGBRow_AVX512BW / RGB24ToARGBRow_AVX512BW): Masked loads and
  stores in both row_gcc.cc inline assembly and row_win.cc intrinsics.

Reduces x86-64 binary .text size by 2,592 bytes with 0 bytes added to
.rodata.

Performance on Intel Sapphire Rapids (1275x1650, 1000 iterations):
Function (Test)          | Before  | After   | Speedup
-------------------------|---------|---------|--------
NV12Rotate180_Opt        | 429 ms  | 260 ms  | 1.65x
RGB24ToI420_Opt          | 615 ms  | 531 ms  | 1.16x
I420ToAR30_Opt           | 425 ms  | 383 ms  | 1.11x
ARGBToI420_Opt           | 427 ms  | 411 ms  | 1.04x
I420ToARGB_Opt           | 423 ms  | 411 ms  | 1.03x
RGB24ToARGB_Opt          | 493 ms  | 490 ms  | 1.01x
ARGBToBGRA_Opt           | 544 ms  | 542 ms  | 1.00x
CopyPlane_Opt            | 246 ms  | 245 ms  | 1.00x
BlendPlane_Opt           | 259 ms  | 258 ms  | 1.00x
RAWToARGB_Opt            | 486 ms  | 486 ms  | 1.00x

R=rrwinterton@gmail.com

Test: LIBYUV_WIDTH=1275 LIBYUV_HEIGHT=1650 LIBYUV_REPEAT=1000 out/Release/libyuv_unittest
Change-Id: Ib5e5ae52076352649108b20f8df2b12d81860fb1
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8563977
Reviewed-by: richard winterton <rrwinterton@gmail.com>
2026-10-12 15:33:19 -07:00
Frank Barchard
1ddb18fb6b [libyuv] AVX512, NEON, WASM and RVV alpha copy and mirror rows
1275x1650 (US Letter 150 DPI, 1000 iterations) speedup:

CPU            ARGBExtractAlpha ARGBCopyYToAlpha ARGBMirror RGB24Mirror
-----------------------------------------------------------------------
Intel Granite Rapids      1.00x            1.00x      1.00x       1.04x
Intel Emerald Rapids      1.01x            0.97x      1.03x       1.07x
Intel Sapphire Rapids     0.97x            1.01x      1.08x       1.26x
Intel Ice Lake            0.99x            1.02x      0.97x       1.08x
Intel Skylake-X           1.04x            1.03x      1.01x          NA
Intel Haswell                NA               NA         NA          NA
AMD Turin (Zen 5)         1.01x            1.10x      1.25x       1.31x
AMD Genoa (Zen 4)         0.97x            1.04x      1.09x       1.42x
AMD Milan (Zen 3)            NA               NA         NA          NA
AMD Rome (Zen 2)             NA               NA         NA          NA
NVIDIA Grace (V2)         1.57x            2.51x         NA          NA
Google Axion 2            1.12x            3.17x         NA          NA
Ampere Siryn              1.06x            1.70x         NA          NA
ARM Neoverse-N1           1.49x            2.01x         NA          NA
Google Axion (Maple)      1.47x            2.03x         NA          NA
ARM Cortex-A53            1.06x            1.69x         NA          NA

Add AVX512BW ARGBExtractAlphaRow, ARGBCopyYToAlphaRow and
ARGBMirrorRow, and AVX512VBMI RGB24MirrorRow, in row_gcc.cc and as
intrinsics in row_win.cc. They are x64 only. The remainder is done
with a k-mask (bzhi) zero-masked load and a masked store, so they
handle any width without an Any wrapper and never access memory
outside the row.

RGB24MirrorRow_AVX512VBMI loads and stores 3 full zmm vectors per
64 pixels using 3 vpermi2b. The one output byte that comes from the
third input vector is merged with a masked vpbroadcastb. The 1 to 63
pixel tail rebases the same tables by 192 - 3 * r; indices >= 128 are
taken from the third vector with vpmovb2m and a masked vpermb.

Add ARGBCopyYToAlphaRow_NEON for Arm 32 bit (vld4 + vst4) and
AArch64 (zip + sli), and rewrite AArch64 ARGBExtractAlphaRow_NEON
with ldp + uzp2. Both prefetch source and destination, which is
2.5x faster on Neoverse-N1 and 1.2x to 1.5x faster on Cortex-A53
for 1280x720. Add WASM SIMD ARGBExtractAlphaRow and
ARGBCopyYToAlphaRow, using a swizzle table for CopyYToAlpha. Rework
the RVV versions to use unit stride loads with vnsrl and vzext.vf4.


R=rrwinterton@gmail.com

Bug: None
Change-Id: I436f27d70a3db0a2b176c91eb789a9491133cfcb
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8523531
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Commit-Queue: Frank Barchard <fbarchard@google.com>
2026-10-07 12:44:53 -07:00
Frank Barchard
98697ab033 [libyuv] Add WASM SIMD128 compare, rotate, scale and row functions
d8 geomean speedup vs C compiled with -O2 -msimd128:
File            AMD Zen 3  ARM Neoverse-V2
row_wasm.cc         5.67x            3.24x
scale_wasm.cc       5.47x            3.17x
compare_wasm.cc     4.58x            5.77x
rotate_wasm.cc      6.83x            6.03x

Bug: None
Change-Id: Ia06c805dc4029f94842c40e7301b2933beb8c1e5
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8524106
Reviewed-by: richard winterton <rrwinterton@gmail.com>
2026-10-06 19:05:05 -07:00
Frank Barchard
b25fa89920 InterpolateRow_AVX512BW with tail masking
I420ScaleTo569x480_Bilinear (LIBYUV_WIDTH=569 LIBYUV_REPEAT=5000):
CPU                     AVX2      AVX512     Speedup
Intel Emerald Rapids   124 ms      63 ms      1.97x
Intel Sapphire Rapids  134 ms      69 ms      1.94x
Intel Skylake-X        219 ms     129 ms      1.70x
Intel Granite Rapids   124 ms      76 ms      1.63x
Intel Ice Lake         164 ms     101 ms      1.62x

Bug: None
Change-Id: I7a10446eb4dbcebae68380c2a186d4e3badec551
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8483371
Commit-Queue: Frank Barchard <fbarchard@google.com>
Reviewed-by: richard winterton <rrwinterton@gmail.com>
2026-09-29 11:22:47 -07:00
Frank Barchard
f1c9b58986 clang format and bump version
Bug: None
Change-Id: I6a482d5c538b113549b88e820473af644d6d3704
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8467772
Reviewed-by: richard winterton <rrwinterton@gmail.com>
2026-09-28 10:42:45 -07:00
Sida Zhu
dab3111c8a convert, scale: Add P010/P210/P410 convert paths and NV16/NV24/Px10 scale
P010 and P210 were auxiliary FourCCs and P410 did not exist, so
ConvertToI420, ConvertToARGB, and ConvertFromI420 could not consume or
produce them. Callers had to pick I010/I210 helpers and pack UV by hand.
NV12Scale existed, but NV16/NV24 and P010/P210/P410 had no Scale APIs.

Promote P010 and P210 to primary FourCCs, add FOURCC_P410, and add the
I4xx/Px10 converters those entry points need: I410ToP410, I412ToP412,
P210ToI210, P410ToI410, P010/P210/P410ToI420, I420ToP010/P210/P410,
I422ToP210, I444ToP410, and P410ToARGB/AR30Matrix.

Add NV16Scale (same path as NV12Scale: ScalePlane + UVScale).
Add P010Scale, P210Scale, and P410Scale: 10-bit samples stay in the MSBs, so Y/UV convert to 10-bit LSB, ScalePlane_16, then back to MSB.

UVScale_16 cannot general-scale, so UV is split, scaled as planes, and merged.

Packed-plane layout, odd-width strides, ConvertTo/From round-trips, and
the existing scale factor/size/swap tests cover the new APIs.

Bug: 537818862
Change-Id: I1ae5e6cad5e6d83acf1d0df69f94c23688bbe0e8
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8346569
Reviewed-by: Frank Barchard <fbarchard@google.com>
Reviewed-by: richard winterton <rrwinterton@gmail.com>
2026-09-23 20:43:22 -07:00
Frank Barchard
f51ad56a3e Multiply_16 port to avx512, rvv, neon 32 bit, and windows
- Also remove redundant neon check for I8MM kernels

======================================================================
CPU                                 Before      After          Speedup
----------------------------------------------------------------------
Intel Granite Rapids (AVX10.1)      251 ms     141 ms   1.78x (+43.8%)
Intel Emerald Rapids (AVX512)       199 ms     108 ms   1.84x (+45.7%)
Intel Sapphire Rapids (AVX512)      230 ms     112 ms   2.05x (+51.3%)
AMD Turin Zen 5 (AVX512)            156 ms      99 ms   1.58x (+36.5%)
AMD Venice Zen 6 (AVX512)           204 ms     106 ms   1.92x (+48.0%)
Intel Skylake-X (AVX512)            320 ms     156 ms   2.05x (+51.2%)
AMD Genoa Zen 4 (AVX512)            236 ms     346 ms   0.68x (-46.6%)
Intel Ice Lake (AVX512)             242 ms     316 ms   0.77x (-30.6%)
AMD Milan Zen 3 (AVX2)              252 ms     230 ms    1.10x (+8.7%)
Intel Haswell (AVX2)                369 ms     456 ms   0.81x (-23.6%)
NVIDIA Grace (SVE2)                 336 ms     337 ms    1.00x (-0.3%)
ARM Neoverse-N1 (NEON)             1081 ms    1105 ms    0.98x (-2.2%)
======================================================================


Bug: 537818862
Change-Id: I3ddeddb040fc52a30dabe7ae2c71d16dda021568
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8343467
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Commit-Queue: Frank Barchard <fbarchard@google.com>
2026-09-01 19:08:52 -07:00
yuanhecai
60102bd795 loongarch: Fix RGBToY SIMD
Add missing RGBToYMatrixRow_Any_{LSX,LASX} and kAddY offset fix so
RAW/RGB24 to YUV works on LoongArch.

Change-Id: I4c990a3705d7f521fa6d0c9e7e01f1e36f81c379
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8292090
Reviewed-by: Wan-Teh Chang <wtc@google.com>
Reviewed-by: Frank Barchard <fbarchard@google.com>
Commit-Queue: Wan-Teh Chang <wtc@google.com>
2026-08-31 20:57:34 -07:00
Frank Barchard
0c781f87b8 [libyuv] Keep LIBYUV_API in basic_types.h and remove legacy types and bool macros
Reduces include/libyuv/basic_types.h to only define LIBYUV_API.
Directly includes <stdint.h> and <stddef.h> where needed in public
headers.
Replaces LIBYUV_BOOL, LIBYUV_FALSE, and LIBYUV_TRUE with C++ bool,
true, and false in C++ code (MJpegDecoder, unit tests) and int (0, 1)
for C API functions.
Updates documentation and unit tests.

Test: ninja -C out/Release libyuv_unittest && ./out/Release/libyuv_unittest --gtest_filter=*
Change-Id: I2d58e872f0f976263bcda546dcc3b1b5f7e53d58
TAG=agy
CONV=2730bc56-93ff-48ed-b615-dcde1b834394
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8280662
Commit-Queue: Wan-Teh Chang <wtc@google.com>
Reviewed-by: Wan-Teh Chang <wtc@google.com>
2026-08-28 08:32:19 -07:00
Frank Barchard
eac1ea9744 I410ToI420 use 1 step HalfWidthRow function for UV
On Icelake
Was C+AVX512
I410ToI420_Opt (593 ms)
I412ToI420_Opt (581 ms)
Now AVX512
I410ToI420_Opt (241 ms)
I412ToI420_Opt (227 ms)
 60.28% HalfWidthRow_16To8_AVX512BW
 32.34% Convert16To8Row_AVX512BW

Samsung S25 Oryon
Was C+NEON
I410ToI420_Opt (141 ms)
I412ToI420_Opt (127 ms)
Now NEON
I410ToI420_Opt (89 ms)
I412ToI420_Opt (88 ms)

Vivo X300 lunix c1
Was C+NEON
I410ToI420_Opt (682 ms)
I412ToI420_Opt (679 ms)
With SVE2 (slow)
I410ToI420_Opt (622 ms)
I412ToI420_Opt (584 ms)
 65.59% HalfWidthRow_16To8_SVE2
 26.74% Convert16To8Row_SVE2
Now NEON
I410ToI420_Opt (412 ms)
I412ToI420_Opt (406 ms)

Bug: chromium:531172025
Change-Id: I1732157f6be660d2a01086f21daf85fe7f7d166f
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8230200
Commit-Queue: Frank Barchard <fbarchard@google.com>
Reviewed-by: Wan-Teh Chang <wtc@google.com>
2026-08-10 18:19:25 -07:00
Frank Barchard
5dc477899b Harden I21xToI420 against oversize heights
I21xToI420 (reached via I210ToI420 / I212ToI420): fix integer overflows
in ScalePlaneVertical_16To8() by switching to HalfRow_16To8.

Add a unit test covering the I21x vertical-scale path. Co-authored-by:
Timothy Nikkel <tnikkel@mozilla.com> Test: libyuv_unittest
--gtest_filter=*.I21xToI420NoHeightOverflow

AMD Zen4
 Was LibYUVConvertTest.I210ToI420_Opt (81 ms)
  30.32% Convert16To8Row_AVX2
  29.81% Convert16To8Row_AVX512BW
  25.72% InterpolateRow_16To8_AVX2

 Now LibYUVConvertTest.I210ToI420_Opt (56 ms)
  41.32% Convert16To8Row_AVX512BW
  40.13% HalfRow_16To8_AVX512BW

Vivo X300 (ARM Lunix C1 Ultra)
 Was LibYUVConvertTest.I210ToI420_Opt (89 ms)
  38.95% InterpolateRow_16To8_NEON
  37.25% Convert16To8Row_NEON

 Now LibYUVConvertTest.I210ToI420_Opt (85 ms)
  47.26% Convert16To8Row_SVE2
  30.39% HalfRow_16To8_SVE2

Bug: chromium:531172025
Change-Id: I23e1215030c40b8577d58617098a8aeec27dd99a
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8221883
Reviewed-by: Wan-Teh Chang <wtc@google.com>
Commit-Queue: Frank Barchard <fbarchard@google.com>
2026-08-08 12:11:18 -07:00
Frank Barchard
149568401f SVE2 row functions needed for multipass image functions
- MergeUVRow_SVE2: Interleaves U and V
 - SplitUVRow_SVE2: De-interleaves UV
 - InterpolateRow_SVE2: Bilinear row interpolation
 - YUY2ToYRow_SVE2, YUY2ToUVRow_SVE2, UYVYToYRow_SVE2, UYVYToUVRow_SVE2
 - HalfMergeUVRow_SVE2: 2:1 vertical averaging of U and V

OnePlus 15 with Qualcomm Snapdragon 8 Elite Gen 5 Oryon V3

Benchmark (1280x720 1000x)     | SVE2   | NEON   | Result
-------------------------------+--------+--------+------------------
TestInterpolatePlane           | 119 ms | 164 ms | SVE2 is 1.38x win
TestInterpolatePlane_16        | 138 ms | 172 ms | SVE2 is 1.25x win
SplitUVPlane_Opt               |  68 ms |  69 ms | SVE2 is 1.01x win
MergeUVPlane_Opt               |  40 ms |  40 ms | Tied
SwapUVPlane_Opt                |  72 ms |  72 ms | Tied
HalfMergeUVPlane_Opt           |  50 ms |  50 ms | Tied
I420ToNV12_Opt                 |  25 ms |  26 ms | SVE2 is faster
I420ToNV21_Opt                 |  26 ms |  26 ms | Tied
YUY2ToNV12_Opt                 |  79 ms |  81 ms | SVE2 is faster
NV21ToNV12_Opt                 |  36 ms |  35 ms | Tied
Android420ToI420ToNV12_Opt     |  53 ms |  53 ms | Tied
Android420ToI420ToNV21_Opt     |  35 ms |  33 ms | NEON is faster
YUY2ToI420_Opt                 |  87 ms |  84 ms | NEON is faster
UYVYToI420_Opt                 |  87 ms |  83 ms | NEON is faster
YUY2ToI422_Opt                 | 101 ms |  97 ms | NEON is faster
UYVYToI422_Opt                 | 101 ms |  97 ms | NEON is faster
UYVYToNV12_Opt                 | 111 ms | 108 ms | NEON is faster
ARGBToNV21_Opt                 | 279 ms | 279 ms | Tied
ABGRToNV21_Opt                 | 279 ms | 280 ms | SVE2 is faster
ARGBToNV12_Opt                 | 285 ms | 280 ms | NEON is faster
ABGRToNV12_Opt                 | 284 ms | 281 ms | NEON is faster

Bug: 42280902
Change-Id: I53f633fe453f2853f7bc9fe17280e938912c4e8f
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8196068
Reviewed-by: Justin Green <greenjustin@google.com>
Commit-Queue: Frank Barchard <fbarchard@google.com>
2026-08-06 12:40:26 -07:00
Frank Barchard
7138e0a2a7 Make RGBToY a 1 pass avx512bw
- RGBToARGB use vpermi2q+vpshufb
- direct RGBToY for avx512 and rvv

+----------+----------+-------------+----------+---------+-----------+
| ARGBToY  | ARGBToUV | ARGBToUV444 | RGBToY   | RGBToUV | RGBToUV444|
+----------+----------+-------------+----------+---------+-----------+
| avx512bw | avx512bw | avx512bw    | avx512bw | 2 step  | 2 step    |
| avx2     | avx2     | avx2        | 2 step   | 2 step  | 2 step    |
| ssse3    | ssse3    | ssse3       | 2 step   | 2 step  | 2 step    |
| dot      | i8mm     | i8mm        | dot      | neon    | neon      |
| sve2     | sve2     | -           | -        | -       | -         |
| sme      | sme      | -           | -        | -       | -         |
| rvv      | rvv      | rvv         | rvv      | rvv     | rvv       |
+----------+----------+-------------+----------+---------+-----------+


Bug: 42280902
Change-Id: I9f83bf3039431f9fb5391bd7d9eb393e186d6bcf
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8175442
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Commit-Queue: Frank Barchard <fbarchard@google.com>
2026-08-03 17:53:19 -07:00
Frank Barchard
0148582bb8 Change all 1 use wrappers to matrix calls
Bug: 42280902
Change-Id: Ieccb1e8eeaec3064fc5d36d2f1233fd38eb2a128
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8177647
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Commit-Queue: Frank Barchard <fbarchard@google.com>
2026-07-31 17:29:30 -07:00
Frank Barchard
1e06475900 [libyuv] Fix color matrix constants in RAWToI420
RAW format in libyuv is Red-first ([R, G, B] in memory), whereas RGB24
is Blue-first ([B, G, R] in memory).

RGBToYMatrixRow and RGBToUVMatrixRow internally expand 3-byte input
into 4-byte [byte0, byte1, byte2, 255]. For RAW, this buffer becomes
[R, G, B, 255] (matching ABGR byte order). RAWToI420 previously passed
&kArgbI601Constants (which expects [B, G, R, 255]) instead of
&kAbgrI601Constants, causing Red and Blue channels to be swapped.

Pass &kAbgrI601Constants in RAWToI420, fix parameter names in
source/convert.cc, and add a unit test.

Test: libyuv_unittest --gtest_filter=*RAWToI420*
Bug: libyuv:537503370

TAG=agy
CONV=2c54c4b5-f515-421b-80b3-079caa9f948b

Change-Id: Ic72470813eaf15e80046c2c01cf804cb827039ab
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8133048
Reviewed-by: richard winterton <rrwinterton@gmail.com>
2026-07-21 18:31:48 -07:00
Wan-Teh Chang
8aeb3a9ca3 I010ToNV12: dispatch Convert16To8Row on halfwidth
The Convert16To8Row function pointer in I010ToNV12 is only ever called
with halfwidth for the chroma planes (the Y plane goes through
Convert16To8Plane which has its own dispatch), but its SIMD variants
were selected based on the alignment of the full luma width. When width
is a multiple of 32 but halfwidth is not, the bare AVX2 kernel was
selected and over-read the chroma sources and over-wrote the temporary
row buffer. Match the MergeUVRow dispatch in the same function and key
on halfwidth.

Bug: chromium:514748734
Change-Id: I4c2a42857828cdcc6505ebaa65d5b6a95b0f7e55
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8031724
Reviewed-by: Frank Barchard <fbarchard@google.com>
Commit-Queue: Wan-Teh Chang <wtc@google.com>
2026-07-01 18:38:27 -07:00
Frank Barchard
4be798d7c5 BGRAToI420 use BgraConstants for a direct conversion using AVX512BW
row win (msvc)
Was C/SSSE3
BGRAToARGB_Opt (594 ms)
BGRAToARGB_Endswap_Opt (609 ms)
BGRAToI420_Opt (122 ms)

Now AVX2
BGRAToARGB_Opt (100 ms)
BGRAToARGB_Endswap_Opt (99 ms)
BGRAToI420_Opt (115 ms)

Clang/GCC AVX512BW
BGRAToARGB_Opt (86 ms)
BGRAToARGB_Endswap_Opt (91 ms)
BGRAToI420_Opt (110 ms)


Bug: 42280902
Change-Id: I52cb2b0cacea8f2f0b138ec3cc521185dbef8595
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7905821
Commit-Queue: Frank Barchard <fbarchard@google.com>
Reviewed-by: richard winterton <rrwinterton@gmail.com>
2026-06-08 12:21:47 -07:00
Wan-Teh Chang
f722313c74 Validate int param is not INT_MIN before negating
Validate that an int parameter is not equal to INT_MIN before negating
it.

Remove redundant src_width > 32768 || src_height > 32768 checks in
callers of ScalePlane(), ScalePlane_16(), ScalePlane_12(), and
UVScale().

Change UVScale() to validate its parameters in the same way as
ScalePlane(), ScalePlane_16(), and ScalePlane_12().

Change-Id: I64e03257cf090760030c966b49c4d23e4cec25e5
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7902889
Reviewed-by: Frank Barchard <fbarchard@google.com>
Commit-Queue: Wan-Teh Chang <wtc@google.com>
2026-06-04 21:55:57 -07:00
Wan-Teh Chang
62fffa9eeb Fix integer overflow when flipping negative height
Treat height == INT_MIN as invalid. Omit explicit height == INT_MIN
check if we disallow height < 32768.

Perform multiplications of stride in the ptrdiff_t type.

Add checks for invalid width and height to some functions.

Bug: 518806561
Change-Id: I5e39fffed7f806852a8758d4b59df919839c0a3b
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7891415
Reviewed-by: Frank Barchard <fbarchard@google.com>
Commit-Queue: Wan-Teh Chang <wtc@google.com>
2026-06-03 16:17:37 -07:00
Frank Barchard
e14b0e2c60 RGB565ToARGB use AVX2 instead of SSE2
Now AVX2/AVX512
ARGB4444ToI420_Opt (204 ms)
RGB565ToI420_Opt (211 ms)
ARGB1555ToI420_Opt (231 ms)
RAWToI420_Opt (197 ms)
RGB24ToI420_Opt (197 ms)

Was SSE2/AVX2
ARGB4444ToI420_Opt (276 ms)
RGB565ToI420_Opt (292 ms)
ARGB1555ToI420_Opt (332 ms)
RAWToI420_Opt (237 ms)
RGB24ToI420_Opt (232 ms)

Bug: libyuv:508639302
Change-Id: I2005189d1b6af15cb5ebef1f6d66b426fa9df8eb
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7891416
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Commit-Queue: Frank Barchard <fbarchard@google.com>
2026-06-02 18:28:02 -07:00
Frank Barchard
3c5fa6ef27 libyuv] Replace hardcoded RGB to YUV functions with Matrix variants
Removes non-matrix implementations for RGB24, RAW, RGB565, ARGB1555,
and ARGB4444 conversions. Introduces RGBToYMatrixRow, RGBToUVMatrixRow,
and equivalent functions for 16-bit and 24-bit formats. These functions
utilize a 2-step conversion internally (to ARGB, then to YUV) inside
row_common.cc for C, AVX2, and NEON, allowing the high-level
convert.cc logic to execute in a single pass using ArgbConstants.

Benchmark on Zen4
Test: libyuv_unittest --gtest_filter=*RGB*ToI420*

Was BT.601-only
ARGBToI420_Opt (115 ms)
ARGB4444ToI420_Opt (190 ms)
RGB565ToI420_Opt (194 ms)
ARGB1555ToI420_Opt (207 ms)
RGB24ToI420_Opt (143 ms)
RGBAToI420_Opt (167 ms)
28.07% ARGBToUVMatrixRow_AVX512BW
19.65% ARGBToYMatrixRow_AVX512BW
11.32% RGBAToUVRow_SSSE3
10.24% ARGB1555ToARGBRow_SSE2
 8.56% ARGB4444ToARGBRow_SSE2
 8.47% RGB565ToARGBRow_SSE2
 4.17% RGBAToYRow_AVX512BW
 4.04% RGB24ToARGBRow_AVX512BW

Now Matrix
ARGBToI420_Opt (124 ms)
ARGB4444ToI420_Opt (287 ms)
RGB565ToI420_Opt (292 ms)
ARGB1555ToI420_Opt (324 ms)
RGB24ToI420_Opt (236 ms)
RGBAToI420_Opt (126 ms)
29.74% ARGBToUVMatrixRow_AVX2
14.58% ARGB1555ToARGBRow_SSE2
12.59% RGB565ToARGBRow_SSE2
11.32% ARGB4444ToARGBRow_SSE2
 9.35% ARGBToYMatrixRow_AVX2
 8.45% RGB24ToARGBRow_SSSE3
 5.56% ARGBToYMatrixRow_AVX512BW
 1.37% ARGBToUVMatrixRow_Any_AVX2
 0.74% ARGBToYMatrixRow_Any_AVX2
 0.49% ARGB4444ToARGBRow_Any_SSE2
 0.46% RGB565ToARGBRow_Any_SSE2
 0.39% ARGB1555ToARGBRow_Any_SSE2
 0.28% RGB24ToARGBRow_Any_SSSE3
 0.11% ARGB4444ToYMatrixRow_AVX2
 0.09% RGB565ToUVMatrixRow_AVX2
 0.09% RGB565ToYMatrixRow_AVX2
 0.07% RGBToYMatrixRow_AVX2
 0.05% ARGB1555ToUVMatrixRow_AVX2
 0.04% ARGB1555ToYMatrixRow_AVX2
 0.03% RGBToUVMatrixRow_AVX2
 0.02% ARGB4444ToUVMatrixRow_AVX2

Bug: libyuv:508639302
Change-Id: I362c0cfe4c86ee1f3ffb569fa4f784b84148f11a
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7891045
Commit-Queue: Frank Barchard <fbarchard@google.com>
Reviewed-by: richard winterton <rrwinterton@gmail.com>
2026-06-01 14:04:07 -07:00
Frank Barchard
957f295ea9 [libyuv] Fix potential UV coalescing overflow in NV12ToI420
Adds a safety check to prevent signed integer overflow in the UV
plane coalescing logic within NV12ToI420. This ensures that
halfwidth * halfheight does not overflow INT_MAX, matching the Y
plane coalescing check and preventing potential undefined behavior
(signed integer overflow) which could lead to negative widths being
passed to SIMD functions.

Test: libyuv_unittest --gtest_filter=*NV12Crop*
Bug: None

CONV=6401df25-4d5d-4595-a231-f72c2c8e78df
TAG=agy
R=wtc@google.com

Change-Id: I15a51609a1e000a82f4b6958b4ada444efb1f2f4
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7886824
Commit-Queue: Wan-Teh Chang <wtc@google.com>
Reviewed-by: Wan-Teh Chang <wtc@google.com>
2026-05-29 22:53:29 -07:00
Wan-Teh Chang
d2c6dd5e6a Fix integer overflow in two convert functions
Fix integer overflow in buffer allocation size calculations in the
align_buffer_64() macro and the I422ToNV21() and
Android420ToARGBMatrix() functions.

Based on a CL autogenerated by MendIt (go/androidmendit):
https://googleplex-android-review.googlesource.com/c/platform/external/libyuv/+/39981732

Bug: 511821134
Change-Id: Ie1728c3ad337d460d9b85979489a817cc97e3bf3
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7886817
Reviewed-by: Frank Barchard <fbarchard@google.com>
Commit-Queue: Wan-Teh Chang <wtc@google.com>
2026-05-29 19:26:14 -07:00
Wan-Teh Chang
c98edcc8dc Don't coalesce rows if width*height would overflow
Audit all occurrences of "width *= height;" in the libyuv source code.
Make sure height > 0 and (ptrdiff_t)width * height <= INT_MAX before
executing width *= height.

Bug: chromium:517339758
Change-Id: I143a41c66492a6e4c48b6aa2a1c4a2ae974ceeb1
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7883816
Commit-Queue: Wan-Teh Chang <wtc@google.com>
Reviewed-by: Frank Barchard <fbarchard@google.com>
2026-05-29 11:57:47 -07:00
Frank Barchard
9d98aaefe7 InterpolateRow for Visual C
- remove InterpolateRow_SSSE3
- optimize ARGBToUV444MatrixRow_AVX2 to use unsigned pixels

5.7x faster on AMD Zen4

Was C
TestInterpolatePlane (144 ms)
TestInterpolatePlane_16 (142 ms)

Now AVX2
TestInterpolatePlane (25 ms)
TestInterpolatePlane_16 (48 ms)

Was signed
ARGBToJ444_Opt (157 ms)
Now unsigned
ARGBToJ444_Opt (155 ms)

Bug: None
Change-Id: I903109668ff9cfedaddad1ad75411393b3226f41
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7856498
Reviewed-by: richard winterton <rrwinterton@gmail.com>
2026-05-18 17:28:46 -07:00
Frank Barchard
cb061d0378 Unittests use ASSERT instead of EXPECT
Bug: libyuv:508639302
Change-Id: I22c35e08f3b6db1a656192877c1fb1bf4e96d6f5
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7838659
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Commit-Queue: Frank Barchard <fbarchard@google.com>
2026-05-11 19:10:47 -07:00
Frank Barchard
4b4e68b372 ABGRToJ420 call ARGBToI420Matrix
- Standardize libyuv ARGB-family (ARGB, ABGR, RGBA, BGRA) to YUV conversion by utilizing the generic MatrixRow architecture and explicit ArgbConstants.
- Consolidated ARGBToI420, ABGRToI420, BGRAToI420, and RGBAToI420 as wrappers for ARGBToI420Matrix.
- Refactored ABGRToJ420, ABGRToJ422, and ABGRToI422 to use generic matrix functions.
- Added matrix-based versions for NV21, I400, YUY2, and UYVY.
- Updated RAW and RGB24 to I420/I422/I444 dispatchers to use MatrixRow logic and explicit constants.
- Fixed parameter swap bugs in ARGBToI422, ARGBToJ422, and ABGRToJ422.
- Fixed a bug in the generic C implementation of matrix row functions ensuring all 4 channels are processed correctly for all ARGB-family formats.
- Moved kShuffleAARRGGBB in row_gcc.cc to the top of the libyuv namespace for visibility.
- Cleaned up redundant format-specific row implementations.

Bug: libyuv:42280902
Change-Id: I67ffa4c476abc0d2dcc4650510d7bda91b65988e
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7830291
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Commit-Queue: Frank Barchard <fbarchard@google.com>
2026-05-08 15:23:30 -07:00
Frank Barchard
4aacbbdfb4 Refactored RGB/RAW to YUV color conversion functions to use generic Matrix-based functions parameterized by ArgbConstants.
This consolidation standardizes conversion logic, improves code
maintainability, and provides flexible support for various color spaces
(e.g., BT.601, JPEG full
  range).

Key Modifications:
 - Function Consolidation: Refactored several high-level conversion functions into lightweight wrappers around generic Matrix variants:
     - ARGBToI420 → ARGBToI420Matrix
     - ARGBToI444 → ARGBToI444Matrix
     - ARGBToI422 → ARGBToI422Matrix
     - ARGBToNV12 → ARGBToNV12Matrix
     - RAWToJ400, RGB24ToJ400 → RGBToI400Matrix
     - RAWToI444, RAWToJ444 → RGBToI444Matrix
 - 2-Pass Conversions: Updated RGB565ToI420, ARGB1555ToI420, and ARGB4444ToI420 to utilize 2-pass conversions via RGBToI420Matrix.
 - Standardization: Refactored ARGBToNV21, ARGBToYUY2, and ARGBToUYVY to use parameterized matrix row functions (ARGBToYMatrixRow,
   ARGBToUVMatrixRow).
 - Legacy Cleanup: Replaced legacy calls to ARGBToYJRow with the parameterized ARGBToYMatrixRow in the ARGBSobelize helper.
 - Internal Integration: Included libyuv/convert_from_argb.h in planar_functions.cc and ensured all new matrix symbols are properly
   declared/exported (LIBYUV_API).

Bug: libyuv:42280902
Change-Id: Ied5fd9899767427e3a03cdcfbeaff3e9d502374a
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7822033
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Commit-Queue: Frank Barchard <fbarchard@google.com>
2026-05-06 20:02:47 -07:00
Frank Barchard
125f151316 ARGBToNV12 use Matrix
Refactored Matrix functions (ARGBToI420Matrix, ARGBToI422Matrix, ARGBToI444Matrix and ARGBToNV12Matrix)
  and updated their CPU dispatch logic.

ARGBToNV12 clang
 68.05% ARGBToUVMatrixRow_AVX512BW
 21.04% ARGBToYMatrixRow_AVX512BW
  2.88% MergeUVRow_AVX512BW

ARGBToNV12 rowwin
 61.26% ARGBToUVMatrixRow_AVX2
 25.43% ARGBToYMatrixRow_AVX2
  3.09% MergeUVRow_AVX2

ARM on One Plus 15
 42.98% libyuv::ARGBToUVMatrixRow_SVE_SC()
 38.95% ARGBToYMatrixRow_NEON_DotProd
  2.96% MergeUVRow_NEON
  0.18% ARGBToUVMatrixRow_SVE2

ARGBToI420
 72.28% ARGBToUVMatrixRow_AVX512BW
 19.04% ARGBToYMatrixRow_AVX512BW

ARGBToI422
 77.46% ARGBToUVMatrixRow_AVX512BW
 15.55% ARGBToYMatrixRow_AVX512BW

ARGBToI444
 67.03% ARGBToYMatrixRow_AVX512BW
 24.80% ARGBToUV444MatrixRow_AVX512BW

Bug: libyuv:42280902
Change-Id: I463ebcdb70cb669a1ce1a81102b8fd2fb3943bd3
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7819051
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Commit-Queue: Frank Barchard <fbarchard@google.com>
2026-05-05 18:17:19 -07:00
Frank Barchard
2143edfa7a ARGBToUVMatrixRow_NEON arm32 reimplemented for GCC
Bug: libyuv:508639302
Change-Id: Ib120373d799c66926a64c980873034be262d8848
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7810481
Commit-Queue: Frank Barchard <fbarchard@google.com>
Reviewed-by: Justin Green <greenjustin@google.com>
2026-05-04 11:38:45 -07:00
Frank Barchard
f2ac6db694 RAWToNV21 using SME, SVE, I8MM or Neon
Pixel 9 Now SVE2 2 pass LibYUVConvertTest.RAWToNV21_Opt (364 ms)
 31.76% libyuv::ARGBToUVMatrixRow_SVE_SC()
 30.38% RAWToARGBRow_SVE2
 26.81% ARGBToYMatrixRow_NEON_DotProd
  3.26% MergeUVRow_NEON

Was NEON 1 pass LibYUVConvertTest.RAWToJNV21_Opt (295 ms)
 44.14% RAWToYJRow_NEON
 41.91% RAWToUVJRow_NEON
  5.11% MergeUVRow_NEON

Clang on Intel Skylake clang [ OK ] LibYUVConvertTest.RAWToJNV21_Opt
(301 ms) visual c (row_win) [ OK ] LibYUVConvertTest.RAWToJNV21_Opt
(2056 ms)

clang [ OK ] LibYUVConvertTest.RAWToJNV21_Opt (275 ms) visual c [ OK ]
LibYUVConvertTest.RAWToJNV21_Opt (365 ms)

Bug: libyuv:42280902
Change-Id: Iaba558ebe96ce6b9881ee9335ba72b8aac390cde
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7802432
Commit-Queue: Frank Barchard <fbarchard@google.com>
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
2026-04-29 13:11:04 -07:00
Frank Barchard
4afb965416 RAWToARGB use AVX512BW
Bug: libyuv:42280902
Change-Id: I7a80fd64d97b6d411316819df0fd917d609a173b
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7787163
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Commit-Queue: Frank Barchard <fbarchard@google.com>
2026-04-22 16:56:46 -07:00
Frank Barchard
bd2c4c76ec RAWToARGB AVX512VBMI
Bug: libyuv:42280902
Change-Id: I1c7f432f004079357a00515785bc524c459ed4b9
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7787160
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Commit-Queue: Frank Barchard <fbarchard@google.com>
2026-04-22 14:48:29 -07:00
Frank Barchard
d445250d8b Replace RAWToY/RGB24ToY with RGBToYMatrix
Bug: libyuv:42280902
Change-Id: I6ddebd492036c416550fc045eb39493dea73246b
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7784094
Commit-Queue: Frank Barchard <fbarchard@google.com>
Reviewed-by: richard winterton <rrwinterton@gmail.com>
2026-04-21 17:11:14 -07:00
Frank Barchard
81f698829b Add RGBToNV21Matrix function
- implement wrappers with RAW, RGB24, NV21 and JNV21 to call it.

Zen5
Was [       OK ] LibYUVConvertTest.RAWToJNV21_Opt (1146 ms)
Now [       OK ] LibYUVConvertTest.RAWToJNV21_Opt (1446 ms)
reason - the new code uses 1 pass for RAWToY but 2 pass for RAWToARGB,ARGBToUV.  needs 1 RGBToUV

Bug: libyuv:42280902
Change-Id: Ife6fbed0829484045409e6d42b85cec1d1fd6052
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7780026
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Commit-Queue: Frank Barchard <fbarchard@google.com>
2026-04-20 18:03:34 -07:00
Frank Barchard
9f13b2814d add RGBToYMatrixRow_AVX2
Adds RGBToYMatrixRow_AVX2 which reads 24 bit RGB values by reading 3 vectors instead of 4 and permutes them into 4 ARGB vectors before conversion.
Also adds RGBToYMatrixRow_Opt and RGBToYMatrixRow_2Step_Opt to convert_argb_test.cc to benchmark and compare the direct AVX2 conversion vs a 2-step approach.

./libyuv_test '--gunit_filter=*RAWToJ400_Opt' --libyuv_width=1280 --libyuv_height=720 --libyuv_repeat=10000 --libyuv_flags=-1 --libyuv_cpu_info=-1

AMD Zen 5
Was LibYUVConvertTest.RAWToJ400_Opt (757 ms)
Now LibYUVConvertTest.RAWToJ400_Opt (699 ms)

Intel Skylake
Was LibYUVConvertTest.RAWToJ400_Opt (1705 ms)
Now LibYUVConvertTest.RAWToJ400_Opt (1426 ms)

Bug: 477295731
Change-Id: I29866baf4ad5fe7a3725e4a01f2fe24649510a7d
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7777325
Reviewed-by: Frank Barchard <fbarchard@chromium.org>
Reviewed-by: Justin Green <greenjustin@google.com>
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Commit-Queue: Frank Barchard <fbarchard@chromium.org>
2026-04-20 12:52:44 -07:00
Frank Barchard
ace7c4573c Add ARGBToUV444MatrixRow_RVV, ARGBToUVMatrixRow_RVV, and wrappers
This change implements ARGBToUV444MatrixRow_RVV, ARGBToUVMatrixRow_RVV,
and their wrappers (ARGBToUVRow_RVV, ARGBToUVJRow_RVV, etc.) using RVV
intrinsics, mirroring the NEON/AVX2 designs. It wires them into the
build and dispatch systems.

LIBYUV_RVV_HAS_TUPLE_TYPE is always true on new compilers. This macro
has been removed, assuming it is true everywhere, reducing the amount of
code in row_rvv.cc, scale_rvv.cc, and row.h.

Tested via: ~/bin/doyuv3v && ~/bin/runyuv3v TestARGBToI444Matrix
~/bin/doyuv3av

Bug: libyuv:42280902
Change-Id: I36d305386b297d69023c068aa9c62ab6b2ad039c
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7769956
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Commit-Queue: Frank Barchard <fbarchard@chromium.org>
2026-04-16 20:52:43 -07:00
Frank Barchard
e034c41661 Port ARGBToUVMatrixRow from AVX2 to AVX512BW
Benchmark on Icelake Xeon
Now AVX512BW:
[       OK ] LibYUVConvertTest.ARGBToNV12_Opt (1723 ms)
Was AVX2:
[       OK ] LibYUVConvertTest.ARGBToNV12_Opt (2144 ms)

- Added `ARGBToUVMatrixRow_AVX512BW` implementation in `source/row_gcc.cc`.
- Added corresponding `ARGBToUVRow_AVX512BW` and `ABGRToUVRow_AVX512BW` functions.
- Added unaligned wrappers `ARGBToUVRow_Any_AVX512BW` and `ABGRToUVRow_Any_AVX512BW` in `source/row_any.cc`.
- Updated `source/row_any.cc` to correctly size `vin` and `vout` buffers for AVX512BW width and adjusted the `ANY12MS` and `ANY12S` macros to handle `MASK=63`.
- Updated `include/libyuv/row.h` with the required AVX512BW headers and definitions, scoped appropriately.
- Wired all callers of `ARGBToUVRow_AVX2` and related functions in `source/convert.cc` and `source/convert_from_argb.cc` to dynamically use the `AVX512BW` implementations if the CPU flag indicates AVX-512BW support.
- Optimized AVX-512 code to generate the `-1` multiplier in a single instruction (`vpternlogd`) and reused it across word (`vpmaddwd`) dot products. Handled the resulting negation by replacing a subtraction with `vpaddw` offset adjustment.

Bug: 477295731
R=dalecurtis@chromium.org, rrwinterton@gmail.com

Change-Id: Ida5fb27e59ae4c1c3824737f009b80549cd20a06
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7763257
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Commit-Queue: Frank Barchard <fbarchard@chromium.org>
2026-04-14 16:15:31 -07:00
Frank Barchard
cbc64c353c Port ARGBToYRow_AVX2 usages to dynamically use ARGBToYRow_AVX512BW
I have successfully ported the usage of ARGBToYRow_AVX2 to dynamically detect and utilize ARGBToYRow_AVX512BW when available.

  Here's a summary of the changes:
   1. Source Modifications: In both source/convert.cc and source/convert_from_argb.cc, I searched for all references where ARGBToYRow_AVX2 was
      being conditionally used (which operates on 32 pixels).
   2. AVX512BW Detection: Immediately following those blocks, I injected a new check for kCpuHasAVX512BW. If the CPU flag is present, the logic
      now utilizes ARGBToYRow_Any_AVX512BW by default, falling back to the fully aligned ARGBToYRow_AVX512BW when the width is aligned to 64
      bytes.
   3. Profiling: After building and compiling the tests (doyuv3x), I validated the change using perfyuv3 ARGBToNV12_Opt | cat. The test
      successfully executed and the performance profile indicated that ARGBToYRow_AVX512BW successfully executed (taking up ~18% of CPU cycles,
      replacing the previous AVX2 specific instruction overhead for the Y row extraction).

  The HAS_ARGBTOYROW_AVX512BW macro implementation now fully supports all AVX2 conversion paths to utilize AVX512BW when the system processor
  flags allow it!

R=richard, rrwinterton@gmail.com

Change-Id: Iad811e12d301f5621e6f6d039105420861ade43e
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7760779
Commit-Queue: Frank Barchard <fbarchard@chromium.org>
Reviewed-by: richard winterton <rrwinterton@gmail.com>
2026-04-14 11:42:59 -07:00
Frank Barchard
893eacf9b4 ARGBToY for AVX512
- add ARGBToYMatrixRow_AVX512BW
- refactor SSE and AVX to use Matrix functions, making old functions
  call the new ones.

Zen5 1280x720
Was AVX2   LibYUVConvertTest.ARGBToI444_Opt (1125 ms)
Now AVX512 LibYUVConvertTest.ARGBToI444_Opt (641 ms)

Details by Gemini:
  1. Created 3 new Matrix functions:
    Added ARGBToYMatrixRow_SSSE3, ARGBToYMatrixRow_AVX2, and
    ARGBToYMatrixRow_AVX512BW to source/row_gcc.cc. These take the
    const struct ArgbConstants* c parameter similarly to
    ARGBToUV444MatrixRow_*. The x86 vector instructions dynamically
    calculate the needed values using the properties of the constants
    struct, including using vpmaddwd inside the AVX512 code to offset
    the lack of a native vphaddw.

  2. Replaced Old Functions with Wrappers:
    Modified the existing implementations of ARGBToYRow_SSSE3,
    ARGBToYJRow_SSSE3, ABGRToYRow_SSSE3, ABGRToYJRow_SSSE3,
    RGBAToYRow_SSSE3, RGBAToYJRow_SSSE3, BGRAToYRow_SSSE3 (and their
    _AVX2 equivalents) in source/row_gcc.cc to act as inline wrappers
    calling the new ARGBToYMatrixRow_* functions, passing the right
    matrix parameters (e.g. &kArgbI601Constants, &kArgbJPEGConstants,
    &kAbgrI601Constants).

  3. Added row_any.cc Handlers:
    Added ANY11MC definitions to source/row_any.cc to autogenerate
    ARGBToYMatrixRow_Any_SSSE3, ARGBToYMatrixRow_Any_AVX2, and
    ARGBToYMatrixRow_Any_AVX512BW which safely handles non-aligned
    tails.

  4. Updated include/libyuv/row.h:
    Updated the headers with the proper void declarations for all newly
    generated Matrix and Any_ variants. Also defined
    HAS_ARGBTOYROW_AVX512BW in the CPU macros.

  5. Tested the Implementations:
    Compiled and tested on Linux x86, which resulted in all tests passing
    cleanly. Also successfully completed all Windows 32-bit build checks
    ensuring 32-bit regression prevention without issues.

Bug: 477295731
Change-Id: I4f5eec9a961e24a9d760d0a1c0810fb5e29a0bd1
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7759494
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: richard winterton <rrwinterton@gmail.com>
2026-04-13 17:26:07 -07:00
Frank Barchard
4c3d7d517a ARGBToUV444 for AVX512
1.27x faster on AMD Zen5 (turin)

Now AVX512
perf record ./libyuv_test '--gunit_filter=*ARGBToI444_Opt' --libyuv_width=1280 --libyuv_height=720 --libyuv_repeat=10000 --libyuv_flags=-1 --libyuv_cpu_info=-1

[       OK ] LibYUVConvertTest.ARGBToI444_Opt (1071 ms)
Overhead  Symbol
  53.49%  ARGBToYRow_AVX2
  44.70%  ARGBToUV444Row_AVX512BW

Was AVX2
[       OK ] LibYUVConvertTest.ARGBToI444_Opt (1369 ms)
  61.06%  ARGBToUV444Row_AVX2
  37.67%  ARGBToYRow_AVX2

Bug:  libyuv:42280902
Change-Id: I306fbac656d6f7834ce1559e86d01eb34931ec3c
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7738362
Commit-Queue: Frank Barchard <fbarchard@chromium.org>
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
2026-04-08 19:25:41 -07:00
Dale Curtis
1170363ce5 Add Gemini implementation for NEON32 RGB to YUV matrix operations
These are about 25% faster than the C versions.

Bug: libyuv:42280902

Change-Id: I8b298670ee5f3ed5db35527fc41d6d9a51b020a1
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7573682
Reviewed-by: Frank Barchard <fbarchard@chromium.org>
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
2026-03-23 16:30:44 -07:00
Dale Curtis
b1cacfb38f Unify X86/X64 versions of ARGBToI4xxMatrix functions
Change-Id: Iead13414414543e5f10ba9ba47a6ceaeb3113dee
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7562443
Reviewed-by: Frank Barchard <fbarchard@chromium.org>
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: Wan-Teh Chang <wtc@google.com>
2026-03-18 16:27:07 -07:00
Dale Curtis
2c21d57319 Add ABGR versions of the ArgbConstants structures
This allows for ABGR conversion using the same methods

Bug: libyuv:42280902
Change-Id: I5566e3150b30573a2326a900ce31ab095f8935f9
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/7564316
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: Wan-Teh Chang <wtc@google.com>
2026-03-17 17:28:51 -07:00