From 52273943c614afacf9321fef61940ebf7859317b Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 11 Nov 2020 17:46:17 +0000 Subject: [PATCH] Couple of fixes to allow SIMD on Emscripten - Add `-msimd128` to flags to actually enable WebAssembly SIMD when performing SIMD detection. It's currently required in addition to `-msse*` / `-mfpu=neon` flags which only perform translation of corresponding intrinsics to Wasm SIMD ones. See a discussion at emscripten-core/emscripten#12714 for automating this and making easier in the future. - Remove compilation branch that prevented definitions of `WEBP_USE_SSE` and `WEBP_USE_NEON` on Emscripten even when SIMD support was detected at compile-time. - Add an implementation of `VP8GetCPUInfo` for Emscripten which uses static `WEBP_USE_*` flags to determine if a corresponding SIMD instruction is supported. This is because Wasm doesn't have proper feature detection (yet) and requires making separate build for SIMD version anyway. Change-Id: I77592081b91fd0e4cbc9242f5600ce905184f506 --- CMakeLists.txt | 9 +++++++-- cmake/cpu.cmake | 3 +++ src/dsp/cpu.c | 24 ++++++++++++++++++++++++ src/dsp/dsp.h | 5 ----- 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d2dadf79..923976d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,13 @@ cmake_minimum_required(VERSION 3.5) project(WebP C) # Options for coder / decoder executables. -option(WEBP_ENABLE_SIMD "Enable any SIMD optimization." ON) +if(NOT EMSCRIPTEN) + # Disable SIMD on Emscripten by default, as it's a new unstable Wasm feature. + # Users can still explicitly opt-in to make a SIMD-enabled build. + set(WEBP_ENABLE_SIMD_DEFAULT ON) +endif() +option(WEBP_ENABLE_SIMD "Enable any SIMD optimization." + ${WEBP_ENABLE_SIMD_DEFAULT}) option(WEBP_BUILD_ANIM_UTILS "Build animation utilities." ON) option(WEBP_BUILD_CWEBP "Build the cwebp command line tool." ON) option(WEBP_BUILD_DWEBP "Build the dwebp command line tool." ON) @@ -26,7 +32,6 @@ if(WIN32) endif() if(WEBP_BUILD_WEBP_JS) - set(WEBP_ENABLE_SIMD OFF) set(WEBP_BUILD_ANIM_UTILS OFF) set(WEBP_BUILD_CWEBP OFF) set(WEBP_BUILD_DWEBP OFF) diff --git a/cmake/cpu.cmake b/cmake/cpu.cmake index da9a42a4..93a230c1 100644 --- a/cmake/cpu.cmake +++ b/cmake/cpu.cmake @@ -70,6 +70,9 @@ foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE}) webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD}) if(NOT WEBP_HAVE_${WEBP_SIMD_FLAG}) list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG) + if(EMSCRIPTEN) + set(SIMD_COMPILE_FLAG "-msimd128 ${SIMD_COMPILE_FLAG}") + endif() set(CMAKE_REQUIRED_FLAGS ${SIMD_COMPILE_FLAG}) webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD}) else() diff --git a/src/dsp/cpu.c b/src/dsp/cpu.c index 0fa5b6a5..637c2931 100644 --- a/src/dsp/cpu.c +++ b/src/dsp/cpu.c @@ -179,6 +179,30 @@ static int AndroidCPUInfo(CPUFeature feature) { return 0; } VP8CPUInfo VP8GetCPUInfo = AndroidCPUInfo; +#elif defined(EMSCRIPTEN) // also needs to be before generic NEON test +// Use compile flags as an indicator of SIMD support instead of a runtime check. +static int wasmCPUInfo(CPUFeature feature) { + switch (feature) { +#ifdef WEBP_USE_SSE2 + case kSSE2: + return 1; +#endif +#ifdef WEBP_USE_SSE41 + case kSSE3: + case kSlowSSSE3: + case kSSE4_1: + return 1; +#endif +#ifdef WEBP_USE_NEON + case kNEON: + return 1; +#endif + default: + break; + } + return 0; +} +VP8CPUInfo VP8GetCPUInfo = wasmCPUInfo; #elif defined(WEBP_USE_NEON) // define a dummy function to enable turning off NEON at runtime by setting // VP8DecGetCPUInfo = NULL diff --git a/src/dsp/dsp.h b/src/dsp/dsp.h index cf50bb13..b7c08ce0 100644 --- a/src/dsp/dsp.h +++ b/src/dsp/dsp.h @@ -51,9 +51,6 @@ extern "C" { # define __has_builtin(x) 0 #endif -// for now, none of the optimizations below are available in emscripten -#if !defined(EMSCRIPTEN) - #if defined(_MSC_VER) && _MSC_VER > 1310 && \ (defined(_M_X64) || defined(_M_IX86)) #define WEBP_MSC_SSE2 // Visual C++ SSE2 targets @@ -110,8 +107,6 @@ extern "C" { #define WEBP_USE_MSA #endif -#endif /* EMSCRIPTEN */ - #ifndef WEBP_DSP_OMIT_C_CODE #define WEBP_DSP_OMIT_C_CODE 1 #endif