diff --git a/modules/juce_dsp/juce_dsp.cpp b/modules/juce_dsp/juce_dsp.cpp index e34bfe56a740..a3674aaa0cd2 100644 --- a/modules/juce_dsp/juce_dsp.cpp +++ b/modules/juce_dsp/juce_dsp.cpp @@ -79,7 +79,9 @@ #include "widgets/juce_Chorus.cpp" #if JUCE_USE_SIMD - #if JUCE_INTEL + #if JUCE_USE_SIMD_FALLBACK + // no extra includes needed for fallback implementation + #elif JUCE_INTEL #ifdef __AVX2__ #include "native/juce_SIMDNativeOps_avx.cpp" #else diff --git a/modules/juce_dsp/juce_dsp.h b/modules/juce_dsp/juce_dsp.h index c8cbf13e7a54..7b48c1334f31 100644 --- a/modules/juce_dsp/juce_dsp.h +++ b/modules/juce_dsp/juce_dsp.h @@ -86,13 +86,22 @@ #else - // No SIMD Support + // No native SIMD support; use fallback implementation + #ifndef JUCE_USE_SIMD_FALLBACK + #define JUCE_USE_SIMD_FALLBACK 1 + #endif + #ifndef JUCE_USE_SIMD - #define JUCE_USE_SIMD 0 + #define JUCE_USE_SIMD JUCE_USE_SIMD_FALLBACK #endif #endif +// Ensure macro is defined +#ifndef JUCE_USE_SIMD_FALLBACK + #define JUCE_USE_SIMD_FALLBACK 0 +#endif + #ifndef JUCE_VECTOR_CALLTYPE // __vectorcall does not work on 64-bit due to internal compiler error in // release mode VS2017. Re-enable when Microsoft fixes this @@ -225,7 +234,9 @@ namespace util #include "native/juce_SIMDNativeOps_fallback.h" // include the correct native file for this build target CPU - #if defined (__i386__) || defined (__amd64__) || defined (_M_X64) || defined (_X86_) || defined (_M_IX86) + #if JUCE_USE_SIMD_FALLBACK + // will use fallback implementation in juce_SIMDNativeOps_fallback.h + #elif defined (__i386__) || defined (__amd64__) || defined (_M_X64) || defined (_X86_) || defined (_M_IX86) #ifdef __AVX2__ #include "native/juce_SIMDNativeOps_avx.h" #else diff --git a/modules/juce_dsp/native/juce_SIMDNativeOps_fallback.h b/modules/juce_dsp/native/juce_SIMDNativeOps_fallback.h index b7214eeece65..5bee119e57d9 100644 --- a/modules/juce_dsp/native/juce_SIMDNativeOps_fallback.h +++ b/modules/juce_dsp/native/juce_SIMDNativeOps_fallback.h @@ -261,4 +261,54 @@ struct SIMDFallbackOps } }; +/** + Fallback implementation of SIMD ops. This will be overridden by the + specializations in architecture-specific files. + + @tags{DSP} +*/ +template +struct SIMDNativeOps +{ + using vSIMDType = std::array; + using fb = SIMDFallbackOps; + + static forcedinline vSIMDType expand (ScalarType s) noexcept { return fb::expand (s); } + static forcedinline vSIMDType load (const ScalarType* a) noexcept { return fb::load (a); } + static forcedinline void store (vSIMDType value, ScalarType* dest) noexcept { return fb::store (value, dest); } + static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept { return fb::add (a, b); } + static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept { return fb::sub (a, b); } + static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept { return fb::mul (a, b); } + static forcedinline vSIMDType bit_and (vSIMDType a, vSIMDType b) noexcept { return fb::bit_and (a, b); } + static forcedinline vSIMDType bit_or (vSIMDType a, vSIMDType b) noexcept { return fb::bit_or (a, b); } + static forcedinline vSIMDType bit_xor (vSIMDType a, vSIMDType b) noexcept { return fb::bit_xor (a, b); } + static forcedinline vSIMDType bit_notand (vSIMDType a, vSIMDType b) noexcept { return fb::bit_notand (a, b); } + static forcedinline vSIMDType bit_not (vSIMDType a) noexcept { return fb::bit_not (a); } + static forcedinline vSIMDType min (vSIMDType a, vSIMDType b) noexcept { return fb::min (a, b); } + static forcedinline vSIMDType max (vSIMDType a, vSIMDType b) noexcept { return fb::max (a, b); } + static forcedinline vSIMDType equal (vSIMDType a, vSIMDType b) noexcept { return fb::equal (a, b); } + static forcedinline vSIMDType notEqual (vSIMDType a, vSIMDType b) noexcept { return fb::notEqual (a, b); } + static forcedinline vSIMDType greaterThan (vSIMDType a, vSIMDType b) noexcept { return fb::greaterThan (a, b); } + static forcedinline vSIMDType greaterThanOrEqual (vSIMDType a, vSIMDType b) noexcept { return fb::greaterThanOrEqual (a, b); } + static forcedinline bool allEqual (vSIMDType a, vSIMDType b) noexcept { return fb::allEqual (a, b); } + static forcedinline vSIMDType multiplyAdd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return fb::multiplyAdd (a, b, c); } + static forcedinline ScalarType get (vSIMDType v, size_t i) noexcept { return fb::get (v, i); } + static forcedinline vSIMDType set (vSIMDType v, size_t i, ScalarType s) noexcept { return fb::set (v, i, s); } + static forcedinline vSIMDType truncate (vSIMDType a) noexcept { return fb::truncate (a); } + static forcedinline vSIMDType cmplxmul (vSIMDType a, vSIMDType b) noexcept { return fb::cmplxmul (a, b); } + static forcedinline ScalarType sum (vSIMDType a) noexcept { return fb::sum (a); } + + static forcedinline vSIMDType oddevensum (vSIMDType a) noexcept + { + if (fb::n <= 2) + return a; + ScalarType sums[2] = {}; + for (size_t i = 0; i < fb::n; ++i) + sums[i % 2] += get (a, i); + for (size_t i = 0; i < fb::n; ++i) + a = set (a, i, sums[i % 2]); + return a; + } +}; + } // namespace juce::dsp