diff --git a/.gitmodules b/.gitmodules index 9cbfac18..92f842e7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -39,3 +39,6 @@ path = external/filesystem url = https://github.com/gulrak/filesystem.git shallow = true +[submodule "external/simde"] + path = external/simde + url = https://github.com/sfztools/simde.git diff --git a/cmake/SfizzDeps.cmake b/cmake/SfizzDeps.cmake index 3dcb1916..864f1225 100644 --- a/cmake/SfizzDeps.cmake +++ b/cmake/SfizzDeps.cmake @@ -1,6 +1,16 @@ # Find system threads find_package(Threads REQUIRED) +# Find OpenMP +find_package(OpenMP) +if(OPENMP_FOUND) + add_library(sfizz_openmp INTERFACE) + add_library(sfizz::openmp ALIAS sfizz_openmp) + target_compile_options(sfizz_openmp INTERFACE + $<$:${OpenMP_C_FLAGS}> + $<$:${OpenMP_CXX_FLAGS}>) +endif() + # Find macOS system libraries if(APPLE) find_library(APPLE_COREFOUNDATION_LIBRARY "CoreFoundation") @@ -67,6 +77,14 @@ else() endif() add_subdirectory("external/st_audiofile" EXCLUDE_FROM_ALL) +# The simde library +add_library(sfizz_simde INTERFACE) +add_library(sfizz::simde ALIAS sfizz_simde) +target_include_directories(sfizz_simde INTERFACE "external/simde") +if(TARGET sfizz::openmp) + target_link_libraries(sfizz_simde INTERFACE sfizz::openmp) +endif() + # The pugixml library add_library(sfizz_pugixml STATIC "src/external/pugixml/src/pugixml.cpp") add_library(sfizz::pugixml ALIAS sfizz_pugixml) diff --git a/common.mk b/common.mk index ae100d0d..ca23cad7 100644 --- a/common.mk +++ b/common.mk @@ -315,6 +315,10 @@ SFIZZ_SOURCES += \ src/external/cpuid/src/cpuid/cpuinfo.cpp \ src/external/cpuid/src/cpuid/version.cpp +### simde dependency +SFIZZ_C_FLAGS += \ + -I$(SFIZZ_DIR)/external/simde + ### Pugixml dependency SFIZZ_C_FLAGS += -I$(SFIZZ_DIR)/src/external/pugixml/src @@ -360,3 +364,9 @@ SFIZZ_C_FLAGS += -pthread SFIZZ_CXX_FLAGS += -pthread SFIZZ_LINK_FLAGS += -pthread endif + +### OpenMP dependency + +SFIZZ_C_FLAGS += -fopenmp +SFIZZ_CXX_FLAGS += -fopenmp +SFIZZ_LINK_FLAGS += -fopenmp diff --git a/external/simde b/external/simde new file mode 160000 index 00000000..0ba9d8fd --- /dev/null +++ b/external/simde @@ -0,0 +1 @@ +Subproject commit 0ba9d8fdc0569e5a887dc42c6ddfa2a27a9f6867 diff --git a/scripts/run_clang_tidy.sh b/scripts/run_clang_tidy.sh index 041d331a..ceb29530 100755 --- a/scripts/run_clang_tidy.sh +++ b/scripts/run_clang_tidy.sh @@ -30,7 +30,7 @@ clang-tidy \ vst/SfizzVstState.cpp \ -- -Iexternal/abseil-cpp -Iexternal/jsl/include -Iexternal/filesystem/include -Iexternal/atomic_queue/include -Iexternal/threadpool -Isrc/external/hiir -Isrc/external/pugixml/src \ -Iexternal/st_audiofile/src -Iexternal/st_audiofile/thirdparty/dr_libs \ - -Isrc/sfizz -Isrc -Isrc/sfizz/utility/spin_mutex -Isrc/external/spline -Isrc/external/cpuid/src \ + -Isrc/sfizz -Isrc -Isrc/sfizz/utility/spin_mutex -Isrc/external/spline -Isrc/external/cpuid/src -Iexternal/simde \ -Ivst -Ivst/external/VST_SDK/VST3_SDK -Ieditor/external/vstgui4 -Ivst/external/ring_buffer \ -Ieditor/src \ -DNDEBUG -std=c++17 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d75cd15f..616e401e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -217,7 +217,7 @@ target_sources(sfizz_parser PRIVATE ${SFIZZ_PARSER_HEADERS} ${SFIZZ_PARSER_SOURCES} ${SFIZZ_PARSER_OTHER}) target_include_directories(sfizz_parser PUBLIC sfizz) target_link_libraries(sfizz_parser - PUBLIC sfizz::filesystem absl::strings + PUBLIC sfizz::filesystem sfizz::simde absl::strings PRIVATE absl::flat_hash_map) # OSC messaging library @@ -252,7 +252,7 @@ add_library(sfizz::internal ALIAS sfizz_internal) target_sources(sfizz_internal PRIVATE ${SFIZZ_HEADERS} ${SFIZZ_SOURCES} ${FAUST_FILES}) target_include_directories(sfizz_internal PUBLIC "." "sfizz") target_link_libraries(sfizz_internal - PUBLIC absl::strings absl::span sfizz::filesystem sfizz::atomic_queue sfizz::spin_mutex + PUBLIC absl::strings absl::span sfizz::filesystem sfizz::atomic_queue sfizz::spin_mutex sfizz::simde PRIVATE sfizz::parser sfizz::messaging absl::flat_hash_map Threads::Threads st_audiofile sfizz::pugixml sfizz::spline sfizz::tunings sfizz::hiir sfizz::kissfft sfizz::cephes sfizz::cpuid sfizz::threadpool sfizz::jsl sfizz::atomic) if(SFIZZ_USE_SNDFILE) target_compile_definitions(sfizz_internal PUBLIC "SFIZZ_USE_SNDFILE=1") diff --git a/src/sfizz/Interpolators.hpp b/src/sfizz/Interpolators.hpp index a75c9608..2585704e 100644 --- a/src/sfizz/Interpolators.hpp +++ b/src/sfizz/Interpolators.hpp @@ -8,6 +8,11 @@ #include "WindowedSinc.h" #include "MathHelpers.h" #include "SIMDConfig.h" +#include +#if SIMDE_NATURAL_VECTOR_SIZE_GE(128) +#include +#include +#endif namespace sfz { @@ -49,25 +54,17 @@ public: //------------------------------------------------------------------------------ // Hermite 3rd order, SSE specialization -#if SFIZZ_HAVE_SSE +#if SIMDE_NATURAL_VECTOR_SIZE_GE(128) template <> class Interpolator { public: static inline float process(const float* values, float coeff) { - __m128 x = _mm_sub_ps(_mm_setr_ps(-1, 0, 1, 2), _mm_set1_ps(coeff)); - __m128 h = hermite3x4(x); - __m128 y = _mm_mul_ps(h, _mm_loadu_ps(values - 1)); - // sum 4 to 1 - __m128 xmm0 = y; - __m128 xmm1 = _mm_shuffle_ps(xmm0, xmm0, 0xe5); - __m128 xmm2 = _mm_movehl_ps(xmm0, xmm0); - xmm1 = _mm_add_ss(xmm1, xmm0); - xmm0 = _mm_shuffle_ps(xmm0, xmm0, 0xe7); - xmm2 = _mm_add_ss(xmm2, xmm1); - xmm0 = _mm_add_ss(xmm0, xmm2); - return _mm_cvtss_f32(xmm0); + simde__m128 x = simde_mm_sub_ps(simde_mm_setr_ps(-1, 0, 1, 2), simde_mm_set1_ps(coeff)); + simde__m128 h = hermite3x4(x); + simde__m128 y = simde_mm_mul_ps(h, simde_mm_loadu_ps(values - 1)); + return simde_vaddvq_f32(y); } }; #endif @@ -93,25 +90,17 @@ public: //------------------------------------------------------------------------------ // B-spline 3rd order, SSE specialization -#if SFIZZ_HAVE_SSE +#if SIMDE_NATURAL_VECTOR_SIZE_GE(128) template <> class Interpolator { public: static inline float process(const float* values, float coeff) { - __m128 x = _mm_sub_ps(_mm_setr_ps(-1, 0, 1, 2), _mm_set1_ps(coeff)); - __m128 h = bspline3x4(x); - __m128 y = _mm_mul_ps(h, _mm_loadu_ps(values - 1)); - // sum 4 to 1 - __m128 xmm0 = y; - __m128 xmm1 = _mm_shuffle_ps(xmm0, xmm0, 0xe5); - __m128 xmm2 = _mm_movehl_ps(xmm0, xmm0); - xmm1 = _mm_add_ss(xmm1, xmm0); - xmm0 = _mm_shuffle_ps(xmm0, xmm0, 0xe7); - xmm2 = _mm_add_ss(xmm2, xmm1); - xmm0 = _mm_add_ss(xmm0, xmm2); - return _mm_cvtss_f32(xmm0); + simde__m128 x = simde_mm_sub_ps(simde_mm_setr_ps(-1, 0, 1, 2), simde_mm_set1_ps(coeff)); + simde__m128 h = bspline3x4(x); + simde__m128 y = simde_mm_mul_ps(h, simde_mm_loadu_ps(values - 1)); + return simde_vaddvq_f32(y); } }; #endif @@ -190,7 +179,7 @@ class SincInterpolator; //------------------------------------------------------------------------------ // Windowed sinc any order, SSE specialization -#if SFIZZ_HAVE_SSE2 +#if SIMDE_NATURAL_VECTOR_SIZE_GE(128) template class SincInterpolator { @@ -204,25 +193,17 @@ public: constexpr int j0 = 1 - int(Points) / 2; float x0 = j0 - coeff; - __m128 y = _mm_set1_ps(0.0f); - __m128 x = _mm_add_ps(_mm_set1_ps(x0), _mm_setr_ps(0, 1, 2, 3)); + simde__m128 y = simde_mm_set1_ps(0.0f); + simde__m128 x = simde_mm_add_ps(simde_mm_set1_ps(x0), simde_mm_setr_ps(0, 1, 2, 3)); size_t i = 0; do { - __m128 h = ws.getUncheckedX4(x); - y = _mm_add_ps(y, _mm_mul_ps(h, _mm_loadu_ps(&values[j0 + i]))); - x = _mm_add_ps(x, _mm_set1_ps(4.0f)); + simde__m128 h = ws.getUncheckedX4(x); + y = simde_mm_add_ps(y, simde_mm_mul_ps(h, simde_mm_loadu_ps(&values[j0 + i]))); + x = simde_mm_add_ps(x, simde_mm_set1_ps(4.0f)); i += 4; } while (i < Points); - // sum 4 to 1 - __m128 xmm0 = y; - __m128 xmm1 = _mm_shuffle_ps(xmm0, xmm0, 0xe5); - __m128 xmm2 = _mm_movehl_ps(xmm0, xmm0); - xmm1 = _mm_add_ss(xmm1, xmm0); - xmm0 = _mm_shuffle_ps(xmm0, xmm0, 0xe7); - xmm2 = _mm_add_ss(xmm2, xmm1); - xmm0 = _mm_add_ss(xmm0, xmm2); - return _mm_cvtss_f32(xmm0); + return simde_vaddvq_f32(y); } }; #endif diff --git a/src/sfizz/MathHelpers.h b/src/sfizz/MathHelpers.h index d04793fc..066b8e04 100644 --- a/src/sfizz/MathHelpers.h +++ b/src/sfizz/MathHelpers.h @@ -21,8 +21,9 @@ #include #include #include -#if SFIZZ_HAVE_SSE -#include +#include +#if SIMDE_NATURAL_VECTOR_SIZE_GE(128) +#include #endif #if __cplusplus >= 201703L @@ -195,26 +196,26 @@ R hermite3(R x) return y; } -#if SFIZZ_HAVE_SSE +#if SIMDE_NATURAL_VECTOR_SIZE_GE(128) /** * @brief Compute 4 parallel elements of the 3rd-order Hermite interpolation polynomial. * * @param x - * @return __m128 + * @return simde__m128 */ -inline __m128 hermite3x4(__m128 x) +inline simde__m128 hermite3x4(simde__m128 x) { - x = _mm_andnot_ps(_mm_set1_ps(-0.0f), x); - __m128 x2 = _mm_mul_ps(x, x); - __m128 x3 = _mm_mul_ps(x2, x); - __m128 y = _mm_set1_ps(0.0f); - __m128 q = _mm_mul_ps(_mm_set1_ps(5./2.), x2); - __m128 p1 = _mm_add_ps(_mm_sub_ps(_mm_set1_ps(1), q), _mm_mul_ps(_mm_set1_ps(3./2.), x3)); - __m128 p2 = _mm_sub_ps(_mm_add_ps(_mm_sub_ps(_mm_set1_ps(2), _mm_mul_ps(_mm_set1_ps(4), x)), q), _mm_mul_ps(_mm_set1_ps(1./2.), x3)); - __m128 m2 = _mm_cmple_ps(x, _mm_set1_ps(2)); - y = _mm_or_ps(_mm_and_ps(m2, p2), _mm_andnot_ps(m2, y)); - __m128 m1 = _mm_cmple_ps(x, _mm_set1_ps(1)); - y = _mm_or_ps(_mm_and_ps(m1, p1), _mm_andnot_ps(m1, y)); + x = simde_x_mm_abs_ps(x); + simde__m128 x2 = simde_mm_mul_ps(x, x); + simde__m128 x3 = simde_mm_mul_ps(x2, x); + simde__m128 y = simde_mm_set1_ps(0.0f); + simde__m128 q = simde_mm_mul_ps(simde_mm_set1_ps(5./2.), x2); + simde__m128 p1 = simde_mm_add_ps(simde_mm_sub_ps(simde_mm_set1_ps(1), q), simde_mm_mul_ps(simde_mm_set1_ps(3./2.), x3)); + simde__m128 p2 = simde_mm_sub_ps(simde_mm_add_ps(simde_mm_sub_ps(simde_mm_set1_ps(2), simde_mm_mul_ps(simde_mm_set1_ps(4), x)), q), simde_mm_mul_ps(simde_mm_set1_ps(1./2.), x3)); + simde__m128 m2 = simde_mm_cmple_ps(x, simde_mm_set1_ps(2)); + y = simde_mm_or_ps(simde_mm_and_ps(m2, p2), simde_mm_andnot_ps(m2, y)); + simde__m128 m1 = simde_mm_cmple_ps(x, simde_mm_set1_ps(1)); + y = simde_mm_or_ps(simde_mm_and_ps(m1, p1), simde_mm_andnot_ps(m1, y)); return y; } #endif @@ -240,25 +241,25 @@ R bspline3(R x) return y; } -#if SFIZZ_HAVE_SSE +#if SIMDE_NATURAL_VECTOR_SIZE_GE(128) /** * @brief Compute 4 parallel elements of the 3rd-order B-spline interpolation polynomial. * * @param x - * @return __m128 + * @return simde__m128 */ -inline __m128 bspline3x4(__m128 x) +inline simde__m128 bspline3x4(simde__m128 x) { - x = _mm_andnot_ps(_mm_set1_ps(-0.0f), x); - __m128 x2 = _mm_mul_ps(x, x); - __m128 x3 = _mm_mul_ps(x2, x); - __m128 y = _mm_set1_ps(0.0f); - __m128 p1 = _mm_add_ps(_mm_sub_ps(_mm_set1_ps(2./3.), x2), _mm_mul_ps(_mm_set1_ps(1./2.), x3)); - __m128 p2 = _mm_sub_ps(_mm_add_ps(_mm_sub_ps(_mm_set1_ps(4./3.), _mm_mul_ps(_mm_set1_ps(2), x)), x2), _mm_mul_ps(_mm_set1_ps(1./6.), x3)); - __m128 m2 = _mm_cmple_ps(x, _mm_set1_ps(2)); - y = _mm_or_ps(_mm_and_ps(m2, p2), _mm_andnot_ps(m2, y)); - __m128 m1 = _mm_cmple_ps(x, _mm_set1_ps(1)); - y = _mm_or_ps(_mm_and_ps(m1, p1), _mm_andnot_ps(m1, y)); + x = simde_x_mm_abs_ps(x); + simde__m128 x2 = simde_mm_mul_ps(x, x); + simde__m128 x3 = simde_mm_mul_ps(x2, x); + simde__m128 y = simde_mm_set1_ps(0.0f); + simde__m128 p1 = simde_mm_add_ps(simde_mm_sub_ps(simde_mm_set1_ps(2./3.), x2), simde_mm_mul_ps(simde_mm_set1_ps(1./2.), x3)); + simde__m128 p2 = simde_mm_sub_ps(simde_mm_add_ps(simde_mm_sub_ps(simde_mm_set1_ps(4./3.), simde_mm_mul_ps(simde_mm_set1_ps(2), x)), x2), simde_mm_mul_ps(simde_mm_set1_ps(1./6.), x3)); + simde__m128 m2 = simde_mm_cmple_ps(x, simde_mm_set1_ps(2)); + y = simde_mm_or_ps(simde_mm_and_ps(m2, p2), simde_mm_andnot_ps(m2, y)); + simde__m128 m1 = simde_mm_cmple_ps(x, simde_mm_set1_ps(1)); + y = simde_mm_or_ps(simde_mm_and_ps(m1, p1), simde_mm_andnot_ps(m1, y)); return y; } #endif diff --git a/src/sfizz/WindowedSinc.h b/src/sfizz/WindowedSinc.h index b8beb582..dc7143f2 100644 --- a/src/sfizz/WindowedSinc.h +++ b/src/sfizz/WindowedSinc.h @@ -8,8 +8,9 @@ #include "SIMDConfig.h" #include #include -#if SFIZZ_HAVE_SSE2 -#include +#include +#if SIMDE_NATURAL_VECTOR_SIZE_GE(128) +#include #endif namespace sfz { @@ -30,9 +31,9 @@ public: // interpolate f(x), where x must be in domain [-Points/2:+Points/2] float getUnchecked(float x) const noexcept; -#if SFIZZ_HAVE_SSE2 +#if SIMDE_NATURAL_VECTOR_SIZE_GE(128) // interpolate f(x), 4 values at once - __m128 getUncheckedX4(__m128 x) const noexcept; + simde__m128 getUncheckedX4(simde__m128 x) const noexcept; #endif // calculate exact f(x), where x must be in domain [-Points/2:+Points/2] diff --git a/src/sfizz/WindowedSinc.hpp b/src/sfizz/WindowedSinc.hpp index 1bd4f19c..eb8b3b75 100644 --- a/src/sfizz/WindowedSinc.hpp +++ b/src/sfizz/WindowedSinc.hpp @@ -7,6 +7,9 @@ #pragma once #include "WindowedSinc.h" #include +#if SIMDE_NATURAL_VECTOR_SIZE_GE(128) +#include +#endif namespace sfz { @@ -36,33 +39,33 @@ inline float AbstractWindowedSinc::getUnchecked(float x) const noexcept return y0 + mu * dy; } -#if SFIZZ_HAVE_SSE2 +#if SIMDE_NATURAL_VECTOR_SIZE_GE(128) template -inline __m128 AbstractWindowedSinc::getUncheckedX4(__m128 x) const noexcept +inline simde__m128 AbstractWindowedSinc::getUncheckedX4(simde__m128 x) const noexcept { const float* table = static_cast(this)->getTablePointer(); size_t points = static_cast(this)->getNumPoints(); size_t tableSize = static_cast(this)->getTableSize(); - __m128 ix = _mm_mul_ps( - _mm_add_ps(x, _mm_set1_ps(points / 2.0f)), - _mm_set1_ps((tableSize - 1) / points)); - alignas(__m128i) int j0[4]; - __m128i i0 = _mm_cvttps_epi32(ix); - _mm_store_si128((__m128i*)j0, i0); - __m128 mu = _mm_sub_ps(ix, _mm_cvtepi32_ps(i0)); + simde__m128 ix = simde_mm_mul_ps( + simde_mm_add_ps(x, simde_mm_set1_ps(points / 2.0f)), + simde_mm_set1_ps((tableSize - 1) / points)); + alignas(simde__m128i) int j0[4]; + simde__m128i i0 = simde_mm_cvttps_epi32(ix); + simde_mm_store_si128((simde__m128i*)j0, i0); + simde__m128 mu = simde_mm_sub_ps(ix, simde_mm_cvtepi32_ps(i0)); // reference: Interpolated table lookups using SSE2 [2/2] // https://rawstudio.org/blog/?p=482 - __m128 p0p1 = _mm_castsi128_ps(_mm_loadl_epi64((__m128i*)&table[j0[0]])); - __m128 p2p3 = _mm_castsi128_ps(_mm_loadl_epi64((__m128i*)&table[j0[2]])); - p0p1 = _mm_loadh_pi(p0p1, (__m64*)&table[j0[1]]); - p2p3 = _mm_loadh_pi(p2p3, (__m64*)&table[j0[3]]); - __m128 y0 = _mm_shuffle_ps(p0p1, p2p3, _MM_SHUFFLE(2, 0, 2, 0)); - __m128 y1 = _mm_shuffle_ps(p0p1, p2p3, _MM_SHUFFLE(3, 1, 3, 1)); + simde__m128 p0p1 = simde_mm_castsi128_ps(simde_mm_loadl_epi64((simde__m128i*)&table[j0[0]])); + simde__m128 p2p3 = simde_mm_castsi128_ps(simde_mm_loadl_epi64((simde__m128i*)&table[j0[2]])); + p0p1 = simde_mm_loadh_pi(p0p1, (simde__m64*)&table[j0[1]]); + p2p3 = simde_mm_loadh_pi(p2p3, (simde__m64*)&table[j0[3]]); + simde__m128 y0 = simde_mm_shuffle_ps(p0p1, p2p3, SIMDE_MM_SHUFFLE(2, 0, 2, 0)); + simde__m128 y1 = simde_mm_shuffle_ps(p0p1, p2p3, SIMDE_MM_SHUFFLE(3, 1, 3, 1)); - __m128 dy = _mm_sub_ps(y1, y0); - return _mm_add_ps(y0, _mm_mul_ps(mu, dy)); + simde__m128 dy = simde_mm_sub_ps(y1, y0); + return simde_mm_add_ps(y0, simde_mm_mul_ps(mu, dy)); } #endif