mirror of
https://chromium.googlesource.com/libyuv/libyuv
synced 2026-10-28 18:07:12 +08:00
Implement RAWToRGB24Row_WASMSIMD and RAWToRGB24Row_Any_WASMSIMD in source/row_wasm.cc for RGB24ToRAW and RAWToRGB24 conversions: - Process 16 pixels (48 bytes) per loop iteration using three 128-bit loads, three byte-wise shuffles, and four 2-way blends. - Use wasm_i8x16_relaxed_swizzle when __wasm_relaxed_simd__ is enabled (compiling to a single vpshufb on x86 without bounds-checking overhead) and fall back to wasm_i8x16_swizzle for baseline SIMD128. - Add kCpuHasWASM (0x100) and kCpuHasWASMSIMD (0x101) CPU feature flags and enable -msimd128 in BUILD.bazel, BUILD.gn, and CMakeLists.txt for WebAssembly targets. Performance (RAWToRGB24_Opt, 1280x720, V8 d8): CPU WASM C SIMD128 Relaxed SIMD Spd Rlx Spd ------------------------------------------------------------------- AMD Zen 4 595.0 us 137.0 us 84.0 us 4.34x 7.08x AMD Zen 3 708.0 us 148.0 us 107.0 us 4.78x 6.62x AMD Zen 5 375.0 us 107.0 us 67.0 us 3.50x 5.60x ARM Neoverse-V2 638.0 us 118.0 us 116.0 us 5.41x 5.50x ARM Neoverse-N1 1046.0 us 294.0 us 294.0 us 3.56x 3.56x Intel Ice Lake 707.0 us 209.0 us 220.0 us 3.38x 3.21x Intel Haswell 1110.0 us 344.0 us 360.0 us 3.23x 3.08x Intel Emerald Rapids 519.0 us 207.0 us 208.0 us 2.51x 2.50x Intel Sapphire Rapids 551.0 us 220.0 us 255.0 us 2.50x 2.16x ARM Cortex-A53 14440.0 us 8660.0us 6920.0us 1.67x 2.09x Intel Granite Rapids 453.0 us 225.0 us 221.0 us 2.01x 2.05x Bug: 42271072 Test: libyuv_test --gunit_filter=*RAWToRGB24*:*RGB24ToRAW*:*Cpu* Change-Id: Id902668263a2ab70aa300eeeea18851490c917b5 Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8515581 Reviewed-by: richard winterton <rrwinterton@gmail.com> Commit-Queue: Frank Barchard <fbarchard@google.com>
310 lines
11 KiB
CMake
310 lines
11 KiB
CMake
# CMakeLists for libyuv
|
|
# Originally created for "roxlu build system" to compile libyuv on windows
|
|
# Run with -DUNIT_TEST=ON to build unit tests
|
|
|
|
cmake_minimum_required( VERSION 3.16 )
|
|
project ( YUV C CXX ) # "C" is required even for C++ projects
|
|
option( UNIT_TEST "Built unit tests" OFF )
|
|
option( LIBYUV_DISABLE_JPEG "Disable JPEG support" OFF )
|
|
|
|
include(CheckCSourceCompiles)
|
|
|
|
set ( ly_base_dir ${PROJECT_SOURCE_DIR} )
|
|
set ( ly_src_dir ${ly_base_dir}/source )
|
|
set ( ly_inc_dir ${ly_base_dir}/include )
|
|
set ( ly_tst_dir ${ly_base_dir}/unit_test )
|
|
set ( ly_lib_name yuv )
|
|
set ( ly_lib_static ${ly_lib_name} )
|
|
set ( ly_lib_shared ${ly_lib_name}_shared )
|
|
|
|
# We cannot use GLOB here since we want to be able to separate out files that
|
|
# need particular flags to enable architecture extensions like AArch64's SVE.
|
|
# TODO: More of these files could be separated out for different architectures.
|
|
set ( ly_common_source_files
|
|
${ly_src_dir}/compare.cc
|
|
${ly_src_dir}/compare_common.cc
|
|
${ly_src_dir}/compare_gcc.cc
|
|
${ly_src_dir}/compare_win.cc
|
|
${ly_src_dir}/convert.cc
|
|
${ly_src_dir}/convert_argb.cc
|
|
${ly_src_dir}/convert_from.cc
|
|
${ly_src_dir}/convert_from_argb.cc
|
|
${ly_src_dir}/convert_jpeg.cc
|
|
${ly_src_dir}/convert_to_argb.cc
|
|
${ly_src_dir}/convert_to_i420.cc
|
|
${ly_src_dir}/cpu_id.cc
|
|
${ly_src_dir}/mjpeg_decoder.cc
|
|
${ly_src_dir}/mjpeg_validate.cc
|
|
${ly_src_dir}/planar_functions.cc
|
|
${ly_src_dir}/rotate.cc
|
|
${ly_src_dir}/rotate_any.cc
|
|
${ly_src_dir}/rotate_argb.cc
|
|
${ly_src_dir}/rotate_common.cc
|
|
${ly_src_dir}/rotate_gcc.cc
|
|
${ly_src_dir}/rotate_win.cc
|
|
${ly_src_dir}/row_any.cc
|
|
${ly_src_dir}/row_common.cc
|
|
${ly_src_dir}/row_gcc.cc
|
|
${ly_src_dir}/row_rvv.cc
|
|
${ly_src_dir}/row_wasm.cc
|
|
${ly_src_dir}/row_win.cc
|
|
${ly_src_dir}/scale.cc
|
|
${ly_src_dir}/scale_any.cc
|
|
${ly_src_dir}/scale_argb.cc
|
|
${ly_src_dir}/scale_common.cc
|
|
${ly_src_dir}/scale_gcc.cc
|
|
${ly_src_dir}/scale_rgb.cc
|
|
${ly_src_dir}/scale_rvv.cc
|
|
${ly_src_dir}/scale_uv.cc
|
|
${ly_src_dir}/scale_win.cc
|
|
${ly_src_dir}/video_common.cc)
|
|
|
|
file ( GLOB_RECURSE ly_unittest_sources ${ly_tst_dir}/*.cc )
|
|
list ( SORT ly_unittest_sources )
|
|
|
|
include_directories( BEFORE ${ly_inc_dir} )
|
|
|
|
if(MSVC)
|
|
add_definitions ( -D_CRT_SECURE_NO_WARNINGS )
|
|
endif()
|
|
|
|
# Need to set PIC to allow creating shared libraries from object file libraries.
|
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
|
|
# Build the set of objects that do not need to be compiled with flags to enable
|
|
# particular architecture features.
|
|
add_library( ${ly_lib_name}_common_objects OBJECT ${ly_common_source_files} )
|
|
set(ly_lib_parts $<TARGET_OBJECTS:${ly_lib_name}_common_objects>)
|
|
|
|
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" SYSPROC)
|
|
set(LOONGARCH64_ALIASES loongarch64)
|
|
list(FIND LOONGARCH64_ALIASES "${SYSPROC}" LOONGARCH64MATCH)
|
|
|
|
if(LOONGARCH64MATCH GREATER "-1")
|
|
set(LOONGARCH64 1)
|
|
endif()
|
|
|
|
if(NOT MSVC)
|
|
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" arch_lowercase)
|
|
|
|
if(arch_lowercase MATCHES "^arm" AND NOT arch_lowercase STREQUAL "arm64")
|
|
# Enable Arm Neon kernels.
|
|
add_definitions(-DLIBYUV_NEON=1)
|
|
add_library(${ly_lib_name}_neon OBJECT
|
|
${ly_src_dir}/compare_neon.cc
|
|
${ly_src_dir}/rotate_neon.cc
|
|
${ly_src_dir}/row_neon.cc
|
|
${ly_src_dir}/scale_neon.cc)
|
|
target_compile_options(${ly_lib_name}_neon PRIVATE -mfpu=neon)
|
|
list(APPEND ly_lib_parts $<TARGET_OBJECTS:${ly_lib_name}_neon>)
|
|
endif()
|
|
|
|
if(arch_lowercase STREQUAL "aarch64" OR arch_lowercase STREQUAL "arm64")
|
|
# Enable AArch64 Neon dot-product and i8mm kernels.
|
|
add_library(${ly_lib_name}_neon64 OBJECT
|
|
${ly_src_dir}/compare_neon64.cc
|
|
${ly_src_dir}/rotate_neon64.cc
|
|
${ly_src_dir}/row_neon64.cc
|
|
${ly_src_dir}/scale_neon64.cc)
|
|
target_compile_options(${ly_lib_name}_neon64 PRIVATE -march=armv8.2-a+dotprod+i8mm)
|
|
list(APPEND ly_lib_parts $<TARGET_OBJECTS:${ly_lib_name}_neon64>)
|
|
|
|
# Enable AArch64 SVE kernels.
|
|
add_library(${ly_lib_name}_sve OBJECT
|
|
${ly_src_dir}/row_sve.cc)
|
|
target_compile_options(${ly_lib_name}_sve PRIVATE -march=armv8.5-a+i8mm+sve2)
|
|
list(APPEND ly_lib_parts $<TARGET_OBJECTS:${ly_lib_name}_sve>)
|
|
|
|
# Check whether the compiler can compile SME functions; this fails
|
|
# with Clang for Windows.
|
|
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
|
set(OLD_CMAKE_TRY_COMPILE_TARGET_TYPE ${CMAKE_TRY_COMPILE_TARGET_TYPE})
|
|
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -march=armv8.5-a+i8mm+sme")
|
|
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
|
check_c_source_compiles("
|
|
__arm_locally_streaming void func(void) { }
|
|
int main(void) { return 0; }
|
|
" CAN_COMPILE_SME)
|
|
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
|
|
set(CMAKE_TRY_COMPILE_TARGET_TYPE ${OLD_CMAKE_TRY_COMPILE_TARGET_TYPE})
|
|
|
|
if (CAN_COMPILE_SME)
|
|
# Enable AArch64 SME kernels.
|
|
add_library(${ly_lib_name}_sme OBJECT
|
|
${ly_src_dir}/rotate_sme.cc
|
|
${ly_src_dir}/row_sme.cc
|
|
${ly_src_dir}/scale_sme.cc)
|
|
target_compile_options(${ly_lib_name}_sme PRIVATE -march=armv8.5-a+i8mm+sme)
|
|
list(APPEND ly_lib_parts $<TARGET_OBJECTS:${ly_lib_name}_sme>)
|
|
else()
|
|
add_definitions(-DLIBYUV_DISABLE_SME)
|
|
endif()
|
|
endif()
|
|
|
|
if(arch_lowercase MATCHES "^riscv")
|
|
option(USE_RVV "Enable RISC-V Vector" ON)
|
|
if(USE_RVV)
|
|
if(NOT RISCV_COMPILER_FLAGS)
|
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8 OR arch_lowercase STREQUAL "riscv64")
|
|
set(RISCV_COMPILER_FLAGS "-march=rv64gcv")
|
|
else()
|
|
set(RISCV_COMPILER_FLAGS "-march=rv32gcv")
|
|
endif()
|
|
endif()
|
|
|
|
include(CheckCSourceCompiles)
|
|
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
|
set(OLD_CMAKE_TRY_COMPILE_TARGET_TYPE ${CMAKE_TRY_COMPILE_TARGET_TYPE})
|
|
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${RISCV_COMPILER_FLAGS} -fno-tree-vectorize -fno-tree-slp-vectorize")
|
|
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
|
check_c_source_compiles("
|
|
int main(void) { return 0; }
|
|
" CAN_COMPILE_RVV)
|
|
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
|
|
set(CMAKE_TRY_COMPILE_TARGET_TYPE ${OLD_CMAKE_TRY_COMPILE_TARGET_TYPE})
|
|
|
|
if(CAN_COMPILE_RVV)
|
|
if(NOT CMAKE_C_FLAGS MATCHES "-march=" AND NOT CMAKE_C_FLAGS MATCHES "-mcpu=")
|
|
set(CMAKE_C_FLAGS "${RISCV_COMPILER_FLAGS} -fno-tree-vectorize -fno-tree-slp-vectorize ${CMAKE_C_FLAGS}")
|
|
set(CMAKE_CXX_FLAGS "${RISCV_COMPILER_FLAGS} -fno-tree-vectorize -fno-tree-slp-vectorize ${CMAKE_CXX_FLAGS}")
|
|
endif()
|
|
else()
|
|
add_definitions(-DLIBYUV_DISABLE_RVV)
|
|
endif()
|
|
else()
|
|
add_definitions(-DLIBYUV_DISABLE_RVV)
|
|
endif()
|
|
endif()
|
|
|
|
if(arch_lowercase MATCHES "^wasm" OR EMSCRIPTEN)
|
|
set(CMAKE_C_FLAGS "-msimd128 ${CMAKE_C_FLAGS}")
|
|
set(CMAKE_CXX_FLAGS "-msimd128 ${CMAKE_CXX_FLAGS}")
|
|
endif()
|
|
endif()
|
|
|
|
if(LOONGARCH64)
|
|
include(CheckCXXSourceCompiles)
|
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-narrowing")
|
|
check_cxx_source_compiles("
|
|
int main(int argc, char **argv) {
|
|
__asm__ volatile (
|
|
\"vadd.w $vr0, $vr1, $vr1\"
|
|
);
|
|
return 0; }" SUPPORTS_LSX)
|
|
|
|
check_cxx_source_compiles("
|
|
int main(int argc, char **argv) {
|
|
__asm__ volatile (
|
|
\"xvadd.w $xr0, $xr1, $xr1\"
|
|
);
|
|
return 0; }" SUPPORTS_LASX)
|
|
|
|
if(SUPPORTS_LSX)
|
|
# These kernels use only LSX (128-bit) instructions and must not be
|
|
# compiled with -mlasx, which would let the compiler emit 256-bit LASX
|
|
# code (e.g. for stack-array copies) and crash on LSX-only CPUs.
|
|
add_library(${ly_lib_name}_lsx OBJECT
|
|
${ly_src_dir}/rotate_lsx.cc
|
|
${ly_src_dir}/row_lsx.cc
|
|
${ly_src_dir}/scale_lsx.cc)
|
|
target_compile_options(${ly_lib_name}_lsx PRIVATE -mlsx)
|
|
list(APPEND ly_lib_parts $<TARGET_OBJECTS:${ly_lib_name}_lsx>)
|
|
endif()
|
|
if(SUPPORTS_LASX)
|
|
add_library(${ly_lib_name}_lasx OBJECT
|
|
${ly_src_dir}/row_lasx.cc)
|
|
target_compile_options(${ly_lib_name}_lasx PRIVATE -mlasx)
|
|
list(APPEND ly_lib_parts $<TARGET_OBJECTS:${ly_lib_name}_lasx>)
|
|
endif()
|
|
endif()
|
|
|
|
# this creates the static library (.a)
|
|
add_library( ${ly_lib_static} STATIC ${ly_lib_parts})
|
|
|
|
# this creates the shared library (.so)
|
|
add_library( ${ly_lib_shared} SHARED ${ly_lib_parts})
|
|
set_target_properties( ${ly_lib_shared} PROPERTIES OUTPUT_NAME "${ly_lib_name}" )
|
|
set_target_properties( ${ly_lib_shared} PROPERTIES PREFIX "lib" )
|
|
if(WIN32)
|
|
set_target_properties( ${ly_lib_shared} PROPERTIES IMPORT_PREFIX "lib" )
|
|
endif()
|
|
|
|
# this creates the cpuid tool
|
|
add_executable ( cpuid ${ly_base_dir}/util/cpuid.c )
|
|
target_link_libraries ( cpuid ${ly_lib_static} )
|
|
|
|
# this creates the conversion tool
|
|
add_executable ( yuvconvert ${ly_base_dir}/util/yuvconvert.cc )
|
|
target_link_libraries ( yuvconvert ${ly_lib_static} )
|
|
|
|
# this creates the yuvconstants tool
|
|
add_executable ( yuvconstants ${ly_base_dir}/util/yuvconstants.c )
|
|
target_link_libraries ( yuvconstants ${ly_lib_static} )
|
|
if(NOT MSVC)
|
|
target_link_libraries ( yuvconstants m )
|
|
endif()
|
|
|
|
if (NOT LIBYUV_DISABLE_JPEG)
|
|
find_package ( JPEG )
|
|
if (JPEG_FOUND)
|
|
include_directories( ${JPEG_INCLUDE_DIR} )
|
|
target_link_libraries( ${ly_lib_shared} ${JPEG_LIBRARY} )
|
|
add_definitions( -DHAVE_JPEG )
|
|
endif()
|
|
endif()
|
|
|
|
if(UNIT_TEST)
|
|
find_library(GTEST_LIBRARY gtest)
|
|
if(GTEST_LIBRARY STREQUAL "GTEST_LIBRARY-NOTFOUND")
|
|
set(GTEST_SRC_DIR_DEFAULT /usr/src/gtest)
|
|
if (CMAKE_CROSSCOMPILING)
|
|
set(GTEST_SRC_DIR_DEFAULT ${CMAKE_SOURCE_DIR}/third_party/googletest/src/googletest)
|
|
endif()
|
|
set(GTEST_SRC_DIR ${GTEST_SRC_DIR_DEFAULT} CACHE STRING "Location of gtest sources")
|
|
if(EXISTS ${GTEST_SRC_DIR}/src/gtest-all.cc)
|
|
message(STATUS "building gtest from sources in ${GTEST_SRC_DIR}")
|
|
set(gtest_sources ${GTEST_SRC_DIR}/src/gtest-all.cc)
|
|
add_library(gtest STATIC ${gtest_sources})
|
|
include_directories(${GTEST_SRC_DIR})
|
|
include_directories(${GTEST_SRC_DIR}/include)
|
|
set(GTEST_LIBRARY gtest)
|
|
else()
|
|
message(FATAL_ERROR "UNIT_TEST is set but unable to find gtest library")
|
|
endif()
|
|
endif()
|
|
|
|
add_executable(libyuv_unittest ${ly_unittest_sources})
|
|
target_link_libraries(libyuv_unittest ${ly_lib_name} ${GTEST_LIBRARY})
|
|
if(NOT MSVC)
|
|
target_link_libraries(libyuv_unittest m)
|
|
endif()
|
|
find_library(PTHREAD_LIBRARY pthread)
|
|
if(NOT PTHREAD_LIBRARY STREQUAL "PTHREAD_LIBRARY-NOTFOUND")
|
|
target_link_libraries(libyuv_unittest pthread)
|
|
endif()
|
|
if (JPEG_FOUND)
|
|
target_link_libraries(libyuv_unittest ${JPEG_LIBRARY})
|
|
endif()
|
|
|
|
if(NACL AND NACL_LIBC STREQUAL "newlib")
|
|
target_link_libraries(libyuv_unittest glibc-compat)
|
|
endif()
|
|
|
|
find_library(GFLAGS_LIBRARY gflags)
|
|
if(NOT GFLAGS_LIBRARY STREQUAL "GFLAGS_LIBRARY-NOTFOUND")
|
|
target_link_libraries(libyuv_unittest gflags)
|
|
add_definitions(-DLIBYUV_USE_GFLAGS)
|
|
endif()
|
|
endif()
|
|
|
|
|
|
# install the conversion tool, .so, .a, and all the header files
|
|
install ( TARGETS yuvconvert DESTINATION bin )
|
|
install ( TARGETS ${ly_lib_static} DESTINATION lib )
|
|
install ( TARGETS ${ly_lib_shared} LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib )
|
|
install ( DIRECTORY ${PROJECT_SOURCE_DIR}/include/ DESTINATION include )
|
|
|
|
# create the .deb and .rpm packages using cpack
|
|
include ( CM_linux_packages.cmake )
|
|
|