diff --git a/.github/workflows/CodeQL.yml b/.github/workflows/CodeQL.yml index 90f07ef47..e0fb33f42 100644 --- a/.github/workflows/CodeQL.yml +++ b/.github/workflows/CodeQL.yml @@ -59,7 +59,8 @@ jobs: catch2 \ mesa-vulkan-drivers \ libhidapi-dev \ - ccache + ccache \ + libfftw3-dev - name: Load Vulkan SDK Repo (Ubuntu 22.04) run: | @@ -68,30 +69,6 @@ jobs: sudo apt update sudo apt install vulkan-sdk - - name: Cache FFTS - uses: actions/cache@v4 - with: - path: ~/ffts - key: ${{ runner.os }}-ubuntu-22.04-ffts - - - name: Clone and Build FFTS Library - run: | - if [[ ! -d ~/ffts ]]; then - cd - git clone https://github.com/anthonix/ffts.git - cd ffts - mkdir build - cd build - cmake \ - -DENABLE_SHARED=ON \ - -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ - -GNinja \ - .. - ninja - fi - cd ~/ffts/build - sudo ninja install - # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v3 diff --git a/.github/workflows/build-arch.yml b/.github/workflows/build-arch.yml index 4b61e9deb..5fd56fb0d 100644 --- a/.github/workflows/build-arch.yml +++ b/.github/workflows/build-arch.yml @@ -55,7 +55,8 @@ jobs: ccache \ ninja \ vulkan-swrast \ - lsb-release + lsb-release \ + fftw - name: Install Docs Dependencies if: ${{ matrix.docs }} @@ -110,33 +111,6 @@ jobs: curl -LO https://sdk.lunarg.com/sdk/download/${{ env.SDK_VERSION_STANDALONE }}/linux/vulkansdk-linux-x86_64-${{ env.SDK_VERSION_STANDALONE }}.tar.xz tar xf vulkansdk-linux-x86_64-${{ env.SDK_VERSION_STANDALONE }}.tar.xz - - name: Cache FFTS - uses: actions/cache@v4 - with: - path: ~/ffts - key: ${{ runner.os }}-${{ matrix.os.container }}-ffts - - - name: Clone and Build FFTS Library - run: | - [[ ${{ matrix.docs }} = 'false' ]] && export CMAKE_C_COMPILER_LAUNCHER=ccache && export CMAKE_CXX_COMPILER_LAUNCHER=ccache - if [[ ! -d ~/ffts ]]; then - export CC=/usr/bin/gcc-14 - export CXX=/usr/bin/g++-14 - cd - git clone https://github.com/anthonix/ffts.git - cd ffts - mkdir build - cd build - cmake \ - -DENABLE_SHARED=ON \ - -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ - -GNinja \ - .. - ninja - fi - cd ~/ffts/build - ninja install - - name: Configure run: | [[ (${{matrix.sdk_type }} = 'standalone') ]] && source $HOME/VulkanSDK/${{ env.SDK_VERSION_STANDALONE }}/setup-env.sh diff --git a/.github/workflows/build-debian.yml b/.github/workflows/build-debian.yml index e706d197d..575630bbc 100644 --- a/.github/workflows/build-debian.yml +++ b/.github/workflows/build-debian.yml @@ -67,7 +67,8 @@ jobs: glslang-tools \ spirv-tools \ glslc \ - lsb-release + lsb-release \ + libfftw3-dev - name: Install Docs Dependencies if: ${{ matrix.docs }} @@ -113,31 +114,6 @@ jobs: curl -LO https://sdk.lunarg.com/sdk/download/${{ env.SDK_VERSION_STANDALONE }}/linux/vulkansdk-linux-x86_64-${{ env.SDK_VERSION_STANDALONE }}.tar.xz tar xf vulkansdk-linux-x86_64-${{ env.SDK_VERSION_STANDALONE }}.tar.xz - - name: Cache FFTS - uses: actions/cache@v4 - with: - path: ~/ffts - key: ${{ runner.os }}-${{ matrix.os.container }}-ffts - - - name: Clone and Build FFTS Library - run: | - [[ ${{ matrix.docs }} = 'false' ]] && export CMAKE_C_COMPILER_LAUNCHER=ccache && export CMAKE_CXX_COMPILER_LAUNCHER=ccache - if [[ ! -d ~/ffts ]]; then - cd - git clone https://github.com/anthonix/ffts.git - cd ffts - mkdir build - cd build - cmake \ - -DENABLE_SHARED=ON \ - -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ - -GNinja \ - .. - ninja - fi - cd ~/ffts/build - ninja install - - name: Configure run: | [[ (${{matrix.sdk_type }} = 'standalone') ]] && source $HOME/VulkanSDK/${{ env.SDK_VERSION_STANDALONE }}/setup-env.sh diff --git a/.github/workflows/build-fedora.yml b/.github/workflows/build-fedora.yml index 97dc50aa6..b4df6ac2b 100644 --- a/.github/workflows/build-fedora.yml +++ b/.github/workflows/build-fedora.yml @@ -54,7 +54,8 @@ jobs: fedora-packager \ rpmdevtools \ mesa-vulkan-drivers \ - lsb-release + lsb-release \ + fftw3-devel - name: Install Docs Dependencies if: ${{ matrix.docs }} @@ -111,31 +112,6 @@ jobs: curl -LO https://sdk.lunarg.com/sdk/download/${{ env.SDK_VERSION_STANDALONE }}/linux/vulkansdk-linux-x86_64-${{ env.SDK_VERSION_STANDALONE }}.tar.xz tar xf vulkansdk-linux-x86_64-${{ env.SDK_VERSION_STANDALONE }}.tar.xz - - name: Cache FFTS - uses: actions/cache@v4 - with: - path: ~/ffts - key: ${{ runner.os }}-${{ matrix.os.container }}-ffts - - - name: Clone and Build FFTS Library - run: | - [[ ${{ matrix.docs }} = 'false' ]] && export CMAKE_C_COMPILER_LAUNCHER=ccache && export CMAKE_CXX_COMPILER_LAUNCHER=ccache - if [[ ! -d ~/ffts ]]; then - cd - git clone https://github.com/anthonix/ffts.git - cd ffts - mkdir build - cd build - cmake \ - -DENABLE_SHARED=ON \ - -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ - -GNinja \ - .. - ninja - fi - cd ~/ffts/build - sudo ninja install - - name: Configure run: | [[ (${{matrix.sdk_type }} = 'standalone') ]] && source $HOME/VulkanSDK/${{ env.SDK_VERSION_STANDALONE }}/setup-env.sh diff --git a/.github/workflows/build-macos-arm.yml b/.github/workflows/build-macos-arm.yml index 4d0bef073..f45508bb3 100644 --- a/.github/workflows/build-macos-arm.yml +++ b/.github/workflows/build-macos-arm.yml @@ -43,7 +43,8 @@ jobs: shaderc \ molten-vk \ ninja \ - hidapi + hidapi \ + fftw - name: Configure run: | diff --git a/.github/workflows/build-macos-intel.yml b/.github/workflows/build-macos-intel.yml index d9c438536..ccc698395 100644 --- a/.github/workflows/build-macos-intel.yml +++ b/.github/workflows/build-macos-intel.yml @@ -43,33 +43,8 @@ jobs: shaderc \ molten-vk \ ninja \ - hidapi - - - name: Cache FFTS - uses: actions/cache@v4 - with: - path: ~/ffts-prefix - key: ${{ runner.os }}-ffts-prefix - - - - name: Clone and Build FFTS Library - run: | - [[ -d ~/ffts-prefix ]] && exit 0 - cd - git clone https://github.com/anthonix/ffts.git - cd ffts - mkdir build - cd build - cmake \ - -DENABLE_SHARED=ON \ - -DCMAKE_INSTALL_PREFIX=$HOME/ffts-prefix \ - -DCMAKE_INSTALL_RPATH=$HOME/ffts-prefix/lib \ - -DCMAKE_MACOSX_RPATH=ON \ - -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ - -GNinja \ - .. - ninja - sudo ninja install + hidapi \ + fftw - name: Configure run: | @@ -83,7 +58,7 @@ jobs: -DCMAKE_BUILD_TYPE=Release \ -DBUILD_DOCS=OFF \ -DBUILD_TESTING=ON \ - -DCMAKE_PREFIX_PATH="$(brew --prefix)/opt/libomp;$HOME/ffts-prefix" \ + -DCMAKE_PREFIX_PATH="$(brew --prefix)/opt/libomp" \ .. - name: Build diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml index aecb3e994..ea3990d17 100644 --- a/.github/workflows/build-ubuntu.yml +++ b/.github/workflows/build-ubuntu.yml @@ -58,7 +58,8 @@ jobs: wget \ xzip \ libhidapi-dev \ - ccache + ccache \ + libfftw3-dev - name: Install Docs Dependencies if: ${{ matrix.docs }} @@ -107,31 +108,6 @@ jobs: curl -LO https://sdk.lunarg.com/sdk/download/${{ env.SDK_VERSION_STANDALONE }}/linux/vulkansdk-linux-x86_64-${{ env.SDK_VERSION_STANDALONE }}.tar.xz tar xf vulkansdk-linux-x86_64-${{ env.SDK_VERSION_STANDALONE }}.tar.xz - - name: Cache FFTS - uses: actions/cache@v4 - with: - path: ~/ffts - key: ${{ runner.os }}-${{ matrix.os }}-ffts - - - name: Clone and Build FFTS Library - run: | - [[ ${{ matrix.docs }} = 'false' ]] && export CMAKE_C_COMPILER_LAUNCHER=ccache && export CMAKE_CXX_COMPILER_LAUNCHER=ccache - if [[ ! -d ~/ffts ]]; then - cd - git clone https://github.com/anthonix/ffts.git - cd ffts - mkdir build - cd build - cmake \ - -DENABLE_SHARED=ON \ - -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ - -GNinja \ - .. - ninja - fi - cd ~/ffts/build - sudo ninja install - - name: Configure run: | [[ (${{matrix.sdk_type }} = 'standalone') ]] && source $HOME/VulkanSDK/${{ env.SDK_VERSION_STANDALONE }}/setup-env.sh diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index d351a604e..7a44360d4 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -48,7 +48,7 @@ jobs: shaderc:p glslang:p spirv-tools:p - ffts:p + fftw:p hidapi:p libpng:p diff --git a/CMakeLists.txt b/CMakeLists.txt index c2222f6cb..11bc21f7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,12 +130,6 @@ if(WIN32) add_compile_options(-D_USE_MATH_DEFINES -D_POSIX_THREAD_SAFE_FUNCTIONS) endif() -# Detect Apple Silicon as FFTS is not available for it -if(APPLE AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") - add_compile_options(-D_APPLE_SILICON) - set(APPLE_SILICON TRUE) -endif() - # Package detection find_package(PkgConfig MODULE REQUIRED) @@ -282,13 +276,6 @@ add_subdirectory(devdoc) # Unit tests if(Git_FOUND AND BUILD_TESTING) - # find ffts, except on Apple Silicon where it's not supported - if(NOT APPLE_SILICON) - # ffts ships a broken pkgconfig file on some platforms so we are not going to use it - find_path(LIBFFTS_INCLUDE_DIRS ffts.h PATH_SUFFIXES ffts REQUIRED) - find_library(LIBFFTS_LIBRARIES NAMES ffts libffts REQUIRED) - endif() - find_package(Catch2 REQUIRED) include(Catch) #Catch2 v3.x.y have a breaking change: diff --git a/msys2/PKGBUILD b/msys2/PKGBUILD index ce732fd55..2835bab9b 100644 --- a/msys2/PKGBUILD +++ b/msys2/PKGBUILD @@ -14,7 +14,7 @@ depends=( "${MINGW_PACKAGE_PREFIX}-libsigc++" "${MINGW_PACKAGE_PREFIX}-cairomm" "${MINGW_PACKAGE_PREFIX}-yaml-cpp" - "${MINGW_PACKAGE_PREFIX}-ffts" + "${MINGW_PACKAGE_PREFIX}-fftw" "${MINGW_PACKAGE_PREFIX}-vulkan-loader" "${MINGW_PACKAGE_PREFIX}-glfw" ) diff --git a/src/ngscopeclient/wix/license-paths b/src/ngscopeclient/wix/license-paths index 82d00e51e..bc0f129a7 100644 --- a/src/ngscopeclient/wix/license-paths +++ b/src/ngscopeclient/wix/license-paths @@ -1,5 +1,4 @@ ../LICENSE -../../ffts/COPYRIGHT /mingw64/share/licenses/atk/COPYING /mingw64/share/licenses/atkmm/COPYING /mingw64/share/licenses/binutils/COPYING.LIB diff --git a/tests/Filters/CMakeLists.txt b/tests/Filters/CMakeLists.txt index 96ff87773..a0fd1017d 100644 --- a/tests/Filters/CMakeLists.txt +++ b/tests/Filters/CMakeLists.txt @@ -3,26 +3,33 @@ add_executable(Filters Filter_Add.cpp Filter_ACRMS.cpp - Filter_DeEmbed.cpp Filter_EyePattern.cpp Filter_FIR.cpp - Filter_FFT.cpp Filter_Subtract.cpp Filter_Upsample.cpp FrequencyMeasurement.cpp ) -include_directories(Filters - ${LIBFFTS_INCLUDE_DIRS}) - target_link_libraries(Filters scopehal scopeprotocols Catch2::Catch2 - ${LIBFFTS_LIBRARIES} ) +pkg_search_module(FFTW fftw3f IMPORTED_TARGET) + +if (${FFTW_FOUND}) + message("Found FFTW3, enabling unit tests which depend on it") + target_link_libraries(Filters PkgConfig::FFTW) + target_sources(Filters PRIVATE + Filter_DeEmbed.cpp + Filter_FFT.cpp + ) +else () + message("Didn't find FFTW3, disabling tests which depend on it") +endif () + #Needed because Windows does not support RPATH and will otherwise not be able to find DLLs when catch_discover_tests runs the executable if(WIN32) add_custom_command(TARGET Filters POST_BUILD diff --git a/tests/Filters/Filter_DeEmbed.cpp b/tests/Filters/Filter_DeEmbed.cpp index 40fd7fcb2..9092446ba 100644 --- a/tests/Filters/Filter_DeEmbed.cpp +++ b/tests/Filters/Filter_DeEmbed.cpp @@ -43,9 +43,7 @@ #include "../../lib/scopeprotocols/scopeprotocols.h" #include "Filters.h" -//TODO: switch to FFTW since test case is OK to be GPL -#ifndef _APPLE_SILICON -#include +#include using namespace std; @@ -104,13 +102,9 @@ TEST_CASE("Filter_DeEmbed") //Also compute some temporaries we rely on filter->Refresh(cmdbuf, queue); - //Allocate FFTS plan - //TODO: switch to FFTW auto npoints = filter->test_GetNumPoints(); auto outlen = filter->test_GetOutLen(); auto nouts = filter->test_GetNouts(); - ffts_plan_t* forwardPlan = ffts_init_1d_real(npoints, FFTS_FORWARD); - ffts_plan_t* reversePlan = ffts_init_1d_real(npoints, FFTS_BACKWARD); //Allocate output buffers auto& forwardIn = filter->test_GetCachedInputBuffer(); @@ -123,6 +117,16 @@ TEST_CASE("Filter_DeEmbed") reverseOut.resize(npoints); golden.resize(outlen); + //Allocate FFTW plans + auto forwardPlan = fftwf_plan_dft_r2c_1d(npoints, + forwardIn.GetCpuPointer(), + reinterpret_cast(forwardOut.GetCpuPointer()), + FFTW_PRESERVE_INPUT | FFTW_ESTIMATE); + auto reversePlan = fftwf_plan_dft_c2r_1d(npoints, + reinterpret_cast(forwardOut.GetCpuPointer()), + reverseOut.GetCpuPointer(), + FFTW_PRESERVE_INPUT | FFTW_ESTIMATE); + //Baseline on the CPU //We're only going to check correctness of the inner loop for now, so reuse the calculated S-parameters //and padded input buffer @@ -135,7 +139,7 @@ TEST_CASE("Filter_DeEmbed") cosines.PrepareForCpuAccess(); //Do the forward FFT - ffts_execute(forwardPlan, forwardIn.GetCpuPointer(), forwardOut.GetCpuPointer()); + fftwf_execute(forwardPlan); //Apply the interpolated S-parameters for(size_t j=0; j(filter->GetData(0)) != nullptr); - VerifyMatchingResult( - golden, - dynamic_cast(filter->GetData(0))->m_samples, - 1e-2f - ); + VerifyMatchingResult(golden, dynamic_cast(filter->GetData(0))->m_samples, 1e-2f); //Clean up - ffts_free(forwardPlan); - ffts_free(reversePlan); + fftwf_free(forwardPlan); + fftwf_free(reversePlan); } } @@ -191,5 +191,3 @@ TEST_CASE("Filter_DeEmbed") filter->Release(); } - -#endif diff --git a/tests/Filters/Filter_FFT.cpp b/tests/Filters/Filter_FFT.cpp index 8be7c6d51..11aba1956 100644 --- a/tests/Filters/Filter_FFT.cpp +++ b/tests/Filters/Filter_FFT.cpp @@ -43,9 +43,7 @@ #include "../../lib/scopeprotocols/scopeprotocols.h" #include "Filters.h" -//TODO: switch to FFTW since test case is OK to be GPL -#ifndef _APPLE_SILICON -#include +#include using namespace std; @@ -112,13 +110,17 @@ TEST_CASE("Filter_FFT") //Output buffer auto npoints = filter->test_GetNumPoints(); auto nouts = filter->test_GetNumOuts(); - auto plan = ffts_init_1d_real(npoints, FFTS_FORWARD); UniformAnalogWaveform golden; golden.Resize(nouts); AcceleratorBuffer inbuf; inbuf.resize(npoints); AcceleratorBuffer outbuf; outbuf.resize(2*nouts); + //fftwf_complex can be safely treated as a float[2] array, according to https://www.fftw.org/doc/Complex-numbers.html + auto plan = fftwf_plan_dft_r2c_1d(npoints, + inbuf.GetCpuPointer(), + reinterpret_cast(outbuf.GetCpuPointer()), + FFTW_PRESERVE_INPUT); //Calculate output scale float scale = sqrt(2) / npoints; @@ -160,8 +162,7 @@ TEST_CASE("Filter_FFT") window); //Calculate the FFT - ffts_execute(plan, &inbuf[0], &outbuf[0]); - + fftwf_execute(plan); //Normalize magnitudes if(log_output) NormalizeOutputLog(outbuf, golden.m_samples, nouts, scale); @@ -183,7 +184,7 @@ TEST_CASE("Filter_FFT") double tbase = tpeak + tfft; //Clean up - ffts_free(plan); + fftwf_free(plan); //Try again on the GPU, this time for score start = GetTime(); @@ -307,5 +308,3 @@ void HammingWindow(const float* data, size_t len, float* out) { CosineSumWindow(data, len, out, 25.0f / 46); } - -#endif