From ac2a14e885fce5a6d3e1144f8d45137bf84e8383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 25 Jun 2025 15:31:54 -0700 Subject: [PATCH 01/66] Update runner images --- .github/workflows/continuous.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 435d0fe9..7c1653e1 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -24,7 +24,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-22.04, macos-13, macos-14] + os: [ubuntu-24.04, macos-13, macos-15] config: [RelwithDebInfo, Debug] compiler: [gcc, apple, llvm] sanitizer: ["Address", "Thread"] # TODO: Add Memory+Undefined Sanitizer @@ -35,9 +35,9 @@ jobs: sanitizer: Thread - os: macos-13 config: Debug - - os: macos-14 + - os: macos-15 compiler: gcc - - os: ubuntu-22.04 + - os: ubuntu-24.04 compiler: apple steps: - name: Free Disk Space @@ -140,8 +140,8 @@ jobs: #################### Windows: - name: windows-2022 (${{ matrix.config }}) - runs-on: windows-2022 + name: windows-2025 (${{ matrix.config }}) + runs-on: windows-2025 strategy: fail-fast: false matrix: From b79cc2111fe7d96e51a9821a994f771e4cfb9fbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 25 Jun 2025 15:47:20 -0700 Subject: [PATCH 02/66] Update runner images --- .github/workflows/continuous.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 7c1653e1..2ed10f58 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -91,11 +91,17 @@ jobs: fi - name: Setup Xcode version - if: runner.os == 'macOS' + if: matrix.os == 'macos-13' uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: '15.2' + - name: Setup Xcode version + if: matrix.os == 'macos-15' + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: '16.4' + - name: Get number of CPU cores uses: SimenB/github-actions-cpu-cores@v1 id: cpu-cores From 456453eb9c49edd0f7fdc2f4cd0c0927ed82f484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 25 Jun 2025 15:59:13 -0700 Subject: [PATCH 03/66] Update runner images --- .github/workflows/wheel.yaml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/wheel.yaml b/.github/workflows/wheel.yaml index 5302ee97..e44be880 100644 --- a/.github/workflows/wheel.yaml +++ b/.github/workflows/wheel.yaml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-22.04, macos-13, macos-14, windows-2022] + os: [ubuntu-24.04, macos-13, macos-15, windows-2025] name: ${{matrix.os}} runs-on: ${{matrix.os}} @@ -23,11 +23,17 @@ jobs: uses: actions/checkout@v4 - name: Setup Xcode version - if: runner.os == 'macOS' + if: matrix.os == 'macos-13' uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: '15.2' + - name: Setup Xcode version + if: matrix.os == 'macos-15' + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: '16.4' + - name: Setup MSVC if: runner.os == 'windows' uses: ilammy/msvc-dev-cmd@v1 From afe5925b0cc1adff564083e4a2874bb7b9042dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 07:49:35 -0800 Subject: [PATCH 04/66] Silence gcc warning. --- modules/core/src/compute_area.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/core/src/compute_area.cpp b/modules/core/src/compute_area.cpp index 9c77ffff..0ba79d8b 100644 --- a/modules/core/src/compute_area.cpp +++ b/modules/core/src/compute_area.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include // clang-format off @@ -348,8 +349,10 @@ AttributeId compute_facet_vector_area( auto f = mesh.get_facet_vertices(fid); for (Index lv = 0; lv < f_size; lv++) { Index lv_next = (lv + 1) % f_size; + LA_IGNORE_ARRAY_BOUNDS_BEGIN vector_area.row(fid) += vertices.row(f[lv]).template head<3>().cross( vertices.row(f[lv_next]).template head<3>()); + LA_IGNORE_ARRAY_BOUNDS_END } }); vector_area /= 2; From 4c69226f8ea89a3e7613392f4c1b3a560a6db5ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Dumas?= Date: Thu, 13 Nov 2025 08:29:46 -0800 Subject: [PATCH 05/66] Sync with 96afce5 (#76) --- cmake/lagrange/lagrange_cpm_cache.cmake | 3 ++- cmake/lagrange/lagrange_tbb_sanitizers.cmake | 7 ++++-- cmake/recipes/external/assimp.cmake | 4 ++- cmake/recipes/external/assimp.patch | 25 +++++++++++++++---- .../testing/include/lagrange/testing/common.h | 4 ++- 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/cmake/lagrange/lagrange_cpm_cache.cmake b/cmake/lagrange/lagrange_cpm_cache.cmake index 6c34f303..4b2953dd 100644 --- a/cmake/lagrange/lagrange_cpm_cache.cmake +++ b/cmake/lagrange/lagrange_cpm_cache.cmake @@ -14,7 +14,8 @@ if(DEFINED ENV{CPM_SOURCE_CACHE}) set(CPM_SOURCE_CACHE_DEFAULT $ENV{CPM_SOURCE_CACHE}) else() # Set CPM cache folder if unset - file(REAL_PATH "~/.cache/CPM" CPM_SOURCE_CACHE_DEFAULT EXPAND_TILDE) + file(REAL_PATH "~" HOME_DIR EXPAND_TILDE) + cmake_path(APPEND HOME_DIR ".cache/CPM" OUTPUT_VARIABLE CPM_SOURCE_CACHE_DEFAULT) endif() set(CPM_SOURCE_CACHE diff --git a/cmake/lagrange/lagrange_tbb_sanitizers.cmake b/cmake/lagrange/lagrange_tbb_sanitizers.cmake index 66a23381..1ee91815 100644 --- a/cmake/lagrange/lagrange_tbb_sanitizers.cmake +++ b/cmake/lagrange/lagrange_tbb_sanitizers.cmake @@ -10,7 +10,11 @@ # governing permissions and limitations under the License. # -# Set TBB_SANITIZE based on the USE_SANITIZER option +# Set TBB_SANITIZE based on the USE_SANITIZER option. Even though global options are already enabled +# by our sanitizers.cmake script, setting the TBB_SANITIZE option will let OneTBB disable elements +# incompatible with TSan, such as ITT notifications and LTO: +# https://github.com/uxlfoundation/oneTBB/blob/0cd32ab10a84eabf780bb699b17430deb028c0a4/src/tbbmalloc/CMakeLists.txt#L42 +# https://github.com/uxlfoundation/oneTBB/blob/0cd32ab10a84eabf780bb699b17430deb028c0a4/CMakeLists.txt#L254 set(TBB_SANITIZE "") if(USE_SANITIZER) if(UNIX) @@ -29,7 +33,6 @@ if(USE_SANITIZER) elseif(MSVC) if(USE_SANITIZER MATCHES "([Aa]ddress)") set(TBB_SANITIZE "address -fno-omit-frame-pointer") - else() endif() endif() endif() diff --git a/cmake/recipes/external/assimp.cmake b/cmake/recipes/external/assimp.cmake index a453ea97..74214b2c 100644 --- a/cmake/recipes/external/assimp.cmake +++ b/cmake/recipes/external/assimp.cmake @@ -43,12 +43,14 @@ include(CPM) CPMAddPackage( NAME assimp GITHUB_REPOSITORY assimp/assimp - GIT_TAG 2f3e72413f25897c1903e883a94fa5cf4293e26b + GIT_TAG v6.0.2 PATCHES # Prevent Assimp from meddling with compiler flags in debug mode. # See internal lagrange-lib/#1303 for more details. # Remember to update this patch when updating Assimp. + # This patch also fixes the compilation issue related to contrib/zlib. + # See https://github.com/assimp/assimp/issues/6118 assimp.patch ) diff --git a/cmake/recipes/external/assimp.patch b/cmake/recipes/external/assimp.patch index cf73bd92..4ece804b 100644 --- a/cmake/recipes/external/assimp.patch +++ b/cmake/recipes/external/assimp.patch @@ -1,8 +1,8 @@ -diff --git i/CMakeLists.txt w/CMakeLists.txt -index 517a957f4..0f8594369 100644 ---- i/CMakeLists.txt -+++ w/CMakeLists.txt -@@ -339,7 +339,6 @@ ELSEIF(MSVC) +diff --git a/CMakeLists.txt b/CMakeLists.txt +index cd8f515..90b782a 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -343,7 +343,6 @@ ELSEIF(MSVC) ENDIF() # supress warning for double to float conversion if Double precision is activated ADD_COMPILE_OPTIONS(/wd4244) @@ -10,3 +10,18 @@ index 517a957f4..0f8594369 100644 # Allow user to disable PDBs if(ASSIMP_INSTALL_PDB) SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") +diff --git a/contrib/zlib/zutil.h b/contrib/zlib/zutil.h +index 0bc7f4e..e93e4bf 100644 +--- a/contrib/zlib/zutil.h ++++ b/contrib/zlib/zutil.h +@@ -142,10 +142,6 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ + # ifndef Z_SOLO + # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os + # include /* for fdopen */ +-# else +-# ifndef fdopen +-# define fdopen(fd,mode) NULL /* No fdopen() */ +-# endif + # endif + # endif + #endif diff --git a/modules/testing/include/lagrange/testing/common.h b/modules/testing/include/lagrange/testing/common.h index ee494bd5..238ab632 100644 --- a/modules/testing/include/lagrange/testing/common.h +++ b/modules/testing/include/lagrange/testing/common.h @@ -164,7 +164,9 @@ SurfaceMesh load_surface_mesh(const fs::path& relative_path) { auto full_path = get_data_path(relative_path); REQUIRE(lagrange::fs::exists(full_path)); - return lagrange::io::load_mesh>(full_path); + io::LoadOptions options; + options.quiet = true; + return lagrange::io::load_mesh>(full_path, options); } /// From 5828f000f6b0cc6aab2b05c2998c8066a28442c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 09:13:36 -0800 Subject: [PATCH 06/66] Update Eigen to patch release. --- cmake/recipes/external/Eigen3.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/recipes/external/Eigen3.cmake b/cmake/recipes/external/Eigen3.cmake index cdbcca7b..bc86f2ae 100644 --- a/cmake/recipes/external/Eigen3.cmake +++ b/cmake/recipes/external/Eigen3.cmake @@ -26,7 +26,7 @@ else() CPMAddPackage( NAME eigen GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git - GIT_TAG 3.4.0 + GIT_TAG 3.4.1 DOWNLOAD_ONLY ON ) set(EIGEN_INCLUDE_DIRS ${eigen_SOURCE_DIR}) From 1629c366ab91080ee1793e606b6ceb569d6d6477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 10:59:17 -0800 Subject: [PATCH 07/66] Try to use /Zi with sccache... --- .github/workflows/continuous.yaml | 1 + CMakeLists.txt | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index eb0ea024..114b9e24 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -202,6 +202,7 @@ jobs: -DCMAKE_BUILD_TYPE=${{ matrix.config }} ^ -DLAGRANGE_JENKINS=ON ^ -DLAGRANGE_ALL=ON ^ + -DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT=$<$:ProgramDatabase> ^ -B "C:/build" ^ -S . cmake --build "C:/build" -j ${{ steps.cpu-cores.outputs.count }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 9729fde7..a433ffd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,9 @@ set_property(CACHE LAGRANGE_CCACHE_PROGRAM PROPERTY STRINGS ${LAGRANGE_CCACHE_PR # Enable sscache if available if((LAGRANGE_CCACHE_PROGRAM STREQUAL "sccache") AND SCCACHE_PROGRAM) message(STATUS "Using sccache: ${SCCACHE_PROGRAM}") - set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") + if(NOT DEFINED CMAKE_MSVC_DEBUG_INFORMATION_FORMAT) + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") + endif() foreach(lang IN ITEMS C CXX) set(CMAKE_${lang}_COMPILER_LAUNCHER ${CMAKE_COMMAND} -E env ${ccacheEnv} ${SCCACHE_PROGRAM} @@ -79,6 +81,8 @@ if((LAGRANGE_CCACHE_PROGRAM STREQUAL "ccache") AND CCACHE_PROGRAM) CCACHE_SLOPPINESS=clang_index_store,include_file_ctime,include_file_mtime,locale,pch_defines,time_macros ) message(STATUS "Using ccache: ${CCACHE_PROGRAM}") + # ccache does not yet support /Zi on Windows: + # https://github.com/ccache/ccache/issues/1040 set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") foreach(lang IN ITEMS C CXX) set(CMAKE_${lang}_COMPILER_LAUNCHER From bd96fdd2d0be07ebc2694f52c32b05d854b2d7d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 11:39:17 -0800 Subject: [PATCH 08/66] Fix syntax. --- .github/workflows/continuous.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 114b9e24..ac8cb6e9 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -193,6 +193,9 @@ jobs: # We run configure + build in the same step, since they both need to call VsDevCmd # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) + # windows-2025 images have less disk space, so we need to use /Zi instead of /Z7 + # https://github.com/actions/runner-images/issues/12609 + # https://github.com/actions/runner-images/issues/12199 - name: Configure and build shell: cmd run: | @@ -202,7 +205,7 @@ jobs: -DCMAKE_BUILD_TYPE=${{ matrix.config }} ^ -DLAGRANGE_JENKINS=ON ^ -DLAGRANGE_ALL=ON ^ - -DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT=$<$:ProgramDatabase> ^ + -DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT='$<$:ProgramDatabase>' ^ -B "C:/build" ^ -S . cmake --build "C:/build" -j ${{ steps.cpu-cores.outputs.count }} From 79a5175cc6dd6626bd8d8206b85eee62bf06c1de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 11:51:00 -0800 Subject: [PATCH 09/66] Fix syntax again. --- .github/workflows/continuous.yaml | 4 ---- CMakeLists.txt | 8 ++++++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index ac8cb6e9..eb0ea024 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -193,9 +193,6 @@ jobs: # We run configure + build in the same step, since they both need to call VsDevCmd # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) - # windows-2025 images have less disk space, so we need to use /Zi instead of /Z7 - # https://github.com/actions/runner-images/issues/12609 - # https://github.com/actions/runner-images/issues/12199 - name: Configure and build shell: cmd run: | @@ -205,7 +202,6 @@ jobs: -DCMAKE_BUILD_TYPE=${{ matrix.config }} ^ -DLAGRANGE_JENKINS=ON ^ -DLAGRANGE_ALL=ON ^ - -DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT='$<$:ProgramDatabase>' ^ -B "C:/build" ^ -S . cmake --build "C:/build" -j ${{ steps.cpu-cores.outputs.count }} diff --git a/CMakeLists.txt b/CMakeLists.txt index a433ffd5..55e7e82c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,14 @@ endif() set(LAGRANGE_CCACHE_PROGRAMS none ccache sccache) set_property(CACHE LAGRANGE_CCACHE_PROGRAM PROPERTY STRINGS ${LAGRANGE_CCACHE_PROGRAMS}) +# windows-2025 images have less disk space, so we need to use /Zi instead of /Z7 +# https://github.com/actions/runner-images/issues/12609 +# https://github.com/actions/runner-images/issues/12199 +if($ENV{GITHUB_ACTIONS}) + message(STATUS "GitHub Runner detected: setting /Zi on Windows to save disk space") + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") +endif() + # Enable sscache if available if((LAGRANGE_CCACHE_PROGRAM STREQUAL "sccache") AND SCCACHE_PROGRAM) message(STATUS "Using sccache: ${SCCACHE_PROGRAM}") From fe6f41c623118c641c7dc0485ff02b6acd464657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 11:53:58 -0800 Subject: [PATCH 10/66] Update OneTBB version. --- cmake/recipes/external/onetbb.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/recipes/external/onetbb.cmake b/cmake/recipes/external/onetbb.cmake index f7a3911b..9bb4ddf4 100644 --- a/cmake/recipes/external/onetbb.cmake +++ b/cmake/recipes/external/onetbb.cmake @@ -72,7 +72,7 @@ function(onetbb_import_target) CPMAddPackage( NAME tbb GITHUB_REPOSITORY oneapi-src/oneTBB - GIT_TAG v2021.13.0 + GIT_TAG v2022.3.0 ) # TODO: This might break with future versions of onetbb. Onetbb should eventually add a proper cmake option to turn wasm threads on/off. From fc3e6f89d434d7d3d13f2672e6f8a95caf307b06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 14:05:43 -0800 Subject: [PATCH 11/66] Run ncdu after build --- .github/workflows/continuous.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index eb0ea024..9d730271 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -206,5 +206,20 @@ jobs: -S . cmake --build "C:/build" -j ${{ steps.cpu-cores.outputs.count }} + - name: Run ncdu + shell: msys2 {0} + if: always() + run: | + ncdu -0 -o ${{ matrix.config }}-C.json /C + ncdu -0 -o ${{ matrix.config }}-D.json /D + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.config }} + path: | + ${{ matrix.config }}-C.json + ${{ matrix.config }}-D.json + - name: Tests run: cd "C:/build"; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} From f2e40ab17710474ba1e31cab1dd81c658ac985d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 14:11:13 -0800 Subject: [PATCH 12/66] Print disk usage. --- .github/workflows/continuous.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 9d730271..58e9fcc9 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -191,6 +191,11 @@ jobs: # Scoop modifies the PATH so we make it available for the next steps of the job echo "${env:PATH}" >> ${env:GITHUB_PATH} + - name: Print disk usage + run: | + echo "disk usage:" + df -h + # We run configure + build in the same step, since they both need to call VsDevCmd # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) - name: Configure and build @@ -206,6 +211,12 @@ jobs: -S . cmake --build "C:/build" -j ${{ steps.cpu-cores.outputs.count }} + - name: Print disk usage + if: always() + run: | + echo "disk usage:" + df -h + - name: Run ncdu shell: msys2 {0} if: always() From 86db1de98895ab1e9170d7d07d586c7414b20d34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 15:00:42 -0800 Subject: [PATCH 13/66] Move build folder to D:/ on Windows. --- .github/workflows/continuous.yaml | 43 ++++++++++++------------------- CMakeLists.txt | 12 +-------- 2 files changed, 17 insertions(+), 38 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 58e9fcc9..e910bf7e 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -57,6 +57,11 @@ jobs: docker-images: true swap-storage: true + - name: Show disk space + run: | + echo "disk usage:" + df -h + - name: Checkout repository uses: actions/checkout@v4 with: @@ -138,6 +143,12 @@ jobs: cmake --build build -j ${{ steps.cpu-cores.outputs.count }} ccache --show-stats + - name: Show disk space + if: always() + run: | + echo "disk usage:" + df -h + - name: Tests run: cd build; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} @@ -191,11 +202,6 @@ jobs: # Scoop modifies the PATH so we make it available for the next steps of the job echo "${env:PATH}" >> ${env:GITHUB_PATH} - - name: Print disk usage - run: | - echo "disk usage:" - df -h - # We run configure + build in the same step, since they both need to call VsDevCmd # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) - name: Configure and build @@ -207,30 +213,13 @@ jobs: -DCMAKE_BUILD_TYPE=${{ matrix.config }} ^ -DLAGRANGE_JENKINS=ON ^ -DLAGRANGE_ALL=ON ^ - -B "C:/build" ^ + -B "D:/build" ^ -S . - cmake --build "C:/build" -j ${{ steps.cpu-cores.outputs.count }} - - - name: Print disk usage - if: always() - run: | - echo "disk usage:" - df -h + cmake --build "D:/build" -j ${{ steps.cpu-cores.outputs.count }} - - name: Run ncdu - shell: msys2 {0} + - name: Show disk space if: always() - run: | - ncdu -0 -o ${{ matrix.config }}-C.json /C - ncdu -0 -o ${{ matrix.config }}-D.json /D - - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.config }} - path: | - ${{ matrix.config }}-C.json - ${{ matrix.config }}-D.json + run: Get-PSDrive - name: Tests - run: cd "C:/build"; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} + run: cd "D:/build"; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 55e7e82c..a89f00d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,20 +61,10 @@ endif() set(LAGRANGE_CCACHE_PROGRAMS none ccache sccache) set_property(CACHE LAGRANGE_CCACHE_PROGRAM PROPERTY STRINGS ${LAGRANGE_CCACHE_PROGRAMS}) -# windows-2025 images have less disk space, so we need to use /Zi instead of /Z7 -# https://github.com/actions/runner-images/issues/12609 -# https://github.com/actions/runner-images/issues/12199 -if($ENV{GITHUB_ACTIONS}) - message(STATUS "GitHub Runner detected: setting /Zi on Windows to save disk space") - set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") -endif() - # Enable sscache if available if((LAGRANGE_CCACHE_PROGRAM STREQUAL "sccache") AND SCCACHE_PROGRAM) message(STATUS "Using sccache: ${SCCACHE_PROGRAM}") - if(NOT DEFINED CMAKE_MSVC_DEBUG_INFORMATION_FORMAT) - set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") - endif() + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") foreach(lang IN ITEMS C CXX) set(CMAKE_${lang}_COMPILER_LAUNCHER ${CMAKE_COMMAND} -E env ${ccacheEnv} ${SCCACHE_PROGRAM} From bbff5152c30c1bccfa63fa8cd2cde4ed1e98d1c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 13 Nov 2025 16:04:35 -0800 Subject: [PATCH 14/66] Hide eigen warnings. --- cmake/recipes/external/Eigen3.cmake | 2 +- modules/core/include/lagrange/utils/warning.h | 7 +++++++ modules/polyddg/src/DifferentialOperators.cpp | 3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/cmake/recipes/external/Eigen3.cmake b/cmake/recipes/external/Eigen3.cmake index bc86f2ae..cdbcca7b 100644 --- a/cmake/recipes/external/Eigen3.cmake +++ b/cmake/recipes/external/Eigen3.cmake @@ -26,7 +26,7 @@ else() CPMAddPackage( NAME eigen GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git - GIT_TAG 3.4.1 + GIT_TAG 3.4.0 DOWNLOAD_ONLY ON ) set(EIGEN_INCLUDE_DIRS ${eigen_SOURCE_DIR}) diff --git a/modules/core/include/lagrange/utils/warning.h b/modules/core/include/lagrange/utils/warning.h index de45d4c4..482affc3 100644 --- a/modules/core/include/lagrange/utils/warning.h +++ b/modules/core/include/lagrange/utils/warning.h @@ -160,6 +160,13 @@ /// @hideinitializer #define LA_IGNORE_ARRAY_BOUNDS_END LA_DISABLE_WARNING_END +/// Ignore maybe uninitialized warnings (e.g. when instancing third-party code) +/// @hideinitializer +#define LA_IGNORE_MAYBE_UNINITIALIZED_START LA_DISABLE_WARNING_BEGIN \ + LA_DISABLE_WARNING_CLANG(-Wmaybe-uninitialized) +/// @hideinitializer +#define LA_IGNORE_MAYBE_UNINITIALIZED_END LA_DISABLE_WARNING_END + // clang-format on /// @} diff --git a/modules/polyddg/src/DifferentialOperators.cpp b/modules/polyddg/src/DifferentialOperators.cpp index 726b1e8e..27a67681 100644 --- a/modules/polyddg/src/DifferentialOperators.cpp +++ b/modules/polyddg/src/DifferentialOperators.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -1024,7 +1025,9 @@ DifferentialOperators::levi_civita_nrosy(Index fid, Index lv, Ind Vector nf = vec_area.row(fid); // No need to normalize Vector nv = vertex_normal.row(vid); + LA_IGNORE_MAYBE_UNINITIALIZED_START auto Q = Eigen::Quaternion::FromTwoVectors(nv, nf).matrix(); + LA_IGNORE_MAYBE_UNINITIALIZED_END if (n != 1) { la_debug_assert(n > 1, "n should be positive."); From 63d511ba2cdec5588abfb21ef2a4f689c3eee82f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 01:35:03 +0000 Subject: [PATCH 15/66] Update macro. --- modules/core/include/lagrange/utils/warning.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/include/lagrange/utils/warning.h b/modules/core/include/lagrange/utils/warning.h index 482affc3..54b97b17 100644 --- a/modules/core/include/lagrange/utils/warning.h +++ b/modules/core/include/lagrange/utils/warning.h @@ -163,7 +163,7 @@ /// Ignore maybe uninitialized warnings (e.g. when instancing third-party code) /// @hideinitializer #define LA_IGNORE_MAYBE_UNINITIALIZED_START LA_DISABLE_WARNING_BEGIN \ - LA_DISABLE_WARNING_CLANG(-Wmaybe-uninitialized) + LA_DISABLE_WARNING_GCC(-Wmaybe-uninitialized) /// @hideinitializer #define LA_IGNORE_MAYBE_UNINITIALIZED_END LA_DISABLE_WARNING_END From 51d2c111e6ae512e6df1dcce26ca731410e81112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 01:46:06 +0000 Subject: [PATCH 16/66] Update Eigen warnings. --- modules/polyddg/src/DifferentialOperators.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/modules/polyddg/src/DifferentialOperators.cpp b/modules/polyddg/src/DifferentialOperators.cpp index 27a67681..9e40eecf 100644 --- a/modules/polyddg/src/DifferentialOperators.cpp +++ b/modules/polyddg/src/DifferentialOperators.cpp @@ -9,20 +9,26 @@ * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ +#include + +#include + +// Include early so we can explicitly silence warnings from Eigen. +// Note: This warning only shows up with GCC 13, even though we include Eigen headers via -isystem. +// It seems that with GCC 14+ -isystem also silences -Wmaybe-uninitialized. +LA_IGNORE_MAYBE_UNINITIALIZED_START +#include +LA_IGNORE_MAYBE_UNINITIALIZED_END #include #include #include #include -#include #include #include #include -#include #include -#include - #include #include @@ -1025,9 +1031,7 @@ DifferentialOperators::levi_civita_nrosy(Index fid, Index lv, Ind Vector nf = vec_area.row(fid); // No need to normalize Vector nv = vertex_normal.row(vid); - LA_IGNORE_MAYBE_UNINITIALIZED_START auto Q = Eigen::Quaternion::FromTwoVectors(nv, nf).matrix(); - LA_IGNORE_MAYBE_UNINITIALIZED_END if (n != 1) { la_debug_assert(n > 1, "n should be positive."); From bf621e76d3cd174557970566367b1689ad5c1940 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 17:14:08 +0000 Subject: [PATCH 17/66] Update Eigen warnings. --- modules/core/tests/test_mesh_convert.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/core/tests/test_mesh_convert.cpp b/modules/core/tests/test_mesh_convert.cpp index 94ad5c3e..f9ea96dd 100644 --- a/modules/core/tests/test_mesh_convert.cpp +++ b/modules/core/tests/test_mesh_convert.cpp @@ -9,11 +9,19 @@ * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ +#include + +// Include early so we can explicitly silence warnings from Eigen. +// Note: This warning only shows up with GCC 13 when ASan is enabled, even though we include Eigen +// headers via -isystem. It seems that with GCC 14+ -isystem also silences -Wmaybe-uninitialized. +LA_IGNORE_MAYBE_UNINITIALIZED_START +#include +LA_IGNORE_MAYBE_UNINITIALIZED_END + #include #include #include - // clang-format off #include #include From 604f0a77ca6a928bf04e0533c80072aa7b443cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 17:21:07 +0000 Subject: [PATCH 18/66] Update macOS images and Xcode versions. --- .github/workflows/continuous.yaml | 14 +++++++------- .github/workflows/wheel.yaml | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index e910bf7e..b161d57c 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -24,16 +24,16 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-24.04, macos-13, macos-15] + os: [ubuntu-24.04, macos-15-intel, macos-15] config: [RelwithDebInfo, Debug] compiler: [gcc, apple, llvm] sanitizer: ["Address", "Thread"] # TODO: Add Memory+Undefined Sanitizer exclude: - - os: macos-13 + - os: macos-15-intel compiler: gcc - - os: macos-13 + - os: macos-15-intel sanitizer: Thread - - os: macos-13 + - os: macos-15-intel config: Debug - os: macos-15 compiler: gcc @@ -96,16 +96,16 @@ jobs: fi - name: Setup Xcode version - if: matrix.os == 'macos-13' + if: matrix.os == 'macos-15-intel' uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: '15.2' + xcode-version: '16.4' - name: Setup Xcode version if: matrix.os == 'macos-15' uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: '16.4' + xcode-version: '26.0.1' - name: Get number of CPU cores uses: SimenB/github-actions-cpu-cores@v1 diff --git a/.github/workflows/wheel.yaml b/.github/workflows/wheel.yaml index e44be880..47da0999 100644 --- a/.github/workflows/wheel.yaml +++ b/.github/workflows/wheel.yaml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-24.04, macos-13, macos-15, windows-2025] + os: [ubuntu-24.04, macos-15-intel, macos-15, windows-2025] name: ${{matrix.os}} runs-on: ${{matrix.os}} @@ -23,16 +23,16 @@ jobs: uses: actions/checkout@v4 - name: Setup Xcode version - if: matrix.os == 'macos-13' + if: matrix.os == 'macos-15-intel' uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: '15.2' + xcode-version: '16.4' - name: Setup Xcode version if: matrix.os == 'macos-15' uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: '16.4' + xcode-version: '26.0.1' - name: Setup MSVC if: runner.os == 'windows' From b561bcfc95aba7d5d4083e50cb1f7600cc7d2411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 15:15:04 -0800 Subject: [PATCH 19/66] Switch to Embree4 by default and add WinArm GH runner. --- .github/workflows/continuous.yaml | 1 + cmake/lagrange/lagrange_find_package.cmake | 26 + .../external/{embree.cmake => embree3.cmake} | 8 +- .../external/{embree.patch => embree3.patch} | 0 cmake/recipes/external/embree4.cmake | 157 ++++++ cmake/recipes/external/embree4.patch | 491 ++++++++++++++++++ modules/raycasting/CMakeLists.txt | 12 +- .../lagrange/raycasting/EmbreeHelper.h | 8 +- .../lagrange/raycasting/EmbreeRayCaster.h | 63 ++- .../raycasting/embree_closest_point.h | 15 +- modules/raycasting/src/EmbreeHelper.cpp | 8 +- 11 files changed, 756 insertions(+), 33 deletions(-) rename cmake/recipes/external/{embree.cmake => embree3.cmake} (97%) rename cmake/recipes/external/{embree.patch => embree3.patch} (100%) create mode 100644 cmake/recipes/external/embree4.cmake create mode 100644 cmake/recipes/external/embree4.patch diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index b161d57c..e7dd456e 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -162,6 +162,7 @@ jobs: strategy: fail-fast: false matrix: + os: [windows-2025, windows-11-arm] config: [Release, Debug] steps: - name: Show disk space diff --git a/cmake/lagrange/lagrange_find_package.cmake b/cmake/lagrange/lagrange_find_package.cmake index 185d6b37..000b893e 100644 --- a/cmake/lagrange/lagrange_find_package.cmake +++ b/cmake/lagrange/lagrange_find_package.cmake @@ -50,6 +50,19 @@ function(lagrange_find_package name) elseif(${name} STREQUAL algcmake) find_package(${name} ${ARGN}) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} PARENT_SCOPE) + elseif(${name} STREQUAL embree) + if(${ARGC} LESS 2) + message(FATAL_ERROR "lagrange_find_package(embree ...) requires at least 1 argument for the version number, ${ARGC} given") + endif() + if(${ARGV1} EQUAL 3) + # Defer to vcpkg port + find_package(${name} ${ARGN}) + elseif(${ARGV1} EQUAL 4) + # Use internal embree4.cmake recipe + include(embree4) + else() + message(FATAL_ERROR "Unsupported embree version number: ${ARGV1}") + endif() else() find_package(${name} ${ARGN}) endif() @@ -74,6 +87,19 @@ function(lagrange_find_package name) ${algcmake_SOURCE_DIR}/modules ) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} PARENT_SCOPE) + elseif(${name} STREQUAL embree) + if(${ARGC} LESS 2) + message(FATAL_ERROR "lagrange_find_package(embree ...) requires at least 1 argument for the version number, ${ARGC} given") + endif() + if(${ARGV1} EQUAL 3) + # Redirect to embree3.cmake + include(embree3) + elseif(${ARGV1} EQUAL 4) + # Redirect to embree4.cmake + include(embree4) + else() + message(FATAL_ERROR "Unsupported embree version number: ${ARGV1}") + endif() else() include(${name}) endif() diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree3.cmake similarity index 97% rename from cmake/recipes/external/embree.cmake rename to cmake/recipes/external/embree3.cmake index 3c6cf57b..5e2d862a 100644 --- a/cmake/recipes/external/embree.cmake +++ b/cmake/recipes/external/embree3.cmake @@ -89,8 +89,10 @@ function(embree_import_target) lagrange_find_package(TBB CONFIG REQUIRED) ignore_package(TBB) get_target_property(TBB_INCLUDE_DIRS TBB::tbb INTERFACE_INCLUDE_DIRECTORIES) - add_library(TBB INTERFACE) - target_link_libraries(TBB INTERFACE TBB::tbb) + if(NOT TARGET TBB) + add_library(TBB INTERFACE) + target_link_libraries(TBB INTERFACE TBB::tbb) + endif() set(TBB_LIBRARIES TBB) # Ready to include embree's atrocious CMake @@ -105,7 +107,7 @@ function(embree_import_target) # Patch for emscripten compatibility. Fix available upstream in Embree 4+. # https://github.com/RenderKit/embree/pull/365 # https://github.com/RenderKit/embree/issues/486 - embree.patch + embree3.patch ) unignore_package(TBB) diff --git a/cmake/recipes/external/embree.patch b/cmake/recipes/external/embree3.patch similarity index 100% rename from cmake/recipes/external/embree.patch rename to cmake/recipes/external/embree3.patch diff --git a/cmake/recipes/external/embree4.cmake b/cmake/recipes/external/embree4.cmake new file mode 100644 index 00000000..8ff3c553 --- /dev/null +++ b/cmake/recipes/external/embree4.cmake @@ -0,0 +1,157 @@ +# +# Copyright 2019 Adobe. All rights reserved. +# This file is licensed to you under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under +# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +# OF ANY KIND, either express or implied. See the License for the specific language +# governing permissions and limitations under the License. +# +if(TARGET embree::embree4) + return() +endif() + +message(STATUS "Third-party (external): creating target 'embree::embree4'") + +# Set Embree's default options +option(EMBREE_ISPC_SUPPORT "Build Embree with support for ISPC applications." OFF) +option(EMBREE_TUTORIALS "Enable to build Embree tutorials" OFF) +option(EMBREE_STATIC_LIB "Build Embree as a static library." ON) +set(EMBREE_TESTING_INTENSITY 0 CACHE STRING "Intensity of testing (0 = no testing, 1 = verify and tutorials, 2 = light testing, 3 = intensive testing.") +set(EMBREE_TASKING_SYSTEM "TBB" CACHE STRING "Selects tasking system") +option(EMBREE_IGNORE_CMAKE_CXX_FLAGS "When enabled Embree ignores default CMAKE_CXX_FLAGS." OFF) + +# Set C++ namespace to avoid symbol collisions when compiling with embree3 side-by-side +set(EMBREE_API_NAMESPACE "embree4" CACHE STRING "C++ namespace to put API symbols into.") + +# The following options are necessary to ensure packed-ray support +option(EMBREE_RAY_MASK "Enable the usage of mask for packed ray." ON) +option(EMBREE_RAY_PACKETS "Enable the usage packed ray." ON) + +if(APPLE) + set(EMBREE_MAX_ISA "NEON" CACHE STRING "Selects highest ISA to support.") +elseif(EMSCRIPTEN) + set(EMBREE_MAX_ISA "SSE2" CACHE STRING "Selects highest ISA to support.") + set(FLAGS_SSE2 "-msse -msse2 -msimd128") # set to non-empty to prevent embree from using incorrect flags +else() + set(EMBREE_MAX_ISA "DEFAULT" CACHE STRING "Selects highest ISA to support.") +endif() + +# We want to compile Embree with TBB support, so we need to overwrite Embree's +# `find_package()` and provide variables. The following discussion provide some +# context on how to achieve this: +# - https://gitlab.kitware.com/cmake/cmake/issues/17735 +# - https://crascit.com/2018/09/14/do-not-redefine-cmake-commands/ +function(embree4_import_target) + macro(push_variable var value) + if(DEFINED CACHE{${var}}) + set(LAGRANGE_OLD_${var}_VALUE "${${var}}") + set(LAGRANGE_OLD_${var}_TYPE CACHE_TYPE) + elseif(DEFINED ${var}) + set(LAGRANGE_OLD_${var}_VALUE "${${var}}") + set(LAGRANGE_OLD_${var}_TYPE NORMAL_TYPE) + else() + set(LAGRANGE_OLD_${var}_TYPE NONE_TYPE) + endif() + set(${var} "${value}") + endmacro() + + macro(pop_variable var) + if(LAGRANGE_OLD_${var}_TYPE STREQUAL CACHE_TYPE) + set(${var} "${LAGRANGE_OLD_${var}_VALUE}" CACHE PATH "" FORCE) + elseif(LAGRANGE_OLD_${var}_TYPE STREQUAL NORMAL_TYPE) + unset(${var} CACHE) + set(${var} "${LAGRANGE_OLD_${var}_VALUE}") + elseif(LAGRANGE_OLD_${var}_TYPE STREQUAL NONE_TYPE) + unset(${var} CACHE) + else() + message(FATAL_ERROR "Trying to pop a variable that has not been pushed: ${var}") + endif() + endmacro() + + macro(ignore_package NAME) + set(LAGRANGE_DUMMY_DIR "${CMAKE_CURRENT_BINARY_DIR}/embree_cmake/${NAME}") + file(WRITE ${LAGRANGE_DUMMY_DIR}/${NAME}Config.cmake "") + push_variable(${NAME}_DIR ${LAGRANGE_DUMMY_DIR}) + push_variable(${NAME}_ROOT ${LAGRANGE_DUMMY_DIR}) + endmacro() + + macro(unignore_package NAME) + pop_variable(${NAME}_DIR) + pop_variable(${NAME}_ROOT) + endmacro() + + # Prefer Config mode before Module mode to prevent embree from loading its own FindTBB.cmake + set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) + + # Embree wants to be able to export() its target, and expects a target named `TBB` to exist. + # Somehow we stil need to define `TBB_INCLUDE_DIRS`, and linking against `TBB` isn't sufficient + # to compile embree targets properly. + lagrange_find_package(TBB CONFIG REQUIRED) + ignore_package(TBB) + get_target_property(TBB_INCLUDE_DIRS TBB::tbb INTERFACE_INCLUDE_DIRECTORIES) + if(NOT TARGET TBB) + add_library(TBB INTERFACE) + target_link_libraries(TBB INTERFACE TBB::tbb) + endif() + set(TBB_LIBRARIES TBB) + + # Ready to include embree's atrocious CMake + include(CPM) + CPMAddPackage( + NAME embree4 + GITHUB_REPOSITORY RenderKit/embree + GIT_TAG v4.4.0 + + # Maybe one day we'll have https://gitlab.kitware.com/cmake/cmake/-/issues/22687 + # Until then, if we want to compile both Embree3 and Embree4 side by side, we need patching + ) + + unignore_package(TBB) + + # Disable warnings + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # Embree's subgrid.h is known for causing array subscript out of bound + # warning. Embree dev claim the code is correct and it is a GCC bug + # for misfiring warnings. See https://github.com/embree/embree/issues/271 + # + # The issue should be fixed for gcc 9.2.1 and later. + target_compile_options(embree4_embree PRIVATE "-Wno-array-bounds") + endif() + + # Warning setting + set(unix_compilers "AppleClang;Clang;GNU") + if(CMAKE_CXX_COMPILER_ID IN_LIST unix_compilers) # IN_LIST wants the second arg to be a var + target_compile_options(embree4_embree PRIVATE "-Wno-unused-private-field") + target_compile_options(embree4_embree PRIVATE "-Wno-unused-but-set-variable") + endif() + + # Now we need to do some juggling to propagate the include directory properties + # along with the `embree` target + add_library(embree::embree4 INTERFACE IMPORTED GLOBAL) + target_include_directories(embree::embree4 SYSTEM INTERFACE ${embree4_SOURCE_DIR}/include) + target_link_libraries(embree::embree4 INTERFACE embree4_embree) + + # Generate a dummy .cpp for embree's math library, to workaround a weird link issue with + # LLVM-Clang on macOS + # Generate implementation file + file(WRITE "${embree4_BINARY_DIR}/embree_math_dummy.cpp.in" [[ + namespace embree { + void math_dummy() {} + } + ]]) + configure_file(${embree4_BINARY_DIR}/embree_math_dummy.cpp.in ${embree4_BINARY_DIR}/embree_math_dummy.cpp COPYONLY) + target_sources(embree4_math PRIVATE ${embree4_BINARY_DIR}/embree_math_dummy.cpp) +endfunction() + +# Call via a proper function in order to scope variables such as CMAKE_FIND_PACKAGE_PREFER_CONFIG and TBB_DIR +embree4_import_target() + +# Cleanup for IDEs +foreach(name IN ITEMS embree algorithms lexers math simd sys tasking uninstall) + if(TARGET ${name}) + set_target_properties(embree4_${name} PROPERTIES FOLDER "third_party//embree4") + endif() +endforeach() diff --git a/cmake/recipes/external/embree4.patch b/cmake/recipes/external/embree4.patch new file mode 100644 index 00000000..75c28184 --- /dev/null +++ b/cmake/recipes/external/embree4.patch @@ -0,0 +1,491 @@ +diff --git i/CMakeLists.txt w/CMakeLists.txt +index 1292e265..f386ecb5 100644 +--- i/CMakeLists.txt ++++ w/CMakeLists.txt +@@ -691,16 +691,16 @@ ENDIF() + # Uninstall + ############################################################## + +-IF (NOT TARGET uninstall) ++IF (NOT TARGET embree4_uninstall) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/common/cmake/uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake" + IMMEDIATE @ONLY) + +- add_custom_target(uninstall ++ add_custom_target(embree4_uninstall + COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake") + +- SET_PROPERTY(TARGET uninstall PROPERTY FOLDER CMakePredefinedTargets) ++ SET_PROPERTY(TARGET embree4_uninstall PROPERTY FOLDER CMakePredefinedTargets) + ENDIF() + + ############################################################## +diff --git i/common/lexers/CMakeLists.txt w/common/lexers/CMakeLists.txt +index 1e2452cd..5d060c7a 100644 +--- i/common/lexers/CMakeLists.txt ++++ w/common/lexers/CMakeLists.txt +@@ -1,16 +1,16 @@ + ## Copyright 2009-2021 Intel Corporation + ## SPDX-License-Identifier: Apache-2.0 + +-ADD_LIBRARY(lexers STATIC ++ADD_LIBRARY(embree4_lexers STATIC + stringstream.cpp + tokenstream.cpp + ) +-TARGET_LINK_LIBRARIES(lexers sys math) +-SET_PROPERTY(TARGET lexers PROPERTY FOLDER common) +-SET_PROPERTY(TARGET lexers APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") ++TARGET_LINK_LIBRARIES(embree4_lexers embree4_sys embree4_math) ++SET_PROPERTY(TARGET embree4_lexers PROPERTY FOLDER common) ++SET_PROPERTY(TARGET embree4_lexers APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") + + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS lexers EXPORT lexers-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_lexers EXPORT lexers-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT lexers-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() + +diff --git i/common/math/CMakeLists.txt w/common/math/CMakeLists.txt +index fcfa4559..6cfed20e 100644 +--- i/common/math/CMakeLists.txt ++++ w/common/math/CMakeLists.txt +@@ -1,12 +1,12 @@ + ## Copyright 2009-2021 Intel Corporation + ## SPDX-License-Identifier: Apache-2.0 + +-ADD_LIBRARY(math STATIC constants.cpp) +-SET_PROPERTY(TARGET math PROPERTY FOLDER common) +-SET_PROPERTY(TARGET math APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") ++ADD_LIBRARY(embree4_math STATIC constants.cpp) ++SET_PROPERTY(TARGET embree4_math PROPERTY FOLDER common) ++SET_PROPERTY(TARGET embree4_math APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") + + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS math EXPORT math-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_math EXPORT math-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT math-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() + +diff --git i/common/simd/CMakeLists.txt w/common/simd/CMakeLists.txt +index 989a00d6..742b885d 100644 +--- i/common/simd/CMakeLists.txt ++++ w/common/simd/CMakeLists.txt +@@ -1,11 +1,11 @@ + ## Copyright 2009-2021 Intel Corporation + ## SPDX-License-Identifier: Apache-2.0 + +-ADD_LIBRARY(simd STATIC sse.cpp) +-SET_PROPERTY(TARGET simd PROPERTY FOLDER common) +-SET_PROPERTY(TARGET simd APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") ++ADD_LIBRARY(embree4_simd STATIC sse.cpp) ++SET_PROPERTY(TARGET embree4_simd PROPERTY FOLDER common) ++SET_PROPERTY(TARGET embree4_simd APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") + + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS simd EXPORT simd-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_simd EXPORT simd-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT simd-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() +diff --git i/common/sys/CMakeLists.txt w/common/sys/CMakeLists.txt +index 66fc7083..d0e16cde 100644 +--- i/common/sys/CMakeLists.txt ++++ w/common/sys/CMakeLists.txt +@@ -4,7 +4,7 @@ + SET(CMAKE_THREAD_PREFER_PTHREAD TRUE) + FIND_PACKAGE(Threads REQUIRED) + +-ADD_LIBRARY(sys STATIC ++ADD_LIBRARY(embree4_sys STATIC + sysinfo.cpp + alloc.cpp + filename.cpp +@@ -17,16 +17,16 @@ ADD_LIBRARY(sys STATIC + barrier.cpp + ) + +-SET_PROPERTY(TARGET sys PROPERTY FOLDER common) +-SET_PROPERTY(TARGET sys APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") ++SET_PROPERTY(TARGET embree4_sys PROPERTY FOLDER common) ++SET_PROPERTY(TARGET embree4_sys APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") + +-TARGET_LINK_LIBRARIES(sys ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) ++TARGET_LINK_LIBRARIES(embree4_sys ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) + IF (EMBREE_SYCL_SUPPORT) +- TARGET_LINK_LIBRARIES(sys ${SYCL_LIB_NAME}) ++ TARGET_LINK_LIBRARIES(embree4_sys ${SYCL_LIB_NAME}) + ENDIF() + + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS sys EXPORT sys-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_sys EXPORT sys-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT sys-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() + +diff --git i/common/tasking/CMakeLists.txt w/common/tasking/CMakeLists.txt +index bf790ef6..e2768e98 100644 +--- i/common/tasking/CMakeLists.txt ++++ w/common/tasking/CMakeLists.txt +@@ -2,7 +2,7 @@ + ## SPDX-License-Identifier: Apache-2.0 + + IF (TASKING_INTERNAL) +- ADD_LIBRARY(tasking STATIC taskschedulerinternal.cpp) ++ ADD_LIBRARY(embree4_tasking STATIC taskschedulerinternal.cpp) + ELSEIF (TASKING_TBB) + ############################################################## + # Find TBB +@@ -13,16 +13,16 @@ ELSEIF (TASKING_TBB) + list(APPEND CMAKE_PREFIX_PATH ${EMBREE_TBB_ROOT}) + endif() + +- ADD_LIBRARY(tasking STATIC taskschedulertbb.cpp) ++ ADD_LIBRARY(embree4_tasking STATIC taskschedulertbb.cpp) + + if (TARGET TBB::${EMBREE_TBB_COMPONENT}) + message("-- TBB: reuse existing TBB::${TBB_COMPONENT} target") +- TARGET_LINK_LIBRARIES(tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) ++ TARGET_LINK_LIBRARIES(embree4_tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) + else() + # Try getting TBB via config first + find_package(TBB 2020 COMPONENTS ${EMBREE_TBB_COMPONENT} CONFIG ${TBB_FIND_PACKAGE_OPTION}) + if (TBB_FOUND) +- TARGET_LINK_LIBRARIES(tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) ++ TARGET_LINK_LIBRARIES(embree4_tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) + message("-- Found TBB: ${TBB_VERSION} at ${TBB_DIR} via TBBConfig.cmake") + else() + +@@ -32,8 +32,8 @@ ELSEIF (TASKING_TBB) + unset(TBB_DIR CACHE) + find_package(TBB 4.1 REQUIRED ${EMBREE_TBB_COMPONENT}) + if (TBB_FOUND) +- TARGET_LINK_LIBRARIES(tasking PUBLIC TBB) +- TARGET_INCLUDE_DIRECTORIES(tasking PUBLIC $) ++ TARGET_LINK_LIBRARIES(embree4_tasking PUBLIC TBB) ++ TARGET_INCLUDE_DIRECTORIES(embree4_tasking PUBLIC $) + + IF (EMBREE_STATIC_LIB) + INSTALL(TARGETS TBB EXPORT TBB-targets) +@@ -50,8 +50,8 @@ ELSEIF (TASKING_TBB) + IF(WIN32) + GET_TARGET_PROPERTY(DLL_PATH TBB::${EMBREE_TBB_COMPONENT} IMPORTED_LOCATION_RELEASE) + GET_TARGET_PROPERTY(DLL_PATH_DEBUG TBB::${EMBREE_TBB_COMPONENT} IMPORTED_LOCATION_DEBUG) +- SET_TARGET_PROPERTIES(tasking PROPERTIES IMPORTED_LOCATION_RELEASE ${DLL_PATH}) +- SET_TARGET_PROPERTIES(tasking PROPERTIES IMPORTED_LOCATION_DEBUG ${DLL_PATH_DEBUG}) ++ SET_TARGET_PROPERTIES(embree4_tasking PROPERTIES IMPORTED_LOCATION_RELEASE ${DLL_PATH}) ++ SET_TARGET_PROPERTIES(embree4_tasking PROPERTIES IMPORTED_LOCATION_DEBUG ${DLL_PATH_DEBUG}) + ENDIF() + + ############################################################### +@@ -65,14 +65,14 @@ ELSEIF (TASKING_TBB) + include(installTBB) + + ELSEIF (TASKING_PPL) +- ADD_LIBRARY(tasking STATIC taskschedulerppl.cpp) +- TARGET_LINK_LIBRARIES(tasking PUBLIC ${PPL_LIBRARIES}) ++ ADD_LIBRARY(embree4_tasking STATIC taskschedulerppl.cpp) ++ TARGET_LINK_LIBRARIES(embree4_tasking PUBLIC ${PPL_LIBRARIES}) + ENDIF() + +-SET_PROPERTY(TARGET tasking PROPERTY FOLDER common) +-SET_PROPERTY(TARGET tasking APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") ++SET_PROPERTY(TARGET embree4_tasking PROPERTY FOLDER common) ++SET_PROPERTY(TARGET embree4_tasking APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") + + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS tasking EXPORT tasking-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_tasking EXPORT tasking-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT tasking-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() +diff --git i/kernels/CMakeLists.txt w/kernels/CMakeLists.txt +index b8278079..da9824f3 100644 +--- i/kernels/CMakeLists.txt ++++ w/kernels/CMakeLists.txt +@@ -31,7 +31,7 @@ SOURCE_GROUP("Source Files\\algorithms" "/algorithms/") + SOURCE_GROUP("" FILES embree.rc) + + SET(EMBREE_LIBRARY_FILES +- ++ + embree.rc + + common/device.cpp +@@ -105,7 +105,7 @@ IF (EMBREE_GEOMETRY_SUBDIVISION) + subdiv/tessellation_cache.cpp + subdiv/subdivpatch1base.cpp + subdiv/catmullclark_coefficients.cpp +- geometry/grid_soa.cpp ++ geometry/grid_soa.cpp + subdiv/subdivpatch1base_eval.cpp + bvh/bvh_builder_subdiv.cpp) + ENDIF() +@@ -116,7 +116,7 @@ IF (EMBREE_RAY_PACKETS) + ENDIF() + + MACRO(embree_files TARGET ISA) +- ++ + SET(${TARGET} + geometry/instance_intersector.cpp + geometry/instance_array_intersector.cpp +@@ -130,16 +130,16 @@ MACRO(embree_files TARGET ISA) + + IF (${ISA} EQUAL ${ISA_LOWEST_AVX}) + LIST(APPEND ${TARGET} geometry/primitive8.cpp) +- ENDIF() ++ ENDIF() + + IF (${ISA} EQUAL ${SSE2} OR ${ISA} EQUAL ${AVX} OR ${ISA} EQUAL ${AVX2} OR ${ISA} EQUAL ${AVX512} OR ${ISA_LOWEST} EQUAL ${ISA}) +- ++ + LIST(APPEND ${TARGET} + common/scene_user_geometry.cpp + common/scene_instance.cpp + common/scene_instance_array.cpp + common/scene_triangle_mesh.cpp +- common/scene_quad_mesh.cpp ++ common/scene_quad_mesh.cpp + common/scene_curves.cpp + common/scene_line_segments.cpp + common/scene_grid_mesh.cpp +@@ -166,7 +166,7 @@ MACRO(embree_files TARGET ISA) + bvh/bvh_rotate.cpp + builders/primrefgen.cpp) + ENDIF() +- ++ + IF (${ISA} GREATER ${SSE42}) + LIST(APPEND ${TARGET} bvh/bvh_intersector1_bvh8.cpp) + ENDIF() +@@ -183,7 +183,7 @@ MACRO(embree_files TARGET ISA) + geometry/grid_soa.cpp + subdiv/subdivpatch1base_eval.cpp) + ENDIF() +- ++ + IF (EMBREE_RAY_PACKETS) + LIST(APPEND ${TARGET} + bvh/bvh_intersector_hybrid4_bvh4.cpp) +@@ -201,7 +201,7 @@ MACRO(embree_files TARGET ISA) + bvh/bvh_intersector_hybrid16_bvh4.cpp) + ENDIF() + ENDIF() +- ++ + ENDMACRO() + + #embree_files(EMBREE_LIBRARY_FILES_SSE2 ${SSE2}) +@@ -225,7 +225,7 @@ MACRO (CreateISADummyFiles list isa) + SET(dst_file "${CMAKE_BINARY_DIR}/${src}.${isa}.cpp") + SET(${list} ${${list}} ${dst_file}) + ADD_CUSTOM_COMMAND(OUTPUT ${dst_file} +- COMMAND ${CMAKE_COMMAND} ++ COMMAND ${CMAKE_COMMAND} + -D src=${src_file} + -D dst=${dst_file} + -P "${PROJECT_SOURCE_DIR}/common/cmake/create_isa_dummy_file.cmake" +@@ -243,40 +243,40 @@ MACRO (CheckGlobals library) + ADD_CUSTOM_TARGET(${library}_check_globals ALL COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_globals.cmake" DEPENDS ${library}) + ENDIF() + ENDMACRO() +- ++ + DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES}) +-ADD_LIBRARY(embree ${EMBREE_LIB_TYPE} ${EMBREE_LIBRARY_FILES}) ++ADD_LIBRARY(embree4_embree ${EMBREE_LIB_TYPE} ${EMBREE_LIBRARY_FILES}) + + IF (EMBREE_SYCL_SUPPORT) + # add link flag '-fsycl' here to include the kernel for USM prefetch from + # scene_sycl.cpp in embree4.dll/embree4.so +- TARGET_LINK_OPTIONS(embree PRIVATE "-fsycl") ++ TARGET_LINK_OPTIONS(embree4_embree PRIVATE "-fsycl") + +- ADD_LIBRARY(embree_sycl STATIC ++ ADD_LIBRARY(embree4_embree_sycl STATIC + sycl/rtcore_sycl.cpp + sycl/rthwif_embree.cpp) + +- SET_TARGET_PROPERTIES(embree_sycl PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS_SYCL}) ++ SET_TARGET_PROPERTIES(embree4_embree_sycl PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS_SYCL}) + IF (EMBREE_SYCL_RT_VALIDATION_API) +- TARGET_LINK_LIBRARIES(embree_sycl PRIVATE embree_rthwif_sycl) ++ TARGET_LINK_LIBRARIES(embree4_embree_sycl PRIVATE embree_rthwif_sycl) + ENDIF() + + IF (EMBREE_SYCL_RT_SIMULATION) +- TARGET_LINK_LIBRARIES(embree_sycl PRIVATE rtcore) ++ TARGET_LINK_LIBRARIES(embree4_embree_sycl PRIVATE rtcore) + ENDIF() + +- INSTALL(TARGETS embree_sycl EXPORT embree_sycl-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) ++ INSTALL(TARGETS embree4_embree_sycl EXPORT embree_sycl-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) + INSTALL(EXPORT embree_sycl-targets DESTINATION ${EMBREE_CMAKEEXPORT_DIR} COMPONENT devel) + +- SET_TARGET_PROPERTIES(embree_sycl PROPERTIES OUTPUT_NAME embree${EMBREE_VERSION_MAJOR}_sycl) ++ SET_TARGET_PROPERTIES(embree4_embree_sycl PROPERTIES OUTPUT_NAME embree${EMBREE_VERSION_MAJOR}_sycl) + + ENDIF() + +-SET_TARGET_PROPERTIES(embree PROPERTIES COMPILE_FLAGS "${FLAGS_LOWEST}") +-SET_TARGET_PROPERTIES(embree PROPERTIES COMPILE_DEFINITIONS "EMBREE_LOWEST_ISA") +-SET_PROPERTY(TARGET embree PROPERTY FOLDER kernels) ++SET_TARGET_PROPERTIES(embree4_embree PROPERTIES COMPILE_FLAGS "${FLAGS_LOWEST}") ++SET_TARGET_PROPERTIES(embree4_embree PROPERTIES COMPILE_DEFINITIONS "EMBREE_LOWEST_ISA") ++SET_PROPERTY(TARGET embree4_embree PROPERTY FOLDER kernels) + IF (NOT WIN32 AND NOT APPLE) +- ADD_CUSTOM_TARGET(embree_check_stack_frame_size COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_stack_frame_size.cmake" DEPENDS embree) ++ ADD_CUSTOM_TARGET(embree_check_stack_frame_size COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_stack_frame_size.cmake" DEPENDS embree4_embree) + ENDIF() + + #IF (EMBREE_ISA_SSE2 AND EMBREE_LIBRARY_FILES_SSE2) +@@ -292,68 +292,68 @@ ENDIF() + + IF (EMBREE_ISA_SSE42 AND EMBREE_LIBRARY_FILES_SSE42) + DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_SSE42}) +- ADD_LIBRARY(embree_sse42 STATIC ${EMBREE_LIBRARY_FILES_SSE42}) +- TARGET_LINK_LIBRARIES(embree_sse42 PRIVATE tasking) +- SET_TARGET_PROPERTIES(embree_sse42 PROPERTIES COMPILE_FLAGS "${FLAGS_SSE42}") +- SET_PROPERTY(TARGET embree_sse42 PROPERTY FOLDER kernels) +- SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_sse42) +- CheckGlobals(embree_sse42) ++ ADD_LIBRARY(embree4_embree_sse42 STATIC ${EMBREE_LIBRARY_FILES_SSE42}) ++ TARGET_LINK_LIBRARIES(embree4_embree_sse42 PRIVATE tasking) ++ SET_TARGET_PROPERTIES(embree4_embree_sse42 PROPERTIES COMPILE_FLAGS "${FLAGS_SSE42}") ++ SET_PROPERTY(TARGET embree4_embree_sse42 PROPERTY FOLDER kernels) ++ SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree4_embree_sse42) ++ CheckGlobals(embree4_embree_sse42) + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS embree_sse42 EXPORT embree_sse42-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_embree_sse42 EXPORT embree_sse42-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT embree_sse42-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() + ENDIF () + + IF (EMBREE_ISA_AVX AND EMBREE_LIBRARY_FILES_AVX) + DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX}) +- ADD_LIBRARY(embree_avx STATIC ${EMBREE_LIBRARY_FILES_AVX}) +- TARGET_LINK_LIBRARIES(embree_avx PRIVATE tasking) +- SET_TARGET_PROPERTIES(embree_avx PROPERTIES COMPILE_FLAGS "${FLAGS_AVX}") +- SET_PROPERTY(TARGET embree_avx PROPERTY FOLDER kernels) +- SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_avx) +- CheckGlobals(embree_avx) ++ ADD_LIBRARY(embree4_embree_avx STATIC ${EMBREE_LIBRARY_FILES_AVX}) ++ TARGET_LINK_LIBRARIES(embree4_embree_avx PRIVATE tasking) ++ SET_TARGET_PROPERTIES(embree4_embree_avx PROPERTIES COMPILE_FLAGS "${FLAGS_AVX}") ++ SET_PROPERTY(TARGET embree4_embree_avx PROPERTY FOLDER kernels) ++ SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree4_embree_avx) ++ CheckGlobals(embree4_embree_avx) + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS embree_avx EXPORT embree_avx-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_embree_avx EXPORT embree_avx-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT embree_avx-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() + ENDIF() + + IF (EMBREE_ISA_AVX2 AND EMBREE_LIBRARY_FILES_AVX2) + DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX2}) +- ADD_LIBRARY(embree_avx2 STATIC ${EMBREE_LIBRARY_FILES_AVX2}) +- TARGET_LINK_LIBRARIES(embree_avx2 PRIVATE tasking) +- SET_TARGET_PROPERTIES(embree_avx2 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX2}") +- SET_PROPERTY(TARGET embree_avx2 PROPERTY FOLDER kernels) +- SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_avx2) +- CheckGlobals(embree_avx2) ++ ADD_LIBRARY(embree4_embree_avx2 STATIC ${EMBREE_LIBRARY_FILES_AVX2}) ++ TARGET_LINK_LIBRARIES(embree4_embree_avx2 PRIVATE tasking) ++ SET_TARGET_PROPERTIES(embree4_embree_avx2 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX2}") ++ SET_PROPERTY(TARGET embree4_embree_avx2 PROPERTY FOLDER kernels) ++ SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree4_embree_avx2) ++ CheckGlobals(embree4_embree_avx2) + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS embree_avx2 EXPORT embree_avx2-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_embree_avx2 EXPORT embree_avx2-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT embree_avx2-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() + ENDIF() + + IF (EMBREE_ISA_AVX512 AND EMBREE_LIBRARY_FILES_AVX512) + DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX512}) +- ADD_LIBRARY(embree_avx512 STATIC ${EMBREE_LIBRARY_FILES_AVX512}) +- TARGET_LINK_LIBRARIES(embree_avx512 PRIVATE tasking) +- SET_TARGET_PROPERTIES(embree_avx512 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX512}") +- SET_PROPERTY(TARGET embree_avx512 PROPERTY FOLDER kernels) +- SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_avx512) +- CheckGlobals(embree_avx512) ++ ADD_LIBRARY(embree4_embree_avx512 STATIC ${EMBREE_LIBRARY_FILES_AVX512}) ++ TARGET_LINK_LIBRARIES(embree4_embree_avx512 PRIVATE tasking) ++ SET_TARGET_PROPERTIES(embree4_embree_avx512 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX512}") ++ SET_PROPERTY(TARGET embree4_embree_avx512 PROPERTY FOLDER kernels) ++ SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree4_embree_avx512) ++ CheckGlobals(embree4_embree_avx512) + IF (EMBREE_STATIC_LIB) +- INSTALL(TARGETS embree_avx512 EXPORT embree_avx512-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) ++ INSTALL(TARGETS embree4_embree_avx512 EXPORT embree_avx512-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) + INSTALL(EXPORT embree_avx512-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) + ENDIF() + ENDIF() + +-TARGET_LINK_LIBRARIES(embree PRIVATE ${EMBREE_LIBRARIES} sys math simd lexers tasking) ++TARGET_LINK_LIBRARIES(embree4_embree PRIVATE ${EMBREE_LIBRARIES} embree4_sys embree4_math embree4_simd embree4_lexers embree4_tasking) + IF (EMBREE_SYCL_SUPPORT) +- TARGET_LINK_LIBRARIES(embree PRIVATE ${SYCL_LIB_NAME} ze_wrapper PUBLIC embree_sycl) ++ TARGET_LINK_LIBRARIES(embree4_embree PRIVATE ${SYCL_LIB_NAME} ze_wrapper PUBLIC embree4_embree_sycl) + ENDIF() + + #TARGET_LINK_LIBRARIES(embree PRIVATE ${EMBREE_LIBRARIES} sys math simd lexers tasking ${CMAKE_LINK_FLAGS_SYCL}) # FIXME: enable this line +-SET_TARGET_PROPERTIES(embree PROPERTIES OUTPUT_NAME ${EMBREE_LIBRARY_NAME}) +-target_include_directories(embree PUBLIC ++SET_TARGET_PROPERTIES(embree4_embree PROPERTIES OUTPUT_NAME ${EMBREE_LIBRARY_NAME}) ++target_include_directories(embree4_embree PUBLIC + $ + $) + +@@ -361,27 +361,27 @@ target_include_directories(embree PUBLIC + # libtbb is located in same install folder as libembree + IF(WIN32) + ELSEIF(APPLE) +- SET_TARGET_PROPERTIES(embree PROPERTIES INSTALL_RPATH "@loader_path") # On MacOSX we tell dyld to find libtbb in the folder libembree is placed ++ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES INSTALL_RPATH "@loader_path") # On MacOSX we tell dyld to find libtbb in the folder libembree is placed + ELSE() +- SET_TARGET_PROPERTIES(embree PROPERTIES INSTALL_RPATH "$ORIGIN") # Linux we tell ld to find libtbb in the folder libembree is placed. ++ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES INSTALL_RPATH "$ORIGIN") # Linux we tell ld to find libtbb in the folder libembree is placed. + ENDIF() + + IF (WIN32) + ELSEIF (APPLE) +- SET_TARGET_PROPERTIES(embree PROPERTIES LINK_FLAGS -Wl,-exported_symbols_list,"${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") +- SET_SOURCE_FILES_PROPERTIES(common/rtcore.cpp PROPERTIES OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") ++ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES LINK_FLAGS -Wl,-exported_symbols_list,"${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") ++ SET_SOURCE_FILES_PROPERTIES(common/rtcore.cpp PROPERTIES OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") + ELSE() +- SET_TARGET_PROPERTIES(embree PROPERTIES LINK_FLAGS -Wl,--version-script="${PROJECT_SOURCE_DIR}/kernels/export.linux.map") ++ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES LINK_FLAGS -Wl,--version-script="${PROJECT_SOURCE_DIR}/kernels/export.linux.map") + SET_SOURCE_FILES_PROPERTIES(common/rtcore.cpp PROPERTIES OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/kernels/export.linux.map") + ENDIF() + + IF (EMBREE_ZIP_MODE) +- SET_TARGET_PROPERTIES(embree PROPERTIES VERSION ${EMBREE_VERSION_MAJOR} SOVERSION ${EMBREE_VERSION_MAJOR}) ++ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES VERSION ${EMBREE_VERSION_MAJOR} SOVERSION ${EMBREE_VERSION_MAJOR}) + ELSE() +- SET_TARGET_PROPERTIES(embree PROPERTIES VERSION ${EMBREE_VERSION} SOVERSION ${EMBREE_VERSION_MAJOR}) ++ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES VERSION ${EMBREE_VERSION} SOVERSION ${EMBREE_VERSION_MAJOR}) + ENDIF() + +-INSTALL(TARGETS embree EXPORT embree-targets ++INSTALL(TARGETS embree4_embree EXPORT embree-targets + LIBRARY NAMELINK_SKIP DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib + # on Windows put the dlls into bin + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT examples +@@ -394,9 +394,9 @@ INSTALL(EXPORT embree-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT + + # installs libembree4.so link + IF (NOT EMBREE_STATIC_LIB) +- INSTALL(TARGETS embree ++ INSTALL(TARGETS embree4_embree + LIBRARY NAMELINK_ONLY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel + ) + ENDIF() + +-SIGN_TARGET(embree) ++SIGN_TARGET(embree4_embree) diff --git a/modules/raycasting/CMakeLists.txt b/modules/raycasting/CMakeLists.txt index 0c719a4f..703be955 100644 --- a/modules/raycasting/CMakeLists.txt +++ b/modules/raycasting/CMakeLists.txt @@ -13,14 +13,22 @@ lagrange_add_module() # 2. dependencies -lagrange_find_package(embree 3 CONFIG REQUIRED) lagrange_include_modules(bvh) target_link_libraries(lagrange_raycasting PUBLIC lagrange::core lagrange::bvh - embree::embree ) +option(LAGRANGE_WITH_EMBREE_4 "Use Embree4 with Lagrange" ON) +if(LAGRANGE_WITH_EMBREE_4) + lagrange_find_package(embree 4 CONFIG REQUIRED) + target_compile_definitions(lagrange_raycasting PUBLIC LAGRANGE_WITH_EMBREE_4) + target_link_libraries(lagrange_raycasting PUBLIC embree::embree4) +else() + lagrange_find_package(embree 3 CONFIG REQUIRED) + target_link_libraries(lagrange_raycasting PUBLIC embree::embree) +endif() + option(LAGRANGE_EMBREE_DEBUG "Perform error-checking when performing each single Embree call" OFF) if(LAGRANGE_EMBREE_DEBUG) target_compile_definitions(lagrange_raycasting PUBLIC LAGRANGE_EMBREE_DEBUG) diff --git a/modules/raycasting/include/lagrange/raycasting/EmbreeHelper.h b/modules/raycasting/include/lagrange/raycasting/EmbreeHelper.h index c3793877..8e2d0626 100644 --- a/modules/raycasting/include/lagrange/raycasting/EmbreeHelper.h +++ b/modules/raycasting/include/lagrange/raycasting/EmbreeHelper.h @@ -11,9 +11,15 @@ */ #pragma once -#include +#ifdef LAGRANGE_WITH_EMBREE_4 + #include +#else + #include +#endif #include +RTC_NAMESPACE_USE + namespace lagrange { namespace raycasting { namespace EmbreeHelper { diff --git a/modules/raycasting/include/lagrange/raycasting/EmbreeRayCaster.h b/modules/raycasting/include/lagrange/raycasting/EmbreeRayCaster.h index 31cb0bbf..7ad6dbfe 100644 --- a/modules/raycasting/include/lagrange/raycasting/EmbreeRayCaster.h +++ b/modules/raycasting/include/lagrange/raycasting/EmbreeRayCaster.h @@ -11,9 +11,16 @@ */ #pragma once -#include -#include -#include +#ifdef LAGRANGE_WITH_EMBREE_4 + #include + #include + #include +#else + #include + #include + #include +#endif + #include #include #include @@ -33,6 +40,8 @@ #include #include +RTC_NAMESPACE_USE + namespace lagrange { namespace raycasting { @@ -472,11 +481,13 @@ class EmbreeRayCaster for (int i = static_cast(batch_size); i < 4; ++i) packet_mask[i] = 0; ensure_no_errors_internal(); - { - RTCIntersectContext context; - rtcInitIntersectContext(&context); - rtcIntersect4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket); - } +#ifdef LAGRANGE_WITH_EMBREE_4 + rtcIntersect4(packet_mask.data(), m_embree_world_scene, &embree_raypacket); +#else + RTCIntersectContext context; + rtcInitIntersectContext(&context); + rtcIntersect4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket); +#endif ensure_no_errors_internal(); uint32_t is_hits = 0; @@ -582,11 +593,13 @@ class EmbreeRayCaster for (int i = static_cast(batch_size); i < 4; ++i) packet_mask[i] = 0; ensure_no_errors_internal(); - { - RTCIntersectContext context; - rtcInitIntersectContext(&context); - rtcOccluded4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket); - } +#ifdef LAGRANGE_WITH_EMBREE_4 + rtcOccluded4(packet_mask.data(), m_embree_world_scene, &embree_raypacket); +#else + RTCIntersectContext context; + rtcInitIntersectContext(&context); + rtcOccluded4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket); +#endif ensure_no_errors_internal(); // If hit, the tfar field will be set to -inf. @@ -634,11 +647,13 @@ class EmbreeRayCaster embree_rayhit.ray.id = 0; embree_rayhit.ray.flags = 0; ensure_no_errors_internal(); - { - RTCIntersectContext context; - rtcInitIntersectContext(&context); - rtcIntersect1(m_embree_world_scene, &context, &embree_rayhit); - } +#ifdef LAGRANGE_WITH_EMBREE_4 + rtcIntersect1(m_embree_world_scene, &embree_rayhit); +#else + RTCIntersectContext context; + rtcInitIntersectContext(&context); + rtcIntersect1(m_embree_world_scene, &context, &embree_rayhit); +#endif ensure_no_errors_internal(); if (embree_rayhit.hit.geomID != RTC_INVALID_GEOMETRY_ID) { @@ -722,11 +737,13 @@ class EmbreeRayCaster embree_ray.flags = 0; ensure_no_errors_internal(); - { - RTCIntersectContext context; - rtcInitIntersectContext(&context); - rtcOccluded1(m_embree_world_scene, &context, &embree_ray); - } +#ifdef LAGRANGE_WITH_EMBREE_4 + rtcOccluded1(m_embree_world_scene, &embree_ray); +#else + RTCIntersectContext context; + rtcInitIntersectContext(&context); + rtcOccluded1(m_embree_world_scene, &context, &embree_ray); +#endif ensure_no_errors_internal(); // If hit, the tfar field will be set to -inf. diff --git a/modules/raycasting/include/lagrange/raycasting/embree_closest_point.h b/modules/raycasting/include/lagrange/raycasting/embree_closest_point.h index 241135b8..a8be6833 100644 --- a/modules/raycasting/include/lagrange/raycasting/embree_closest_point.h +++ b/modules/raycasting/include/lagrange/raycasting/embree_closest_point.h @@ -11,11 +11,20 @@ #include -#include -#include -#include +#ifdef LAGRANGE_WITH_EMBREE_4 + #include + #include + #include +#else + #include + #include + #include +#endif + #include +RTC_NAMESPACE_USE + namespace lagrange { namespace raycasting { diff --git a/modules/raycasting/src/EmbreeHelper.cpp b/modules/raycasting/src/EmbreeHelper.cpp index 25b983f5..9a3bde91 100644 --- a/modules/raycasting/src/EmbreeHelper.cpp +++ b/modules/raycasting/src/EmbreeHelper.cpp @@ -9,7 +9,12 @@ * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ -#include +#ifdef LAGRANGE_WITH_EMBREE_4 + #include +#else + #include +#endif + #include #include @@ -18,6 +23,7 @@ #include #include +RTC_NAMESPACE_USE void lagrange::raycasting::EmbreeHelper::ensure_no_errors(const RTCDevice& device) { From c89e2602537c2d58502db9fcd01cacca55c35b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 15:17:02 -0800 Subject: [PATCH 20/66] Run CI check on all target branches --- .github/workflows/continuous.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index e7dd456e..4d06d8b2 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -3,7 +3,7 @@ name: Build on: pull_request: branches: - - main + - '*' concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} From 83ec15126afed1ac70294fc795b793a8c7636e43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 15:18:05 -0800 Subject: [PATCH 21/66] Revert. --- .github/workflows/continuous.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 4d06d8b2..e7dd456e 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -3,7 +3,7 @@ name: Build on: pull_request: branches: - - '*' + - main concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} From 4312983a1637c97e93c324dd4eb4d8c8c2a29f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 15:37:00 -0800 Subject: [PATCH 22/66] Update build type. --- .github/workflows/continuous.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index e7dd456e..45c614e4 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -25,7 +25,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-24.04, macos-15-intel, macos-15] - config: [RelwithDebInfo, Debug] + config: [RelWithDebInfo, Debug] compiler: [gcc, apple, llvm] sanitizer: ["Address", "Thread"] # TODO: Add Memory+Undefined Sanitizer exclude: From 5109ac32592da5447f5d3f7c6bddbbad0ca6353a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 15:50:20 -0800 Subject: [PATCH 23/66] Update config. --- .github/workflows/continuous.yaml | 4 ++-- cmake/recipes/external/embree4.cmake | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 45c614e4..a9a13565 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -157,8 +157,8 @@ jobs: #################### Windows: - name: windows-2025 (${{ matrix.config }}) - runs-on: windows-2025 + name: ${{ matrix.os }} (${{ matrix.config }}) + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: diff --git a/cmake/recipes/external/embree4.cmake b/cmake/recipes/external/embree4.cmake index 8ff3c553..5175b431 100644 --- a/cmake/recipes/external/embree4.cmake +++ b/cmake/recipes/external/embree4.cmake @@ -105,8 +105,10 @@ function(embree4_import_target) GITHUB_REPOSITORY RenderKit/embree GIT_TAG v4.4.0 - # Maybe one day we'll have https://gitlab.kitware.com/cmake/cmake/-/issues/22687 - # Until then, if we want to compile both Embree3 and Embree4 side by side, we need patching + PATCHES + # Maybe one day we'll have https://gitlab.kitware.com/cmake/cmake/-/issues/22687 + # Until then, if we want to compile both Embree3 and Embree4 side by side, we need patching. + embree4.patch ) unignore_package(TBB) From 727aa72f7c9cf6ab1da6b681622fff84c46b3019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 16:09:35 -0800 Subject: [PATCH 24/66] Update sccache setup. --- .github/workflows/continuous.yaml | 20 ++++---------------- cmake/recipes/external/embree4.patch | 4 ++-- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index a9a13565..5d42ed36 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -180,28 +180,15 @@ jobs: - name: Install Ninja uses: seanmiddleditch/gha-setup-ninja@master - - name: Set env variable for sccache - run: | - echo "appdata=$env:LOCALAPPDATA" >> ${env:GITHUB_ENV} - - name: Get number of CPU cores uses: SimenB/github-actions-cpu-cores@v1 id: cpu-cores - - name: Cache build - id: cache-build - uses: actions/cache@v3 - with: - path: ${{ env.appdata }}\Mozilla\sccache - key: ${{ runner.os }}-${{ matrix.config }}-cache + - name: Configure sccache + run: echo "SCCACHE_GHA_ENABLED=true" >> ${env:GITHUB_ENV} - name: Prepare sccache - run: | - iwr -useb 'https://raw.githubusercontent.com/scoopinstaller/install/master/install.ps1' -outfile 'install.ps1' - .\install.ps1 -RunAsAdmin - scoop install sccache --global - # Scoop modifies the PATH so we make it available for the next steps of the job - echo "${env:PATH}" >> ${env:GITHUB_PATH} + uses: mozilla-actions/sccache-action@v0.0.9 # We run configure + build in the same step, since they both need to call VsDevCmd # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) @@ -217,6 +204,7 @@ jobs: -B "D:/build" ^ -S . cmake --build "D:/build" -j ${{ steps.cpu-cores.outputs.count }} + sccache --show-stats - name: Show disk space if: always() diff --git a/cmake/recipes/external/embree4.patch b/cmake/recipes/external/embree4.patch index 75c28184..b2e14a91 100644 --- a/cmake/recipes/external/embree4.patch +++ b/cmake/recipes/external/embree4.patch @@ -200,7 +200,7 @@ index bf790ef6..e2768e98 100644 INSTALL(EXPORT tasking-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) ENDIF() diff --git i/kernels/CMakeLists.txt w/kernels/CMakeLists.txt -index b8278079..da9824f3 100644 +index b8278079..33e8a3c6 100644 --- i/kernels/CMakeLists.txt +++ w/kernels/CMakeLists.txt @@ -31,7 +31,7 @@ SOURCE_GROUP("Source Files\\algorithms" "/algorithms/") @@ -336,7 +336,7 @@ index b8278079..da9824f3 100644 +SET_PROPERTY(TARGET embree4_embree PROPERTY FOLDER kernels) IF (NOT WIN32 AND NOT APPLE) - ADD_CUSTOM_TARGET(embree_check_stack_frame_size COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_stack_frame_size.cmake" DEPENDS embree) -+ ADD_CUSTOM_TARGET(embree_check_stack_frame_size COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_stack_frame_size.cmake" DEPENDS embree4_embree) ++ ADD_CUSTOM_TARGET(embree_check_stack_frame_size COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_stack_frame_size.cmake" DEPENDS embree4_embree) ENDIF() #IF (EMBREE_ISA_SSE2 AND EMBREE_LIBRARY_FILES_SSE2) From 99acb1dafa629f139f99a63dab913bdba5b7e783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 16:25:53 -0800 Subject: [PATCH 25/66] Update sscache winarm action. --- .github/workflows/continuous.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 5d42ed36..abcbeda3 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -188,7 +188,9 @@ jobs: run: echo "SCCACHE_GHA_ENABLED=true" >> ${env:GITHUB_ENV} - name: Prepare sccache - uses: mozilla-actions/sccache-action@v0.0.9 + # Re-enable official action one https://github.com/Mozilla-Actions/sccache-action/pull/225 is merged + # uses: mozilla-actions/sccache-action@v0.0.9 + uses: Vee99BR/sccache-action@v0.0.1 # We run configure + build in the same step, since they both need to call VsDevCmd # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) @@ -204,7 +206,6 @@ jobs: -B "D:/build" ^ -S . cmake --build "D:/build" -j ${{ steps.cpu-cores.outputs.count }} - sccache --show-stats - name: Show disk space if: always() From d4c0c3dead631d2aa4563dbaeb38d8d60ddfa5f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 16:48:36 -0800 Subject: [PATCH 26/66] Set build dir for winarm --- .github/workflows/continuous.yaml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index abcbeda3..6d319bef 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -192,6 +192,14 @@ jobs: # uses: mozilla-actions/sccache-action@v0.0.9 uses: Vee99BR/sccache-action@v0.0.1 + - name: Set build folder + run: | + if ("${{ matrix.os }}" -eq "windows-2025") { + echo "BUILD_DIR=D:/build" >> ${env:GITHUB_ENV} + } else { + echo "BUILD_DIR=C:/build" >> ${env:GITHUB_ENV} + } + # We run configure + build in the same step, since they both need to call VsDevCmd # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) - name: Configure and build @@ -203,13 +211,14 @@ jobs: -DCMAKE_BUILD_TYPE=${{ matrix.config }} ^ -DLAGRANGE_JENKINS=ON ^ -DLAGRANGE_ALL=ON ^ - -B "D:/build" ^ + -B %BUILD_DIR% ^ -S . - cmake --build "D:/build" -j ${{ steps.cpu-cores.outputs.count }} + cmake --build %BUILD_DIR% -j ${{ steps.cpu-cores.outputs.count }} - name: Show disk space if: always() run: Get-PSDrive - name: Tests - run: cd "D:/build"; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} + run: cd %BUILD_DIR%; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} + shell: cmd From 8010e9e96340a21c4fe5bb41ca268c638620ab9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 17:14:55 -0800 Subject: [PATCH 27/66] Patch boost context for winarm. --- cmake/recipes/external/Boost.cmake | 9 ++++++--- cmake/recipes/external/Boost.winarm.patch | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 cmake/recipes/external/Boost.winarm.patch diff --git a/cmake/recipes/external/Boost.cmake b/cmake/recipes/external/Boost.cmake index fba630f0..1c88d522 100644 --- a/cmake/recipes/external/Boost.cmake +++ b/cmake/recipes/external/Boost.cmake @@ -84,12 +84,15 @@ if(SKBUILD) set(BUILD_SHARED_LIBS ON) endif() -set(BOOST_PATCHES "") +set(BOOST_PATCHES) if(EMSCRIPTEN) # Wasm doesn't have rounding mode control yet, so we trick Boost::interval into thinking it has. # https://github.com/WebAssembly/rounding-mode-control # https://github.com/boostorg/interval/issues/44 - set(BOOST_PATCHES PATCHES Boost.wasm.patch) + list(APPEND BOOST_PATCHES Boost.wasm.patch) +endif() +if(WIN32) + list(APPEND BOOST_PATCHES Boost.winarm.patch) endif() # Modern CMake target support was added in Boost 1.82.0 @@ -101,7 +104,7 @@ CPMAddPackage( GITHUB_REPOSITORY "boostorg/boost" GIT_TAG "boost-1.84.0" EXCLUDE_FROM_ALL ON - ${BOOST_PATCHES} + PATCHES ${BOOST_PATCHES} ) if(SKBUILD) diff --git a/cmake/recipes/external/Boost.winarm.patch b/cmake/recipes/external/Boost.winarm.patch new file mode 100644 index 00000000..907e8220 --- /dev/null +++ b/cmake/recipes/external/Boost.winarm.patch @@ -0,0 +1 @@ +Submodule libs/context contains modified content From 9512ca537dde9132a24ab36a02a2e1c98509ae21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 17:29:36 -0800 Subject: [PATCH 28/66] Fix patch. --- cmake/recipes/external/Boost.winarm.patch | 134 ++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/cmake/recipes/external/Boost.winarm.patch b/cmake/recipes/external/Boost.winarm.patch index 907e8220..b788d7d5 100644 --- a/cmake/recipes/external/Boost.winarm.patch +++ b/cmake/recipes/external/Boost.winarm.patch @@ -1 +1,135 @@ Submodule libs/context contains modified content +diff --git i/libs/context/CMakeLists.txt w/libs/context/CMakeLists.txt +index dca5349..089592f 100644 +--- i/libs/context/CMakeLists.txt ++++ w/libs/context/CMakeLists.txt +@@ -12,7 +12,7 @@ list(APPEND CMAKE_MODULE_PATH ${boost_context_SOURCE_DIR}/cmake) + + ## Binary format + +-if(WIN32) ++if(WIN32 OR CYGWIN) + set(_default_binfmt pe) + elseif(APPLE) + set(_default_binfmt mach-o) +@@ -31,7 +31,7 @@ math(EXPR _bits "${CMAKE_SIZEOF_VOID_P}*8") + + if(CMAKE_SYSTEM_PROCESSOR MATCHES "^[Aa][Rr][Mm]" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") + set(_default_abi aapcs) +-elseif(WIN32) ++elseif(WIN32 OR CYGWIN) + set(_default_abi ms) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") + if(_bits EQUAL 32) +@@ -60,6 +60,8 @@ elseif(_bits EQUAL 32) + set(_default_arch arm) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") + set(_default_arch mips32) ++ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc32)") ++ set(_default_arch ppc32) + else() + set(_default_arch i386) + endif() +@@ -69,6 +71,8 @@ else() + set(_default_arch arm64) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") + set(_default_arch mips64) ++ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc64)") ++ set(_default_arch ppc64) + else() + set(_default_arch x86_64) + endif() +@@ -89,18 +93,22 @@ if(MSVC) + else() + set(_default_asm masm) + endif() ++elseif(BOOST_CONTEXT_ARCHITECTURE STREQUAL arm64 AND MINGW) ++ set(_default_asm armclang) + else() + set(_default_asm gas) + endif() + +-set(BOOST_CONTEXT_ASSEMBLER "${_default_asm}" CACHE STRING "Boost.Context assembler (masm, gas, armasm)") +-set_property(CACHE BOOST_CONTEXT_ASSEMBLER PROPERTY STRINGS masm gas armasm) ++set(BOOST_CONTEXT_ASSEMBLER "${_default_asm}" CACHE STRING "Boost.Context assembler (masm, gas, armasm, armclang)") ++set_property(CACHE BOOST_CONTEXT_ASSEMBLER PROPERTY STRINGS masm gas armasm armclang) + + unset(_default_asm) + + ## Assembler source suffix + +-if(BOOST_CONTEXT_BINARY_FORMAT STREQUAL pe) ++if(BOOST_CONTEXT_ASSEMBLER STREQUAL armclang) ++ set(_default_ext .S) ++elseif(BOOST_CONTEXT_BINARY_FORMAT STREQUAL pe) + set(_default_ext .asm) + elseif(BOOST_CONTEXT_ASSEMBLER STREQUAL gas) + set(_default_ext .S) +@@ -133,18 +141,22 @@ message(STATUS "Boost.Context: " + "implementation ${BOOST_CONTEXT_IMPLEMENTATION}") + + # Enable the right assembler +- ++set(ASM_LANGUAGE) + if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "fcontext") +- if(BOOST_CONTEXT_ASSEMBLER STREQUAL gas) ++ if(BOOST_CONTEXT_ASSEMBLER STREQUAL gas OR BOOST_CONTEXT_ASSEMBLER STREQUAL armclang) + if(CMAKE_CXX_PLATFORM_ID MATCHES "Cygwin") +- enable_language(ASM-ATT) ++ set(ASM_LANGUAGE ASM-ATT) + else() +- enable_language(ASM) ++ set(ASM_LANGUAGE ASM) + endif() + elseif(BOOST_CONTEXT_ASSEMBLER STREQUAL armasm) +- enable_language(ASM_ARMASM) ++ if(MSVC) ++ set(ASM_LANGUAGE ASM_MARMASM) ++ else() ++ set(ASM_LANGUAGE ASM_ARMASM) ++ endif() + else() +- enable_language(ASM_MASM) ++ set(ASM_LANGUAGE ASM_MASM) + endif() + endif() + +@@ -168,15 +180,31 @@ unset(_asm_suffix) + + if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "fcontext") + +- set(IMPL_SOURCES ${ASM_SOURCES}) ++ set(IMPL_SOURCES ${ASM_SOURCES} src/fcontext.cpp) + +- if(BOOST_CONTEXT_ASSEMBLER STREQUAL masm AND BOOST_CONTEXT_ARCHITECTURE STREQUAL i386) +- set_source_files_properties(${ASM_SOURCES} PROPERTIES COMPILE_FLAGS "/safeseh") +- endif() ++ if(BOOST_CONTEXT_ASSEMBLER STREQUAL masm) + +- if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") +- set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "-x" "assembler-with-cpp") +- endif() ++ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "/nologo") ++ ++ if(MSVC AND NOT(MSVC_VERSION LESS 1936) AND NOT(CMAKE_CXX_SIMULATE_VERSION)) ++ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "/quiet") ++ endif() ++ ++ if(BOOST_CONTEXT_ARCHITECTURE STREQUAL i386) ++ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "/safeseh") ++ endif() ++ ++ # armasm doesn't support most of these options ++ elseif(NOT BOOST_CONTEXT_ASSEMBLER STREQUAL armasm) # masm ++ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") ++ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "-x" "assembler-with-cpp") ++ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") ++ set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "-Wno-unused-command-line-argument") ++ endif() ++ endif() # masm ++ ++ enable_language(${ASM_LANGUAGE}) ++ set_source_files_properties(${ASM_SOURCES} PROPERTIES LANGUAGE ${ASM_LANGUAGE}) + else() + set(IMPL_SOURCES + src/continuation.cpp From 38a0c32fff8bcbf154750db06c1a662587dfb77d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 17:42:15 -0800 Subject: [PATCH 29/66] Update patch. --- cmake/recipes/external/Boost.winarm.patch | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/cmake/recipes/external/Boost.winarm.patch b/cmake/recipes/external/Boost.winarm.patch index b788d7d5..fc6681aa 100644 --- a/cmake/recipes/external/Boost.winarm.patch +++ b/cmake/recipes/external/Boost.winarm.patch @@ -1,6 +1,6 @@ Submodule libs/context contains modified content diff --git i/libs/context/CMakeLists.txt w/libs/context/CMakeLists.txt -index dca5349..089592f 100644 +index dca5349..bd064b1 100644 --- i/libs/context/CMakeLists.txt +++ w/libs/context/CMakeLists.txt @@ -12,7 +12,7 @@ list(APPEND CMAKE_MODULE_PATH ${boost_context_SOURCE_DIR}/cmake) @@ -94,12 +94,9 @@ index dca5349..089592f 100644 endif() endif() -@@ -168,15 +180,31 @@ unset(_asm_suffix) +@@ -170,13 +182,29 @@ if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "fcontext") - if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "fcontext") - -- set(IMPL_SOURCES ${ASM_SOURCES}) -+ set(IMPL_SOURCES ${ASM_SOURCES} src/fcontext.cpp) + set(IMPL_SOURCES ${ASM_SOURCES}) - if(BOOST_CONTEXT_ASSEMBLER STREQUAL masm AND BOOST_CONTEXT_ARCHITECTURE STREQUAL i386) - set_source_files_properties(${ASM_SOURCES} PROPERTIES COMPILE_FLAGS "/safeseh") From 25e206a225640886731701d1490a82bf97de0baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 21:01:35 -0800 Subject: [PATCH 30/66] Update vs dev prompt setup. --- .github/workflows/continuous.yaml | 44 ++++++++++++++++++------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 6d319bef..4b7ebf1f 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -192,33 +192,41 @@ jobs: # uses: mozilla-actions/sccache-action@v0.0.9 uses: Vee99BR/sccache-action@v0.0.1 - - name: Set build folder + - name: Set x64 vars + if: runner.os == 'windows-2025' run: | - if ("${{ matrix.os }}" -eq "windows-2025") { echo "BUILD_DIR=D:/build" >> ${env:GITHUB_ENV} - } else { + echo "ARCH=x64" >> ${env:GITHUB_ENV} + + - name: Set arm64 vars + if: runner.os == 'windows-11-arm' + run: | echo "BUILD_DIR=C:/build" >> ${env:GITHUB_ENV} - } + echo "ARCH=arm64" >> ${env:GITHUB_ENV} - # We run configure + build in the same step, since they both need to call VsDevCmd - # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) - - name: Configure and build - shell: cmd + - name: Setup MSVC Developer Command Prompt + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: ${{ env.ARCH }} + + # Cmd uses ^ to break commands into multiple lines, powershell uses ` + - name: Configure run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=x64 - cmake --version - cmake -G Ninja ^ - -DCMAKE_BUILD_TYPE=${{ matrix.config }} ^ - -DLAGRANGE_JENKINS=ON ^ - -DLAGRANGE_ALL=ON ^ - -B %BUILD_DIR% ^ + cmake --version ` + cmake -G Ninja ` + -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` + -DLAGRANGE_JENKINS=ON ` + -DLAGRANGE_ALL=ON ` + -B ${{ env.BUILD_DIR }} ` -S . - cmake --build %BUILD_DIR% -j ${{ steps.cpu-cores.outputs.count }} + + - name: Build + run: | + cmake --build ${{ env.BUILD_DIR }} -j ${{ steps.cpu-cores.outputs.count }} - name: Show disk space if: always() run: Get-PSDrive - name: Tests - run: cd %BUILD_DIR%; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} - shell: cmd + run: cd ${{ env.BUILD_DIR }}; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} From 7afbec68eb1009e93feadae7e330026ecb871631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 21:27:22 -0800 Subject: [PATCH 31/66] Fix line break. --- .github/workflows/continuous.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 4b7ebf1f..593c7b4d 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -212,7 +212,7 @@ jobs: # Cmd uses ^ to break commands into multiple lines, powershell uses ` - name: Configure run: | - cmake --version ` + cmake --version cmake -G Ninja ` -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` -DLAGRANGE_JENKINS=ON ` From c0593e99cc03d00af05d108d064a4bf5c5293458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 14 Nov 2025 22:07:55 -0800 Subject: [PATCH 32/66] Update config. --- .github/workflows/continuous.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 593c7b4d..7f8e6937 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -193,13 +193,13 @@ jobs: uses: Vee99BR/sccache-action@v0.0.1 - name: Set x64 vars - if: runner.os == 'windows-2025' + if: matrix.os == 'windows-2025' run: | echo "BUILD_DIR=D:/build" >> ${env:GITHUB_ENV} echo "ARCH=x64" >> ${env:GITHUB_ENV} - name: Set arm64 vars - if: runner.os == 'windows-11-arm' + if: matrix.os == 'windows-11-arm' run: | echo "BUILD_DIR=C:/build" >> ${env:GITHUB_ENV} echo "ARCH=arm64" >> ${env:GITHUB_ENV} From 31d6d1599ec11c8aaf9ea39a76c224dc8ca6e7f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Fri, 20 Feb 2026 08:12:28 -0800 Subject: [PATCH 33/66] Update sscache action. --- .github/workflows/continuous.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index fe8680a4..231895ef 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -214,9 +214,7 @@ jobs: run: echo "SCCACHE_GHA_ENABLED=true" >> ${env:GITHUB_ENV} - name: Prepare sccache - # Re-enable official action one https://github.com/Mozilla-Actions/sccache-action/pull/225 is merged - # uses: mozilla-actions/sccache-action@v0.0.9 - uses: Vee99BR/sccache-action@v0.0.1 + uses: mozilla-actions/sccache-action@v0.0.9 - name: Set x64 vars if: matrix.os == 'windows-2025' From b2cd3331d9d56e0c5074c528796f128bec020a51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Dumas?= Date: Fri, 20 Feb 2026 11:47:36 -0800 Subject: [PATCH 34/66] Change LAGRANGE_RAYCASTING to LAGRANGE_MODULE_RAYCASTING --- .github/workflows/continuous.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 231895ef..050c5700 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -240,7 +240,7 @@ jobs: cmake -G Ninja ` -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` -DLAGRANGE_JENKINS=ON ` - -DLAGRANGE_RAYCASTING=ON ` + -DLAGRANGE_MODULE_RAYCASTING=ON ` -B ${{ env.BUILD_DIR }} ` -S . From d82459b04926c526f2c77354a83b4b0345603b4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Mon, 9 Mar 2026 10:14:46 -0700 Subject: [PATCH 35/66] Cleanup. --- cmake/lagrange/lagrange_find_package.cmake | 26 - cmake/recipes/external/embree4.cmake | 159 --- cmake/recipes/external/embree4.patch | 491 ------- modules/raycasting/CMakeLists.txt | 18 - .../lagrange/raycasting/EmbreeHelper.h | 22 - .../lagrange/raycasting/EmbreeRayCaster.h | 1153 ----------------- .../raycasting/embree_closest_point.h | 99 -- .../raycasting/src/legacy/EmbreeHelper.cpp | 7 - 8 files changed, 1975 deletions(-) delete mode 100644 cmake/recipes/external/embree4.cmake delete mode 100644 cmake/recipes/external/embree4.patch diff --git a/cmake/lagrange/lagrange_find_package.cmake b/cmake/lagrange/lagrange_find_package.cmake index b916b2ad..fc82db97 100644 --- a/cmake/lagrange/lagrange_find_package.cmake +++ b/cmake/lagrange/lagrange_find_package.cmake @@ -43,19 +43,6 @@ function(lagrange_find_package name) elseif(${name} STREQUAL algcmake) find_package(${name} ${ARGN}) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} PARENT_SCOPE) - elseif(${name} STREQUAL embree) - if(${ARGC} LESS 2) - message(FATAL_ERROR "lagrange_find_package(embree ...) requires at least 1 argument for the version number, ${ARGC} given") - endif() - if(${ARGV1} EQUAL 3) - # Defer to vcpkg port - find_package(${name} ${ARGN}) - elseif(${ARGV1} EQUAL 4) - # Use internal embree4.cmake recipe - include(embree4) - else() - message(FATAL_ERROR "Unsupported embree version number: ${ARGV1}") - endif() else() find_package(${name} ${ARGN}) endif() @@ -80,19 +67,6 @@ function(lagrange_find_package name) ${algcmake_SOURCE_DIR}/modules ) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} PARENT_SCOPE) - elseif(${name} STREQUAL embree) - if(${ARGC} LESS 2) - message(FATAL_ERROR "lagrange_find_package(embree ...) requires at least 1 argument for the version number, ${ARGC} given") - endif() - if(${ARGV1} EQUAL 3) - # Redirect to embree3.cmake - include(embree3) - elseif(${ARGV1} EQUAL 4) - # Redirect to embree4.cmake - include(embree4) - else() - message(FATAL_ERROR "Unsupported embree version number: ${ARGV1}") - endif() else() include(${name}) endif() diff --git a/cmake/recipes/external/embree4.cmake b/cmake/recipes/external/embree4.cmake deleted file mode 100644 index 5175b431..00000000 --- a/cmake/recipes/external/embree4.cmake +++ /dev/null @@ -1,159 +0,0 @@ -# -# Copyright 2019 Adobe. All rights reserved. -# This file is licensed to you under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. You may obtain a copy -# of the License at http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software distributed under -# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS -# OF ANY KIND, either express or implied. See the License for the specific language -# governing permissions and limitations under the License. -# -if(TARGET embree::embree4) - return() -endif() - -message(STATUS "Third-party (external): creating target 'embree::embree4'") - -# Set Embree's default options -option(EMBREE_ISPC_SUPPORT "Build Embree with support for ISPC applications." OFF) -option(EMBREE_TUTORIALS "Enable to build Embree tutorials" OFF) -option(EMBREE_STATIC_LIB "Build Embree as a static library." ON) -set(EMBREE_TESTING_INTENSITY 0 CACHE STRING "Intensity of testing (0 = no testing, 1 = verify and tutorials, 2 = light testing, 3 = intensive testing.") -set(EMBREE_TASKING_SYSTEM "TBB" CACHE STRING "Selects tasking system") -option(EMBREE_IGNORE_CMAKE_CXX_FLAGS "When enabled Embree ignores default CMAKE_CXX_FLAGS." OFF) - -# Set C++ namespace to avoid symbol collisions when compiling with embree3 side-by-side -set(EMBREE_API_NAMESPACE "embree4" CACHE STRING "C++ namespace to put API symbols into.") - -# The following options are necessary to ensure packed-ray support -option(EMBREE_RAY_MASK "Enable the usage of mask for packed ray." ON) -option(EMBREE_RAY_PACKETS "Enable the usage packed ray." ON) - -if(APPLE) - set(EMBREE_MAX_ISA "NEON" CACHE STRING "Selects highest ISA to support.") -elseif(EMSCRIPTEN) - set(EMBREE_MAX_ISA "SSE2" CACHE STRING "Selects highest ISA to support.") - set(FLAGS_SSE2 "-msse -msse2 -msimd128") # set to non-empty to prevent embree from using incorrect flags -else() - set(EMBREE_MAX_ISA "DEFAULT" CACHE STRING "Selects highest ISA to support.") -endif() - -# We want to compile Embree with TBB support, so we need to overwrite Embree's -# `find_package()` and provide variables. The following discussion provide some -# context on how to achieve this: -# - https://gitlab.kitware.com/cmake/cmake/issues/17735 -# - https://crascit.com/2018/09/14/do-not-redefine-cmake-commands/ -function(embree4_import_target) - macro(push_variable var value) - if(DEFINED CACHE{${var}}) - set(LAGRANGE_OLD_${var}_VALUE "${${var}}") - set(LAGRANGE_OLD_${var}_TYPE CACHE_TYPE) - elseif(DEFINED ${var}) - set(LAGRANGE_OLD_${var}_VALUE "${${var}}") - set(LAGRANGE_OLD_${var}_TYPE NORMAL_TYPE) - else() - set(LAGRANGE_OLD_${var}_TYPE NONE_TYPE) - endif() - set(${var} "${value}") - endmacro() - - macro(pop_variable var) - if(LAGRANGE_OLD_${var}_TYPE STREQUAL CACHE_TYPE) - set(${var} "${LAGRANGE_OLD_${var}_VALUE}" CACHE PATH "" FORCE) - elseif(LAGRANGE_OLD_${var}_TYPE STREQUAL NORMAL_TYPE) - unset(${var} CACHE) - set(${var} "${LAGRANGE_OLD_${var}_VALUE}") - elseif(LAGRANGE_OLD_${var}_TYPE STREQUAL NONE_TYPE) - unset(${var} CACHE) - else() - message(FATAL_ERROR "Trying to pop a variable that has not been pushed: ${var}") - endif() - endmacro() - - macro(ignore_package NAME) - set(LAGRANGE_DUMMY_DIR "${CMAKE_CURRENT_BINARY_DIR}/embree_cmake/${NAME}") - file(WRITE ${LAGRANGE_DUMMY_DIR}/${NAME}Config.cmake "") - push_variable(${NAME}_DIR ${LAGRANGE_DUMMY_DIR}) - push_variable(${NAME}_ROOT ${LAGRANGE_DUMMY_DIR}) - endmacro() - - macro(unignore_package NAME) - pop_variable(${NAME}_DIR) - pop_variable(${NAME}_ROOT) - endmacro() - - # Prefer Config mode before Module mode to prevent embree from loading its own FindTBB.cmake - set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) - - # Embree wants to be able to export() its target, and expects a target named `TBB` to exist. - # Somehow we stil need to define `TBB_INCLUDE_DIRS`, and linking against `TBB` isn't sufficient - # to compile embree targets properly. - lagrange_find_package(TBB CONFIG REQUIRED) - ignore_package(TBB) - get_target_property(TBB_INCLUDE_DIRS TBB::tbb INTERFACE_INCLUDE_DIRECTORIES) - if(NOT TARGET TBB) - add_library(TBB INTERFACE) - target_link_libraries(TBB INTERFACE TBB::tbb) - endif() - set(TBB_LIBRARIES TBB) - - # Ready to include embree's atrocious CMake - include(CPM) - CPMAddPackage( - NAME embree4 - GITHUB_REPOSITORY RenderKit/embree - GIT_TAG v4.4.0 - - PATCHES - # Maybe one day we'll have https://gitlab.kitware.com/cmake/cmake/-/issues/22687 - # Until then, if we want to compile both Embree3 and Embree4 side by side, we need patching. - embree4.patch - ) - - unignore_package(TBB) - - # Disable warnings - if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - # Embree's subgrid.h is known for causing array subscript out of bound - # warning. Embree dev claim the code is correct and it is a GCC bug - # for misfiring warnings. See https://github.com/embree/embree/issues/271 - # - # The issue should be fixed for gcc 9.2.1 and later. - target_compile_options(embree4_embree PRIVATE "-Wno-array-bounds") - endif() - - # Warning setting - set(unix_compilers "AppleClang;Clang;GNU") - if(CMAKE_CXX_COMPILER_ID IN_LIST unix_compilers) # IN_LIST wants the second arg to be a var - target_compile_options(embree4_embree PRIVATE "-Wno-unused-private-field") - target_compile_options(embree4_embree PRIVATE "-Wno-unused-but-set-variable") - endif() - - # Now we need to do some juggling to propagate the include directory properties - # along with the `embree` target - add_library(embree::embree4 INTERFACE IMPORTED GLOBAL) - target_include_directories(embree::embree4 SYSTEM INTERFACE ${embree4_SOURCE_DIR}/include) - target_link_libraries(embree::embree4 INTERFACE embree4_embree) - - # Generate a dummy .cpp for embree's math library, to workaround a weird link issue with - # LLVM-Clang on macOS - # Generate implementation file - file(WRITE "${embree4_BINARY_DIR}/embree_math_dummy.cpp.in" [[ - namespace embree { - void math_dummy() {} - } - ]]) - configure_file(${embree4_BINARY_DIR}/embree_math_dummy.cpp.in ${embree4_BINARY_DIR}/embree_math_dummy.cpp COPYONLY) - target_sources(embree4_math PRIVATE ${embree4_BINARY_DIR}/embree_math_dummy.cpp) -endfunction() - -# Call via a proper function in order to scope variables such as CMAKE_FIND_PACKAGE_PREFER_CONFIG and TBB_DIR -embree4_import_target() - -# Cleanup for IDEs -foreach(name IN ITEMS embree algorithms lexers math simd sys tasking uninstall) - if(TARGET ${name}) - set_target_properties(embree4_${name} PROPERTIES FOLDER "third_party//embree4") - endif() -endforeach() diff --git a/cmake/recipes/external/embree4.patch b/cmake/recipes/external/embree4.patch deleted file mode 100644 index b2e14a91..00000000 --- a/cmake/recipes/external/embree4.patch +++ /dev/null @@ -1,491 +0,0 @@ -diff --git i/CMakeLists.txt w/CMakeLists.txt -index 1292e265..f386ecb5 100644 ---- i/CMakeLists.txt -+++ w/CMakeLists.txt -@@ -691,16 +691,16 @@ ENDIF() - # Uninstall - ############################################################## - --IF (NOT TARGET uninstall) -+IF (NOT TARGET embree4_uninstall) - configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/common/cmake/uninstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake" - IMMEDIATE @ONLY) - -- add_custom_target(uninstall -+ add_custom_target(embree4_uninstall - COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake") - -- SET_PROPERTY(TARGET uninstall PROPERTY FOLDER CMakePredefinedTargets) -+ SET_PROPERTY(TARGET embree4_uninstall PROPERTY FOLDER CMakePredefinedTargets) - ENDIF() - - ############################################################## -diff --git i/common/lexers/CMakeLists.txt w/common/lexers/CMakeLists.txt -index 1e2452cd..5d060c7a 100644 ---- i/common/lexers/CMakeLists.txt -+++ w/common/lexers/CMakeLists.txt -@@ -1,16 +1,16 @@ - ## Copyright 2009-2021 Intel Corporation - ## SPDX-License-Identifier: Apache-2.0 - --ADD_LIBRARY(lexers STATIC -+ADD_LIBRARY(embree4_lexers STATIC - stringstream.cpp - tokenstream.cpp - ) --TARGET_LINK_LIBRARIES(lexers sys math) --SET_PROPERTY(TARGET lexers PROPERTY FOLDER common) --SET_PROPERTY(TARGET lexers APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") -+TARGET_LINK_LIBRARIES(embree4_lexers embree4_sys embree4_math) -+SET_PROPERTY(TARGET embree4_lexers PROPERTY FOLDER common) -+SET_PROPERTY(TARGET embree4_lexers APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") - - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS lexers EXPORT lexers-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_lexers EXPORT lexers-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT lexers-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() - -diff --git i/common/math/CMakeLists.txt w/common/math/CMakeLists.txt -index fcfa4559..6cfed20e 100644 ---- i/common/math/CMakeLists.txt -+++ w/common/math/CMakeLists.txt -@@ -1,12 +1,12 @@ - ## Copyright 2009-2021 Intel Corporation - ## SPDX-License-Identifier: Apache-2.0 - --ADD_LIBRARY(math STATIC constants.cpp) --SET_PROPERTY(TARGET math PROPERTY FOLDER common) --SET_PROPERTY(TARGET math APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") -+ADD_LIBRARY(embree4_math STATIC constants.cpp) -+SET_PROPERTY(TARGET embree4_math PROPERTY FOLDER common) -+SET_PROPERTY(TARGET embree4_math APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") - - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS math EXPORT math-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_math EXPORT math-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT math-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() - -diff --git i/common/simd/CMakeLists.txt w/common/simd/CMakeLists.txt -index 989a00d6..742b885d 100644 ---- i/common/simd/CMakeLists.txt -+++ w/common/simd/CMakeLists.txt -@@ -1,11 +1,11 @@ - ## Copyright 2009-2021 Intel Corporation - ## SPDX-License-Identifier: Apache-2.0 - --ADD_LIBRARY(simd STATIC sse.cpp) --SET_PROPERTY(TARGET simd PROPERTY FOLDER common) --SET_PROPERTY(TARGET simd APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") -+ADD_LIBRARY(embree4_simd STATIC sse.cpp) -+SET_PROPERTY(TARGET embree4_simd PROPERTY FOLDER common) -+SET_PROPERTY(TARGET embree4_simd APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") - - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS simd EXPORT simd-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_simd EXPORT simd-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT simd-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() -diff --git i/common/sys/CMakeLists.txt w/common/sys/CMakeLists.txt -index 66fc7083..d0e16cde 100644 ---- i/common/sys/CMakeLists.txt -+++ w/common/sys/CMakeLists.txt -@@ -4,7 +4,7 @@ - SET(CMAKE_THREAD_PREFER_PTHREAD TRUE) - FIND_PACKAGE(Threads REQUIRED) - --ADD_LIBRARY(sys STATIC -+ADD_LIBRARY(embree4_sys STATIC - sysinfo.cpp - alloc.cpp - filename.cpp -@@ -17,16 +17,16 @@ ADD_LIBRARY(sys STATIC - barrier.cpp - ) - --SET_PROPERTY(TARGET sys PROPERTY FOLDER common) --SET_PROPERTY(TARGET sys APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") -+SET_PROPERTY(TARGET embree4_sys PROPERTY FOLDER common) -+SET_PROPERTY(TARGET embree4_sys APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") - --TARGET_LINK_LIBRARIES(sys ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) -+TARGET_LINK_LIBRARIES(embree4_sys ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) - IF (EMBREE_SYCL_SUPPORT) -- TARGET_LINK_LIBRARIES(sys ${SYCL_LIB_NAME}) -+ TARGET_LINK_LIBRARIES(embree4_sys ${SYCL_LIB_NAME}) - ENDIF() - - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS sys EXPORT sys-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_sys EXPORT sys-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT sys-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() - -diff --git i/common/tasking/CMakeLists.txt w/common/tasking/CMakeLists.txt -index bf790ef6..e2768e98 100644 ---- i/common/tasking/CMakeLists.txt -+++ w/common/tasking/CMakeLists.txt -@@ -2,7 +2,7 @@ - ## SPDX-License-Identifier: Apache-2.0 - - IF (TASKING_INTERNAL) -- ADD_LIBRARY(tasking STATIC taskschedulerinternal.cpp) -+ ADD_LIBRARY(embree4_tasking STATIC taskschedulerinternal.cpp) - ELSEIF (TASKING_TBB) - ############################################################## - # Find TBB -@@ -13,16 +13,16 @@ ELSEIF (TASKING_TBB) - list(APPEND CMAKE_PREFIX_PATH ${EMBREE_TBB_ROOT}) - endif() - -- ADD_LIBRARY(tasking STATIC taskschedulertbb.cpp) -+ ADD_LIBRARY(embree4_tasking STATIC taskschedulertbb.cpp) - - if (TARGET TBB::${EMBREE_TBB_COMPONENT}) - message("-- TBB: reuse existing TBB::${TBB_COMPONENT} target") -- TARGET_LINK_LIBRARIES(tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) -+ TARGET_LINK_LIBRARIES(embree4_tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) - else() - # Try getting TBB via config first - find_package(TBB 2020 COMPONENTS ${EMBREE_TBB_COMPONENT} CONFIG ${TBB_FIND_PACKAGE_OPTION}) - if (TBB_FOUND) -- TARGET_LINK_LIBRARIES(tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) -+ TARGET_LINK_LIBRARIES(embree4_tasking PUBLIC TBB::${EMBREE_TBB_COMPONENT}) - message("-- Found TBB: ${TBB_VERSION} at ${TBB_DIR} via TBBConfig.cmake") - else() - -@@ -32,8 +32,8 @@ ELSEIF (TASKING_TBB) - unset(TBB_DIR CACHE) - find_package(TBB 4.1 REQUIRED ${EMBREE_TBB_COMPONENT}) - if (TBB_FOUND) -- TARGET_LINK_LIBRARIES(tasking PUBLIC TBB) -- TARGET_INCLUDE_DIRECTORIES(tasking PUBLIC $) -+ TARGET_LINK_LIBRARIES(embree4_tasking PUBLIC TBB) -+ TARGET_INCLUDE_DIRECTORIES(embree4_tasking PUBLIC $) - - IF (EMBREE_STATIC_LIB) - INSTALL(TARGETS TBB EXPORT TBB-targets) -@@ -50,8 +50,8 @@ ELSEIF (TASKING_TBB) - IF(WIN32) - GET_TARGET_PROPERTY(DLL_PATH TBB::${EMBREE_TBB_COMPONENT} IMPORTED_LOCATION_RELEASE) - GET_TARGET_PROPERTY(DLL_PATH_DEBUG TBB::${EMBREE_TBB_COMPONENT} IMPORTED_LOCATION_DEBUG) -- SET_TARGET_PROPERTIES(tasking PROPERTIES IMPORTED_LOCATION_RELEASE ${DLL_PATH}) -- SET_TARGET_PROPERTIES(tasking PROPERTIES IMPORTED_LOCATION_DEBUG ${DLL_PATH_DEBUG}) -+ SET_TARGET_PROPERTIES(embree4_tasking PROPERTIES IMPORTED_LOCATION_RELEASE ${DLL_PATH}) -+ SET_TARGET_PROPERTIES(embree4_tasking PROPERTIES IMPORTED_LOCATION_DEBUG ${DLL_PATH_DEBUG}) - ENDIF() - - ############################################################### -@@ -65,14 +65,14 @@ ELSEIF (TASKING_TBB) - include(installTBB) - - ELSEIF (TASKING_PPL) -- ADD_LIBRARY(tasking STATIC taskschedulerppl.cpp) -- TARGET_LINK_LIBRARIES(tasking PUBLIC ${PPL_LIBRARIES}) -+ ADD_LIBRARY(embree4_tasking STATIC taskschedulerppl.cpp) -+ TARGET_LINK_LIBRARIES(embree4_tasking PUBLIC ${PPL_LIBRARIES}) - ENDIF() - --SET_PROPERTY(TARGET tasking PROPERTY FOLDER common) --SET_PROPERTY(TARGET tasking APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") -+SET_PROPERTY(TARGET embree4_tasking PROPERTY FOLDER common) -+SET_PROPERTY(TARGET embree4_tasking APPEND PROPERTY COMPILE_FLAGS " ${FLAGS_LOWEST}") - - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS tasking EXPORT tasking-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_tasking EXPORT tasking-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT tasking-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() -diff --git i/kernels/CMakeLists.txt w/kernels/CMakeLists.txt -index b8278079..33e8a3c6 100644 ---- i/kernels/CMakeLists.txt -+++ w/kernels/CMakeLists.txt -@@ -31,7 +31,7 @@ SOURCE_GROUP("Source Files\\algorithms" "/algorithms/") - SOURCE_GROUP("" FILES embree.rc) - - SET(EMBREE_LIBRARY_FILES -- -+ - embree.rc - - common/device.cpp -@@ -105,7 +105,7 @@ IF (EMBREE_GEOMETRY_SUBDIVISION) - subdiv/tessellation_cache.cpp - subdiv/subdivpatch1base.cpp - subdiv/catmullclark_coefficients.cpp -- geometry/grid_soa.cpp -+ geometry/grid_soa.cpp - subdiv/subdivpatch1base_eval.cpp - bvh/bvh_builder_subdiv.cpp) - ENDIF() -@@ -116,7 +116,7 @@ IF (EMBREE_RAY_PACKETS) - ENDIF() - - MACRO(embree_files TARGET ISA) -- -+ - SET(${TARGET} - geometry/instance_intersector.cpp - geometry/instance_array_intersector.cpp -@@ -130,16 +130,16 @@ MACRO(embree_files TARGET ISA) - - IF (${ISA} EQUAL ${ISA_LOWEST_AVX}) - LIST(APPEND ${TARGET} geometry/primitive8.cpp) -- ENDIF() -+ ENDIF() - - IF (${ISA} EQUAL ${SSE2} OR ${ISA} EQUAL ${AVX} OR ${ISA} EQUAL ${AVX2} OR ${ISA} EQUAL ${AVX512} OR ${ISA_LOWEST} EQUAL ${ISA}) -- -+ - LIST(APPEND ${TARGET} - common/scene_user_geometry.cpp - common/scene_instance.cpp - common/scene_instance_array.cpp - common/scene_triangle_mesh.cpp -- common/scene_quad_mesh.cpp -+ common/scene_quad_mesh.cpp - common/scene_curves.cpp - common/scene_line_segments.cpp - common/scene_grid_mesh.cpp -@@ -166,7 +166,7 @@ MACRO(embree_files TARGET ISA) - bvh/bvh_rotate.cpp - builders/primrefgen.cpp) - ENDIF() -- -+ - IF (${ISA} GREATER ${SSE42}) - LIST(APPEND ${TARGET} bvh/bvh_intersector1_bvh8.cpp) - ENDIF() -@@ -183,7 +183,7 @@ MACRO(embree_files TARGET ISA) - geometry/grid_soa.cpp - subdiv/subdivpatch1base_eval.cpp) - ENDIF() -- -+ - IF (EMBREE_RAY_PACKETS) - LIST(APPEND ${TARGET} - bvh/bvh_intersector_hybrid4_bvh4.cpp) -@@ -201,7 +201,7 @@ MACRO(embree_files TARGET ISA) - bvh/bvh_intersector_hybrid16_bvh4.cpp) - ENDIF() - ENDIF() -- -+ - ENDMACRO() - - #embree_files(EMBREE_LIBRARY_FILES_SSE2 ${SSE2}) -@@ -225,7 +225,7 @@ MACRO (CreateISADummyFiles list isa) - SET(dst_file "${CMAKE_BINARY_DIR}/${src}.${isa}.cpp") - SET(${list} ${${list}} ${dst_file}) - ADD_CUSTOM_COMMAND(OUTPUT ${dst_file} -- COMMAND ${CMAKE_COMMAND} -+ COMMAND ${CMAKE_COMMAND} - -D src=${src_file} - -D dst=${dst_file} - -P "${PROJECT_SOURCE_DIR}/common/cmake/create_isa_dummy_file.cmake" -@@ -243,40 +243,40 @@ MACRO (CheckGlobals library) - ADD_CUSTOM_TARGET(${library}_check_globals ALL COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_globals.cmake" DEPENDS ${library}) - ENDIF() - ENDMACRO() -- -+ - DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES}) --ADD_LIBRARY(embree ${EMBREE_LIB_TYPE} ${EMBREE_LIBRARY_FILES}) -+ADD_LIBRARY(embree4_embree ${EMBREE_LIB_TYPE} ${EMBREE_LIBRARY_FILES}) - - IF (EMBREE_SYCL_SUPPORT) - # add link flag '-fsycl' here to include the kernel for USM prefetch from - # scene_sycl.cpp in embree4.dll/embree4.so -- TARGET_LINK_OPTIONS(embree PRIVATE "-fsycl") -+ TARGET_LINK_OPTIONS(embree4_embree PRIVATE "-fsycl") - -- ADD_LIBRARY(embree_sycl STATIC -+ ADD_LIBRARY(embree4_embree_sycl STATIC - sycl/rtcore_sycl.cpp - sycl/rthwif_embree.cpp) - -- SET_TARGET_PROPERTIES(embree_sycl PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS_SYCL}) -+ SET_TARGET_PROPERTIES(embree4_embree_sycl PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS_SYCL}) - IF (EMBREE_SYCL_RT_VALIDATION_API) -- TARGET_LINK_LIBRARIES(embree_sycl PRIVATE embree_rthwif_sycl) -+ TARGET_LINK_LIBRARIES(embree4_embree_sycl PRIVATE embree_rthwif_sycl) - ENDIF() - - IF (EMBREE_SYCL_RT_SIMULATION) -- TARGET_LINK_LIBRARIES(embree_sycl PRIVATE rtcore) -+ TARGET_LINK_LIBRARIES(embree4_embree_sycl PRIVATE rtcore) - ENDIF() - -- INSTALL(TARGETS embree_sycl EXPORT embree_sycl-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) -+ INSTALL(TARGETS embree4_embree_sycl EXPORT embree_sycl-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel) - INSTALL(EXPORT embree_sycl-targets DESTINATION ${EMBREE_CMAKEEXPORT_DIR} COMPONENT devel) - -- SET_TARGET_PROPERTIES(embree_sycl PROPERTIES OUTPUT_NAME embree${EMBREE_VERSION_MAJOR}_sycl) -+ SET_TARGET_PROPERTIES(embree4_embree_sycl PROPERTIES OUTPUT_NAME embree${EMBREE_VERSION_MAJOR}_sycl) - - ENDIF() - --SET_TARGET_PROPERTIES(embree PROPERTIES COMPILE_FLAGS "${FLAGS_LOWEST}") --SET_TARGET_PROPERTIES(embree PROPERTIES COMPILE_DEFINITIONS "EMBREE_LOWEST_ISA") --SET_PROPERTY(TARGET embree PROPERTY FOLDER kernels) -+SET_TARGET_PROPERTIES(embree4_embree PROPERTIES COMPILE_FLAGS "${FLAGS_LOWEST}") -+SET_TARGET_PROPERTIES(embree4_embree PROPERTIES COMPILE_DEFINITIONS "EMBREE_LOWEST_ISA") -+SET_PROPERTY(TARGET embree4_embree PROPERTY FOLDER kernels) - IF (NOT WIN32 AND NOT APPLE) -- ADD_CUSTOM_TARGET(embree_check_stack_frame_size COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_stack_frame_size.cmake" DEPENDS embree) -+ ADD_CUSTOM_TARGET(embree_check_stack_frame_size COMMAND ${CMAKE_COMMAND} -D file=$ -P "${PROJECT_SOURCE_DIR}/common/cmake/check_stack_frame_size.cmake" DEPENDS embree4_embree) - ENDIF() - - #IF (EMBREE_ISA_SSE2 AND EMBREE_LIBRARY_FILES_SSE2) -@@ -292,68 +292,68 @@ ENDIF() - - IF (EMBREE_ISA_SSE42 AND EMBREE_LIBRARY_FILES_SSE42) - DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_SSE42}) -- ADD_LIBRARY(embree_sse42 STATIC ${EMBREE_LIBRARY_FILES_SSE42}) -- TARGET_LINK_LIBRARIES(embree_sse42 PRIVATE tasking) -- SET_TARGET_PROPERTIES(embree_sse42 PROPERTIES COMPILE_FLAGS "${FLAGS_SSE42}") -- SET_PROPERTY(TARGET embree_sse42 PROPERTY FOLDER kernels) -- SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_sse42) -- CheckGlobals(embree_sse42) -+ ADD_LIBRARY(embree4_embree_sse42 STATIC ${EMBREE_LIBRARY_FILES_SSE42}) -+ TARGET_LINK_LIBRARIES(embree4_embree_sse42 PRIVATE tasking) -+ SET_TARGET_PROPERTIES(embree4_embree_sse42 PROPERTIES COMPILE_FLAGS "${FLAGS_SSE42}") -+ SET_PROPERTY(TARGET embree4_embree_sse42 PROPERTY FOLDER kernels) -+ SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree4_embree_sse42) -+ CheckGlobals(embree4_embree_sse42) - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS embree_sse42 EXPORT embree_sse42-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_embree_sse42 EXPORT embree_sse42-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT embree_sse42-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() - ENDIF () - - IF (EMBREE_ISA_AVX AND EMBREE_LIBRARY_FILES_AVX) - DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX}) -- ADD_LIBRARY(embree_avx STATIC ${EMBREE_LIBRARY_FILES_AVX}) -- TARGET_LINK_LIBRARIES(embree_avx PRIVATE tasking) -- SET_TARGET_PROPERTIES(embree_avx PROPERTIES COMPILE_FLAGS "${FLAGS_AVX}") -- SET_PROPERTY(TARGET embree_avx PROPERTY FOLDER kernels) -- SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_avx) -- CheckGlobals(embree_avx) -+ ADD_LIBRARY(embree4_embree_avx STATIC ${EMBREE_LIBRARY_FILES_AVX}) -+ TARGET_LINK_LIBRARIES(embree4_embree_avx PRIVATE tasking) -+ SET_TARGET_PROPERTIES(embree4_embree_avx PROPERTIES COMPILE_FLAGS "${FLAGS_AVX}") -+ SET_PROPERTY(TARGET embree4_embree_avx PROPERTY FOLDER kernels) -+ SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree4_embree_avx) -+ CheckGlobals(embree4_embree_avx) - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS embree_avx EXPORT embree_avx-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_embree_avx EXPORT embree_avx-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT embree_avx-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() - ENDIF() - - IF (EMBREE_ISA_AVX2 AND EMBREE_LIBRARY_FILES_AVX2) - DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX2}) -- ADD_LIBRARY(embree_avx2 STATIC ${EMBREE_LIBRARY_FILES_AVX2}) -- TARGET_LINK_LIBRARIES(embree_avx2 PRIVATE tasking) -- SET_TARGET_PROPERTIES(embree_avx2 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX2}") -- SET_PROPERTY(TARGET embree_avx2 PROPERTY FOLDER kernels) -- SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_avx2) -- CheckGlobals(embree_avx2) -+ ADD_LIBRARY(embree4_embree_avx2 STATIC ${EMBREE_LIBRARY_FILES_AVX2}) -+ TARGET_LINK_LIBRARIES(embree4_embree_avx2 PRIVATE tasking) -+ SET_TARGET_PROPERTIES(embree4_embree_avx2 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX2}") -+ SET_PROPERTY(TARGET embree4_embree_avx2 PROPERTY FOLDER kernels) -+ SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree4_embree_avx2) -+ CheckGlobals(embree4_embree_avx2) - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS embree_avx2 EXPORT embree_avx2-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_embree_avx2 EXPORT embree_avx2-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT embree_avx2-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() - ENDIF() - - IF (EMBREE_ISA_AVX512 AND EMBREE_LIBRARY_FILES_AVX512) - DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX512}) -- ADD_LIBRARY(embree_avx512 STATIC ${EMBREE_LIBRARY_FILES_AVX512}) -- TARGET_LINK_LIBRARIES(embree_avx512 PRIVATE tasking) -- SET_TARGET_PROPERTIES(embree_avx512 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX512}") -- SET_PROPERTY(TARGET embree_avx512 PROPERTY FOLDER kernels) -- SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree_avx512) -- CheckGlobals(embree_avx512) -+ ADD_LIBRARY(embree4_embree_avx512 STATIC ${EMBREE_LIBRARY_FILES_AVX512}) -+ TARGET_LINK_LIBRARIES(embree4_embree_avx512 PRIVATE tasking) -+ SET_TARGET_PROPERTIES(embree4_embree_avx512 PROPERTIES COMPILE_FLAGS "${FLAGS_AVX512}") -+ SET_PROPERTY(TARGET embree4_embree_avx512 PROPERTY FOLDER kernels) -+ SET(EMBREE_LIBRARIES ${EMBREE_LIBRARIES} embree4_embree_avx512) -+ CheckGlobals(embree4_embree_avx512) - IF (EMBREE_STATIC_LIB) -- INSTALL(TARGETS embree_avx512 EXPORT embree_avx512-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) -+ INSTALL(TARGETS embree4_embree_avx512 EXPORT embree_avx512-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel) - INSTALL(EXPORT embree_avx512-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel) - ENDIF() - ENDIF() - --TARGET_LINK_LIBRARIES(embree PRIVATE ${EMBREE_LIBRARIES} sys math simd lexers tasking) -+TARGET_LINK_LIBRARIES(embree4_embree PRIVATE ${EMBREE_LIBRARIES} embree4_sys embree4_math embree4_simd embree4_lexers embree4_tasking) - IF (EMBREE_SYCL_SUPPORT) -- TARGET_LINK_LIBRARIES(embree PRIVATE ${SYCL_LIB_NAME} ze_wrapper PUBLIC embree_sycl) -+ TARGET_LINK_LIBRARIES(embree4_embree PRIVATE ${SYCL_LIB_NAME} ze_wrapper PUBLIC embree4_embree_sycl) - ENDIF() - - #TARGET_LINK_LIBRARIES(embree PRIVATE ${EMBREE_LIBRARIES} sys math simd lexers tasking ${CMAKE_LINK_FLAGS_SYCL}) # FIXME: enable this line --SET_TARGET_PROPERTIES(embree PROPERTIES OUTPUT_NAME ${EMBREE_LIBRARY_NAME}) --target_include_directories(embree PUBLIC -+SET_TARGET_PROPERTIES(embree4_embree PROPERTIES OUTPUT_NAME ${EMBREE_LIBRARY_NAME}) -+target_include_directories(embree4_embree PUBLIC - $ - $) - -@@ -361,27 +361,27 @@ target_include_directories(embree PUBLIC - # libtbb is located in same install folder as libembree - IF(WIN32) - ELSEIF(APPLE) -- SET_TARGET_PROPERTIES(embree PROPERTIES INSTALL_RPATH "@loader_path") # On MacOSX we tell dyld to find libtbb in the folder libembree is placed -+ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES INSTALL_RPATH "@loader_path") # On MacOSX we tell dyld to find libtbb in the folder libembree is placed - ELSE() -- SET_TARGET_PROPERTIES(embree PROPERTIES INSTALL_RPATH "$ORIGIN") # Linux we tell ld to find libtbb in the folder libembree is placed. -+ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES INSTALL_RPATH "$ORIGIN") # Linux we tell ld to find libtbb in the folder libembree is placed. - ENDIF() - - IF (WIN32) - ELSEIF (APPLE) -- SET_TARGET_PROPERTIES(embree PROPERTIES LINK_FLAGS -Wl,-exported_symbols_list,"${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") -- SET_SOURCE_FILES_PROPERTIES(common/rtcore.cpp PROPERTIES OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") -+ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES LINK_FLAGS -Wl,-exported_symbols_list,"${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") -+ SET_SOURCE_FILES_PROPERTIES(common/rtcore.cpp PROPERTIES OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/kernels/export.macosx.map") - ELSE() -- SET_TARGET_PROPERTIES(embree PROPERTIES LINK_FLAGS -Wl,--version-script="${PROJECT_SOURCE_DIR}/kernels/export.linux.map") -+ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES LINK_FLAGS -Wl,--version-script="${PROJECT_SOURCE_DIR}/kernels/export.linux.map") - SET_SOURCE_FILES_PROPERTIES(common/rtcore.cpp PROPERTIES OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/kernels/export.linux.map") - ENDIF() - - IF (EMBREE_ZIP_MODE) -- SET_TARGET_PROPERTIES(embree PROPERTIES VERSION ${EMBREE_VERSION_MAJOR} SOVERSION ${EMBREE_VERSION_MAJOR}) -+ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES VERSION ${EMBREE_VERSION_MAJOR} SOVERSION ${EMBREE_VERSION_MAJOR}) - ELSE() -- SET_TARGET_PROPERTIES(embree PROPERTIES VERSION ${EMBREE_VERSION} SOVERSION ${EMBREE_VERSION_MAJOR}) -+ SET_TARGET_PROPERTIES(embree4_embree PROPERTIES VERSION ${EMBREE_VERSION} SOVERSION ${EMBREE_VERSION_MAJOR}) - ENDIF() - --INSTALL(TARGETS embree EXPORT embree-targets -+INSTALL(TARGETS embree4_embree EXPORT embree-targets - LIBRARY NAMELINK_SKIP DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib - # on Windows put the dlls into bin - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT examples -@@ -394,9 +394,9 @@ INSTALL(EXPORT embree-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT - - # installs libembree4.so link - IF (NOT EMBREE_STATIC_LIB) -- INSTALL(TARGETS embree -+ INSTALL(TARGETS embree4_embree - LIBRARY NAMELINK_ONLY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel - ) - ENDIF() - --SIGN_TARGET(embree) -+SIGN_TARGET(embree4_embree) diff --git a/modules/raycasting/CMakeLists.txt b/modules/raycasting/CMakeLists.txt index 29a3d836..7659f647 100644 --- a/modules/raycasting/CMakeLists.txt +++ b/modules/raycasting/CMakeLists.txt @@ -13,23 +13,6 @@ lagrange_add_module() # 2. dependencies -<<<<<<< HEAD -lagrange_include_modules(bvh) -target_link_libraries(lagrange_raycasting PUBLIC - lagrange::core - lagrange::bvh -) - -option(LAGRANGE_WITH_EMBREE_4 "Use Embree4 with Lagrange" ON) -if(LAGRANGE_WITH_EMBREE_4) - lagrange_find_package(embree 4 CONFIG REQUIRED) - target_compile_definitions(lagrange_raycasting PUBLIC LAGRANGE_WITH_EMBREE_4) - target_link_libraries(lagrange_raycasting PUBLIC embree::embree4) -else() - lagrange_find_package(embree 3 CONFIG REQUIRED) - target_link_libraries(lagrange_raycasting PUBLIC embree::embree) -endif() -======= lagrange_include_modules(bvh scene) target_link_libraries(lagrange_raycasting PUBLIC lagrange::core @@ -44,7 +27,6 @@ else() lagrange_find_package(embree 4 CONFIG REQUIRED) endif() target_link_libraries(lagrange_raycasting PUBLIC embree::embree) ->>>>>>> origin/main option(LAGRANGE_EMBREE_DEBUG "Perform error-checking when performing each single Embree call" OFF) if(LAGRANGE_EMBREE_DEBUG) diff --git a/modules/raycasting/include/lagrange/raycasting/EmbreeHelper.h b/modules/raycasting/include/lagrange/raycasting/EmbreeHelper.h index 91f2edf6..fe405adf 100644 --- a/modules/raycasting/include/lagrange/raycasting/EmbreeHelper.h +++ b/modules/raycasting/include/lagrange/raycasting/EmbreeHelper.h @@ -11,28 +11,6 @@ */ #pragma once -<<<<<<< HEAD -#ifdef LAGRANGE_WITH_EMBREE_4 - #include -#else - #include -#endif -#include - -RTC_NAMESPACE_USE - -namespace lagrange { -namespace raycasting { -namespace EmbreeHelper { - -LA_RAYCASTING_API -void ensure_no_errors(const RTCDevice& device); - -} // namespace EmbreeHelper -} // namespace raycasting -} // namespace lagrange -======= #ifdef LAGRANGE_ENABLE_LEGACY_FUNCTIONS #include #endif ->>>>>>> origin/main diff --git a/modules/raycasting/include/lagrange/raycasting/EmbreeRayCaster.h b/modules/raycasting/include/lagrange/raycasting/EmbreeRayCaster.h index 8ebd0909..350a4e20 100644 --- a/modules/raycasting/include/lagrange/raycasting/EmbreeRayCaster.h +++ b/modules/raycasting/include/lagrange/raycasting/EmbreeRayCaster.h @@ -11,1159 +11,6 @@ */ #pragma once -<<<<<<< HEAD -#ifdef LAGRANGE_WITH_EMBREE_4 - #include - #include - #include -#else - #include - #include - #include -#endif - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -RTC_NAMESPACE_USE - -namespace lagrange { -namespace raycasting { - -/** - * A wrapper for Embree's raycasting API to compute ray intersections with (instances of) meshes. - * Supports intersection and occlusion queries on single rays and ray packets (currently only - * packets of size at most 4 are supported). Filters may be specified (per mesh, not per instance) - * to process each individual hit event during any of these queries. - */ -template -class EmbreeRayCaster -{ -public: - using Scalar = ScalarType; - using Transform = Eigen::Matrix; - using Point = Eigen::Matrix; - using Direction = Eigen::Matrix; - using Index = size_t; - using ClosestPoint = ClosestPointResult; - using TransformVector = std::vector; - - using Point4 = Eigen::Matrix; - using Direction4 = Eigen::Matrix; - using Index4 = Eigen::Matrix; - using Scalar4 = Eigen::Matrix; - using Mask4 = Eigen::Matrix; - - using FloatData = std::vector; - using IntData = std::vector; - - /** - * Interface for a hit filter function. Most information in `RTCFilterFunctionNArguments` maps - * directly to elements of the EmbreeRayCaster class, but the mesh and instance IDs need special - * conversion. `mesh_index` is an array of `args->N` EmbreeRayCaster mesh indices, and - * `instance_index` is an array of `args->N` EmbreeRayCaster instance indices, one for each - * ray/hit. For the other elements of `args`, the mappings are: - * - * @code - * facet_index <-- primID - * ray_depth <-- tfar - * barycentric_coord <-- [u, v, 1 - u - v] - * normal <-- Ng - * @endcode - */ - using FilterFunction = std::function; - -private: - /** Select between two sets of filters stored in the object. */ - enum { FILTER_INTERSECT = 0, FILTER_OCCLUDED = 1 }; - -public: - /** Constructor. */ - EmbreeRayCaster( - RTCSceneFlags scene_flags = RTC_SCENE_FLAG_DYNAMIC, - RTCBuildQuality build_quality = RTC_BUILD_QUALITY_LOW) - { -// Embree strongly recommend to have the Flush to Zero and -// Denormals are Zero mode of the MXCSR control and status -// register enabled for each thread before calling the -// rtcIntersect and rtcOccluded functions. -#ifdef _MM_SET_FLUSH_ZERO_MODE - _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); -#endif -#ifdef _MM_SET_DENORMALS_ZERO_MODE - _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); -#endif - - m_scene_flags = scene_flags; - m_build_quality = build_quality; - m_device = rtcNewDevice(NULL); - ensure_no_errors_internal(); - m_embree_world_scene = rtcNewScene(m_device); - ensure_no_errors_internal(); - m_instance_index_ranges.push_back(safe_cast(0)); - - m_need_rebuild = true; - m_need_commit = false; - } - - /** Destructor. */ - virtual ~EmbreeRayCaster() - { - release_scenes(); - rtcReleaseDevice(m_device); - } - - EmbreeRayCaster(const EmbreeRayCaster&) = delete; - void operator=(const EmbreeRayCaster&) = delete; - -public: - /** Get the total number of meshes (not instances). */ - Index get_num_meshes() const { return safe_cast(m_meshes.size()); } - - /** Get the total number of mesh instances. */ - Index get_num_instances() const { return m_instance_index_ranges.back(); } - - /** Get the number of instances of a particular mesh. */ - Index get_num_instances(Index mesh_index) const - { - la_debug_assert(mesh_index + 1 < safe_cast(m_instance_index_ranges.size())); - return safe_cast( - m_instance_index_ranges[mesh_index + 1] - m_instance_index_ranges[mesh_index]); - } - - /** - * Get the mesh with a given index. Requires the caller to know the original type of the mesh - * (@a MeshType) in advance. - */ - template - std::shared_ptr get_mesh(Index index) const - { - la_runtime_assert(index < safe_cast(m_meshes.size())); - la_runtime_assert(m_meshes[index] != nullptr); - return dynamic_cast&>(*m_meshes[index]).get_mesh_ptr(); - } - - /** - * Get the index of the mesh corresponding to a given instance, where the instances are indexed - * sequentially starting from the instances of the first mesh, then the instances of the second - * mesh, and so on. Use get_mesh() to map the returned index to an actual mesh. - * - * @param cumulative_instance_index An integer in the range `0` to `get_num_instances() - 1` - * (both inclusive). - */ - Index get_mesh_for_instance(Index cumulative_instance_index) const - { - la_runtime_assert(cumulative_instance_index < get_num_instances()); - return m_instance_to_user_mesh[cumulative_instance_index]; - } - - /** - * Add an instance of a mesh to the scene, with a given transformation. If another instance of - * the same mesh has been previously added to the scene, the two instances will NOT be - * considered to share the same mesh, but will be treated as separate instances of separate - * meshes. To add multiple instances of the same mesh, use add_meshes(). - */ - template - Index add_mesh( - std::shared_ptr mesh, - const Transform& trans = Transform::Identity(), - RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM) - { - return add_raycasting_mesh( - std::make_unique>(mesh), - trans, - build_quality); - } - - /** - * Add multiple instances of a single mesh to the scene, with given transformations. If another - * instance of the same mesh has been previously added to the scene, the new instances will NOT - * be considered to share the same mesh as the old instance, but will be treated as instances of - * a new mesh. Add all instances in a single add_meshes() call if you want to avoid this. - */ - template - Index add_meshes( - std::shared_ptr mesh, - const TransformVector& trans_vector, - RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM) - { - m_meshes.push_back(std::move(std::make_unique>(mesh))); - m_transforms.insert(m_transforms.end(), trans_vector.begin(), trans_vector.end()); - m_mesh_build_qualities.push_back(build_quality); - m_visibility.resize(m_visibility.size() + trans_vector.size(), true); - for (auto& f : m_filters) { // per-mesh, not per-instance - f.push_back(nullptr); - } - Index mesh_index = safe_cast(m_meshes.size() - 1); - la_runtime_assert(m_instance_index_ranges.size() > 0); - Index instance_index = m_instance_index_ranges.back(); - la_runtime_assert(instance_index == safe_cast(m_instance_to_user_mesh.size())); - Index new_instance_size = instance_index + trans_vector.size(); - m_instance_index_ranges.push_back(new_instance_size); - m_instance_to_user_mesh.resize(new_instance_size, mesh_index); - m_need_rebuild = true; - return mesh_index; - } - - /** - * Update a particular mesh with a new mesh object. All its instances will be affected. - * - * @note If you have changed the vertices of a mesh already in the scene, and just want the - * object to reflect that, then call update_mesh_vertices() instead. - */ - template - void update_mesh( - Index index, - std::shared_ptr mesh, - RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM) - { - update_raycasting_mesh( - index, - std::make_unique>(mesh), - build_quality); - } - - /** - * Update the object to reflect external changes to the vertices of a particular mesh which is - * already in the scene. All its instances will be affected. The number of vertices in the mesh, - * and their order in the vertex array, must not change. - */ - void update_mesh_vertices(Index index) - { - la_runtime_assert(index < safe_cast(m_meshes.size())); - if (m_need_rebuild) return; - - la_runtime_assert(index < safe_cast(m_embree_mesh_scenes.size())); - auto geom = rtcGetGeometry(m_embree_mesh_scenes[index], 0); - - // Update the vertex buffer in Embree - auto const& mesh = m_meshes[index]; - la_runtime_assert( - safe_cast(mesh->get_num_vertices()) == m_mesh_vertex_counts[index]); - - auto vbuf = - reinterpret_cast(rtcGetGeometryBufferData(geom, RTC_BUFFER_TYPE_VERTEX, 0)); - la_runtime_assert(vbuf); - mesh->vertices_to_float(vbuf); - rtcUpdateGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, 0); - - // Re-commit the mesh geometry and scene - rtcCommitGeometry(geom); - rtcCommitScene(m_embree_mesh_scenes[index]); - - // Re-commit every instance of the mesh - for (Index instance_index = m_instance_index_ranges[index]; - instance_index < m_instance_index_ranges[index + 1]; - ++instance_index) { - Index rtc_inst_id = m_instance_index_ranges[index] + instance_index; - auto geom_inst = - rtcGetGeometry(m_embree_world_scene, static_cast(rtc_inst_id)); - rtcCommitGeometry(geom_inst); - } - - // Mark the world scene as needing a re-commit (will be called lazily) - m_need_commit = true; - } - - /** Get the transform applied to a given mesh instance. */ - Transform get_transform(Index mesh_index, Index instance_index) const - { - la_runtime_assert(mesh_index + 1 < safe_cast(m_instance_index_ranges.size())); - Index index = m_instance_index_ranges[mesh_index] + instance_index; - la_runtime_assert(index < m_instance_index_ranges[mesh_index + 1]); - la_runtime_assert(index < safe_cast(m_transforms.size())); - return m_transforms[index]; - } - - /** Update the transform applied to a given mesh instance. */ - void update_transformation(Index mesh_index, Index instance_index, const Transform& trans) - { - la_runtime_assert(mesh_index + 1 < safe_cast(m_instance_index_ranges.size())); - Index index = m_instance_index_ranges[mesh_index] + instance_index; - la_runtime_assert(index < m_instance_index_ranges[mesh_index + 1]); - la_runtime_assert(index < safe_cast(m_transforms.size())); - m_transforms[index] = trans; - if (!m_need_rebuild) { - auto geom = rtcGetGeometry(m_embree_world_scene, static_cast(index)); - Eigen::Matrix T = trans.template cast(); - rtcSetGeometryTransform(geom, 0, RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR, T.eval().data()); - rtcCommitGeometry(geom); - m_need_commit = true; - } - } - - /** Get the visibility flag of a given mesh instance. */ - bool get_visibility(Index mesh_index, Index instance_index) const - { - la_runtime_assert(mesh_index + 1 < safe_cast(m_instance_index_ranges.size())); - Index index = m_instance_index_ranges[mesh_index] + instance_index; - la_runtime_assert(index < m_instance_index_ranges[mesh_index + 1]); - la_runtime_assert(index < safe_cast(m_visibility.size())); - return m_visibility[index]; - } - - /** Update the visibility of a given mesh index (true for visible, false for invisible). */ - void update_visibility(Index mesh_index, Index instance_index, bool visible) - { - la_runtime_assert(mesh_index + 1 < safe_cast(m_instance_index_ranges.size())); - Index index = m_instance_index_ranges[mesh_index] + instance_index; - la_runtime_assert(index < m_instance_index_ranges[mesh_index + 1]); - la_runtime_assert(index < safe_cast(m_visibility.size())); - m_visibility[index] = visible; - if (!m_need_rebuild && - rtcGetDeviceProperty(m_device, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED)) { - // ^^^ else, visibility will be checked by the already bound filter - - auto geom = rtcGetGeometry(m_embree_world_scene, static_cast(index)); - rtcSetGeometryMask(geom, visible ? 0xFFFFFFFF : 0x00000000); - rtcCommitGeometry(geom); - m_need_commit = true; - } - } - - /** - * Set an intersection filter that is called for every hit on (every instance of) a mesh during - * an intersection query. The @a filter function must be callable as: - * - * @code - * void filter(const EmbreeRayCaster* obj, const Index* mesh_index, const Index* instance_index, - * const RTCFilterFunctionNArguments* args); - * @endcode - * - * It functions exactly like Embree's `rtcSetGeometryIntersectFilterFunction`, except it also - * receives a handle to this object, and mesh and instance indices specific to this object. A - * null @a filter disables intersection filtering for this mesh. - * - * @note Embree dictates that filters can be associated only with meshes (raw geometries), not - * instances. - */ - void set_intersection_filter(Index mesh_index, FilterFunction filter) - { - la_runtime_assert(mesh_index < m_filters[FILTER_INTERSECT].size()); - m_filters[FILTER_INTERSECT][mesh_index] = filter; - m_need_rebuild = true; - } - - /** - * Get the intersection filter function currently bound to a given mesh. - * - * @note Embree dictates that filters can be associated only with meshes (raw geometries), not - * instances. - */ - FilterFunction get_intersection_filter(Index mesh_index) const - { - la_runtime_assert(mesh_index < m_filters[FILTER_INTERSECT].size()); - return m_filters[FILTER_INTERSECT][mesh_index]; - } - - /** - * Set an occlusion filter that is called for every hit on (every instance of) a mesh during an - * occlusion query. The @a filter function must be callable as: - * - * @code - * void filter(const EmbreeRayCaster* obj, const Index* mesh_index, const Index* instance_index, - * const RTCFilterFunctionNArguments* args); - * @endcode - * - * It functions exactly like Embree's `rtcSetGeometryOccludedFilterFunction`, except it also - * receives a handle to this object, and mesh and instance indices specific to this object. A - * null @a filter disables occlusion filtering for this mesh. - * - * @note Embree dictates that filters can be associated only with meshes (raw geometries), not - * instances. - */ - void set_occlusion_filter(Index mesh_index, FilterFunction filter) - { - la_runtime_assert(mesh_index < m_filters[FILTER_OCCLUDED].size()); - m_filters[FILTER_OCCLUDED][mesh_index] = filter; - m_need_rebuild = true; - } - - /** - * Get the occlusion filter function currently bound to a given mesh. - * - * @note Embree dictates that filters can be associated only with meshes (raw geometries), not - * instances. - */ - FilterFunction get_occlusion_filter(Index mesh_index) const - { - la_runtime_assert(mesh_index < m_filters[FILTER_OCCLUDED].size()); - return m_filters[FILTER_OCCLUDED][mesh_index]; - } - - /** - * Call `rtcCommitScene()` on the overall scene, if it has been marked as modified. - * - * @todo Now that this is automatically called by update_internal() based on a dirty flag, can - * we make this a protected/private function? That would break the API so maybe reserve it - * for a major version. - */ - void commit_scene_changes() - { - if (!m_need_commit) return; - - rtcCommitScene(m_embree_world_scene); - m_need_commit = false; - } - - /** Throw an exception if an Embree error has occurred.*/ - void ensure_no_errors() const { EmbreeHelper::ensure_no_errors(m_device); } - - /** - * Cast a packet of up to 4 rays through the scene, returning full data of the closest - * intersections including normals and instance indices. - */ - uint32_t cast4( - uint32_t batch_size, - const Point4& origin, - const Direction4& direction, - const Mask4& mask, - Index4& mesh_index, - Index4& instance_index, - Index4& facet_index, - Scalar4& ray_depth, - Point4& barycentric_coord, - Point4& normal, - const Scalar4& tmin = Scalar4::Zero(), - const Scalar4& tmax = Scalar4::Constant(std::numeric_limits::infinity())) - { - la_debug_assert(batch_size <= 4); - - update_internal(); - - RTCRayHit4 embree_raypacket; - for (int i = 0; i < static_cast(batch_size); ++i) { - // Set ray origins - embree_raypacket.ray.org_x[i] = static_cast(origin(i, 0)); - embree_raypacket.ray.org_y[i] = static_cast(origin(i, 1)); - embree_raypacket.ray.org_z[i] = static_cast(origin(i, 2)); - - // Set ray directions - embree_raypacket.ray.dir_x[i] = static_cast(direction(i, 0)); - embree_raypacket.ray.dir_y[i] = static_cast(direction(i, 1)); - embree_raypacket.ray.dir_z[i] = static_cast(direction(i, 2)); - - // Misc - embree_raypacket.ray.tnear[i] = static_cast(tmin[i]); - embree_raypacket.ray.tfar[i] = std::isinf(tmax[i]) ? std::numeric_limits::max() - : static_cast(tmax[i]); - embree_raypacket.ray.mask[i] = 0xFFFFFFFF; - embree_raypacket.ray.id[i] = static_cast(i); - embree_raypacket.ray.flags[i] = 0; - - // Required initialization of the hit substructure - embree_raypacket.hit.geomID[i] = RTC_INVALID_GEOMETRY_ID; - embree_raypacket.hit.primID[i] = RTC_INVALID_GEOMETRY_ID; - embree_raypacket.hit.instID[0][i] = RTC_INVALID_GEOMETRY_ID; - } - - // Modify the mask to make 100% sure extra rays in the packet will be ignored - auto packet_mask = mask; - for (int i = static_cast(batch_size); i < 4; ++i) packet_mask[i] = 0; - - ensure_no_errors_internal(); -#ifdef LAGRANGE_WITH_EMBREE_4 - rtcIntersect4(packet_mask.data(), m_embree_world_scene, &embree_raypacket); -#else - RTCIntersectContext context; - rtcInitIntersectContext(&context); - rtcIntersect4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket); -#endif - ensure_no_errors_internal(); - - uint32_t is_hits = 0; - for (int i = 0; i < static_cast(batch_size); ++i) { - if (embree_raypacket.hit.geomID[i] != RTC_INVALID_GEOMETRY_ID) { - Index rtc_inst_id = embree_raypacket.hit.instID[0][i]; - Index rtc_mesh_id = (rtc_inst_id == RTC_INVALID_GEOMETRY_ID) - ? embree_raypacket.hit.geomID[i] - : rtc_inst_id; - assert(rtc_mesh_id < m_instance_to_user_mesh.size()); - assert(m_visibility[rtc_mesh_id]); - mesh_index[i] = m_instance_to_user_mesh[rtc_mesh_id]; - assert(mesh_index[i] + 1 < m_instance_index_ranges.size()); - assert(mesh_index[i] < safe_cast(m_meshes.size())); - instance_index[i] = rtc_mesh_id - m_instance_index_ranges[mesh_index[i]]; - facet_index[i] = embree_raypacket.hit.primID[i]; - ray_depth[i] = embree_raypacket.ray.tfar[i]; - barycentric_coord(i, 0) = - 1.0f - embree_raypacket.hit.u[i] - embree_raypacket.hit.v[i]; - barycentric_coord(i, 1) = embree_raypacket.hit.u[i]; - barycentric_coord(i, 2) = embree_raypacket.hit.v[i]; - normal(i, 0) = embree_raypacket.hit.Ng_x[i]; - normal(i, 1) = embree_raypacket.hit.Ng_y[i]; - normal(i, 2) = embree_raypacket.hit.Ng_z[i]; - is_hits = is_hits | (1 << i); - } - } - - return is_hits; - } - - /** - * Cast a packet of up to 4 rays through the scene, returning data of the closest intersections - * excluding normals and instance indices. - */ - uint32_t cast4( - uint32_t batch_size, - const Point4& origin, - const Direction4& direction, - const Mask4& mask, - Index4& mesh_index, - Index4& facet_index, - Scalar4& ray_depth, - Point4& barycentric_coord, - const Scalar4& tmin = Scalar4::Zero(), - const Scalar4& tmax = Scalar4::Constant(std::numeric_limits::infinity())) - { - Index4 instance_index; - Point4 normal; - return cast4( - batch_size, - origin, - direction, - mask, - mesh_index, - instance_index, - facet_index, - ray_depth, - barycentric_coord, - normal, - tmin, - tmax); - } - - /** - * Cast a packet of up to 4 rays through the scene and check whether they hit anything or not. - */ - uint32_t cast4( - uint32_t batch_size, - const Point4& origin, - const Direction4& direction, - const Mask4& mask, - const Scalar4& tmin = Scalar4::Zero(), - const Scalar4& tmax = Scalar4::Constant(std::numeric_limits::infinity())) - { - la_debug_assert(batch_size <= 4); - - update_internal(); - - RTCRay4 embree_raypacket; - for (int i = 0; i < static_cast(batch_size); ++i) { - // Set ray origins - embree_raypacket.org_x[i] = static_cast(origin(i, 0)); - embree_raypacket.org_y[i] = static_cast(origin(i, 1)); - embree_raypacket.org_z[i] = static_cast(origin(i, 2)); - - // Set ray directions - embree_raypacket.dir_x[i] = static_cast(direction(i, 0)); - embree_raypacket.dir_y[i] = static_cast(direction(i, 1)); - embree_raypacket.dir_z[i] = static_cast(direction(i, 2)); - - // Misc - embree_raypacket.tnear[i] = static_cast(tmin[i]); - embree_raypacket.tfar[i] = std::isinf(tmax[i]) ? std::numeric_limits::max() - : static_cast(tmax[i]); - embree_raypacket.mask[i] = 0xFFFFFFFF; - embree_raypacket.id[i] = static_cast(i); - embree_raypacket.flags[i] = 0; - } - - // Modify the mask to make 100% sure extra rays in the packet will be ignored - auto packet_mask = mask; - for (int i = static_cast(batch_size); i < 4; ++i) packet_mask[i] = 0; - - ensure_no_errors_internal(); -#ifdef LAGRANGE_WITH_EMBREE_4 - rtcOccluded4(packet_mask.data(), m_embree_world_scene, &embree_raypacket); -#else - RTCIntersectContext context; - rtcInitIntersectContext(&context); - rtcOccluded4(packet_mask.data(), m_embree_world_scene, &context, &embree_raypacket); -#endif - ensure_no_errors_internal(); - - // If hit, the tfar field will be set to -inf. - uint32_t is_hits = 0; - for (uint32_t i = 0; i < batch_size; ++i) - if (!std::isfinite(embree_raypacket.tfar[i])) is_hits = is_hits | (1 << i); - - return is_hits; - } - - /** - * Cast a single ray through the scene, returning full data of the closest intersection - * including the normal and the instance index. - */ - bool cast( - const Point& origin, - const Direction& direction, - Index& mesh_index, - Index& instance_index, - Index& facet_index, - Scalar& ray_depth, - Point& barycentric_coord, - Point& normal, - Scalar tmin = 0, - Scalar tmax = std::numeric_limits::infinity()) - { - // Overloaded when specializing tnear and tfar - - update_internal(); - - RTCRayHit embree_rayhit; - embree_rayhit.ray.org_x = static_cast(origin.x()); - embree_rayhit.ray.org_y = static_cast(origin.y()); - embree_rayhit.ray.org_z = static_cast(origin.z()); - embree_rayhit.ray.dir_x = static_cast(direction.x()); - embree_rayhit.ray.dir_y = static_cast(direction.y()); - embree_rayhit.ray.dir_z = static_cast(direction.z()); - embree_rayhit.ray.tnear = static_cast(tmin); - embree_rayhit.ray.tfar = - std::isinf(tmax) ? std::numeric_limits::max() : static_cast(tmax); - embree_rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID; - embree_rayhit.hit.primID = RTC_INVALID_GEOMETRY_ID; - embree_rayhit.hit.instID[0] = RTC_INVALID_GEOMETRY_ID; - embree_rayhit.ray.mask = 0xFFFFFFFF; - embree_rayhit.ray.id = 0; - embree_rayhit.ray.flags = 0; - ensure_no_errors_internal(); -#ifdef LAGRANGE_WITH_EMBREE_4 - rtcIntersect1(m_embree_world_scene, &embree_rayhit); -#else - RTCIntersectContext context; - rtcInitIntersectContext(&context); - rtcIntersect1(m_embree_world_scene, &context, &embree_rayhit); -#endif - ensure_no_errors_internal(); - - if (embree_rayhit.hit.geomID != RTC_INVALID_GEOMETRY_ID) { - Index rtc_inst_id = embree_rayhit.hit.instID[0]; - Index rtc_mesh_id = - (rtc_inst_id == RTC_INVALID_GEOMETRY_ID) ? embree_rayhit.hit.geomID : rtc_inst_id; - assert(rtc_mesh_id < m_instance_to_user_mesh.size()); - assert(m_visibility[rtc_mesh_id]); - mesh_index = m_instance_to_user_mesh[rtc_mesh_id]; - assert(mesh_index + 1 < m_instance_index_ranges.size()); - assert(mesh_index < safe_cast(m_meshes.size())); - instance_index = rtc_mesh_id - m_instance_index_ranges[mesh_index]; - facet_index = embree_rayhit.hit.primID; - ray_depth = embree_rayhit.ray.tfar; - barycentric_coord[0] = 1.0f - embree_rayhit.hit.u - embree_rayhit.hit.v; - barycentric_coord[1] = embree_rayhit.hit.u; - barycentric_coord[2] = embree_rayhit.hit.v; - normal[0] = embree_rayhit.hit.Ng_x; - normal[1] = embree_rayhit.hit.Ng_y; - normal[2] = embree_rayhit.hit.Ng_z; - return true; - } else { - // Ray missed. - mesh_index = invalid(); - instance_index = invalid(); - facet_index = invalid(); - return false; - } - } - - /** - * Cast a single ray through the scene, returning data of the closest intersection excluding the - * normal and the instance index. - */ - bool cast( - const Point& origin, - const Direction& direction, - Index& mesh_index, - Index& facet_index, - Scalar& ray_depth, - Point& barycentric_coord, - Scalar tmin = 0, - Scalar tmax = std::numeric_limits::infinity()) - { - Index instance_index; - Point normal; - return cast( - origin, - direction, - mesh_index, - instance_index, - facet_index, - ray_depth, - barycentric_coord, - normal, - tmin, - tmax); - } - - /** Cast a single ray through the scene and check whether it hits anything or not. */ - bool cast( - const Point& origin, - const Direction& direction, - Scalar tmin = 0, - Scalar tmax = std::numeric_limits::infinity()) - { - update_internal(); - - RTCRay embree_ray; - embree_ray.org_x = static_cast(origin.x()); - embree_ray.org_y = static_cast(origin.y()); - embree_ray.org_z = static_cast(origin.z()); - embree_ray.dir_x = static_cast(direction.x()); - embree_ray.dir_y = static_cast(direction.y()); - embree_ray.dir_z = static_cast(direction.z()); - embree_ray.tnear = static_cast(tmin); - embree_ray.tfar = - std::isinf(tmax) ? std::numeric_limits::max() : static_cast(tmax); - embree_ray.mask = 0xFFFFFFFF; - embree_ray.id = 0; - embree_ray.flags = 0; - - ensure_no_errors_internal(); -#ifdef LAGRANGE_WITH_EMBREE_4 - rtcOccluded1(m_embree_world_scene, &embree_ray); -#else - RTCIntersectContext context; - rtcInitIntersectContext(&context); - rtcOccluded1(m_embree_world_scene, &context, &embree_ray); -#endif - ensure_no_errors_internal(); - - // If hit, the tfar field will be set to -inf. - return !std::isfinite(embree_ray.tfar); - } - - /** Use the underlying BVH to find the point closest to a query point. */ - ClosestPoint query_closest_point(const Point& p) const; - - /** Add raycasting utilities **/ - Index add_raycasting_mesh( - std::unique_ptr mesh, - const Transform& trans = Transform::Identity(), - RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM) - { - m_meshes.push_back(std::move(mesh)); - m_transforms.push_back(trans); - m_mesh_build_qualities.push_back(build_quality); - m_visibility.push_back(true); - for (auto& f : m_filters) { // per-mesh, not per-instance - f.push_back(nullptr); - } - Index mesh_index = safe_cast(m_meshes.size() - 1); - la_runtime_assert(m_instance_index_ranges.size() > 0); - Index instance_index = m_instance_index_ranges.back(); - la_runtime_assert(instance_index == safe_cast(m_instance_to_user_mesh.size())); - m_instance_index_ranges.push_back(instance_index + 1); - m_instance_to_user_mesh.resize(instance_index + 1, mesh_index); - m_need_rebuild = true; - return mesh_index; - } - - void update_raycasting_mesh( - Index index, - std::unique_ptr mesh, - RTCBuildQuality build_quality = RTC_BUILD_QUALITY_MEDIUM) - { - la_runtime_assert(mesh->get_dim() == 3); - la_runtime_assert(mesh->get_vertex_per_facet() == 3); - la_runtime_assert(index < safe_cast(m_meshes.size())); - m_meshes[index] = std::move(mesh); - m_mesh_build_qualities[index] = build_quality; - m_need_rebuild = true; // TODO: Make this more fine-grained so only the affected part of - // the Embree scene is updated - } - -protected: - /** Release internal Embree scenes */ - void release_scenes() - { - for (auto& s : m_embree_mesh_scenes) { - rtcReleaseScene(s); - } - rtcReleaseScene(m_embree_world_scene); - } - - /** Get the Embree scene flags. */ - virtual RTCSceneFlags get_scene_flags() const { return m_scene_flags; } - - /** Get the Embree geometry build quality. */ - virtual RTCBuildQuality get_scene_build_quality() const { return m_build_quality; } - - /** Update all internal structures based on the current dirty flags. */ - void update_internal() - { - if (m_need_rebuild) - generate_scene(); // full rebuild - else if (m_need_commit) - commit_scene_changes(); // just call rtcCommitScene() - } - - /** - * Build the whole Embree scene from the specified meshes, instances, etc. - * - * @todo Make the dirty flags more fine-grained so that only the changed meshes are re-sent to - * Embree. - */ - void generate_scene() - { - if (!m_need_rebuild) return; - - // Scene needs to be updated - release_scenes(); - m_embree_world_scene = rtcNewScene(m_device); - auto scene_flags = get_scene_flags(); // FIXME: or just m_scene_flags? - auto scene_build_quality = get_scene_build_quality(); // FIXME: or just m_build_quality? - rtcSetSceneFlags( - m_embree_world_scene, - scene_flags); // TODO: maybe also set RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION - rtcSetSceneBuildQuality(m_embree_world_scene, scene_build_quality); - m_float_data.clear(); - m_int_data.clear(); - const auto num_meshes = m_meshes.size(); - la_runtime_assert(num_meshes + 1 == m_instance_index_ranges.size()); - m_embree_mesh_scenes.resize(num_meshes); - m_mesh_vertex_counts.resize(num_meshes); - ensure_no_errors_internal(); - - bool is_mask_supported = - rtcGetDeviceProperty(m_device, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED); - for (size_t i = 0; i < num_meshes; i++) { - // Initialize RTC meshes - const auto& mesh = m_meshes[i]; - // const auto& vertices = mesh->get_vertices(); - // const auto& facets = mesh->get_facets(); - const Index num_vertices = m_mesh_vertex_counts[i] = - safe_cast(mesh->get_num_vertices()); - const Index num_facets = safe_cast(mesh->get_num_facets()); - - auto& embree_mesh_scene = m_embree_mesh_scenes[i]; - embree_mesh_scene = rtcNewScene(m_device); - - rtcSetSceneFlags(embree_mesh_scene, scene_flags); - rtcSetSceneBuildQuality(embree_mesh_scene, scene_build_quality); - ensure_no_errors_internal(); - - RTCGeometry geom = rtcNewGeometry( - m_device, - RTC_GEOMETRY_TYPE_TRIANGLE); // EMBREE_FIXME: check if geometry gets properly - // committed - rtcSetGeometryBuildQuality(geom, m_mesh_build_qualities[i]); - // rtcSetGeometryTimeStepCount(geom, 1); - - const float* vertex_data = extract_float_data(*mesh); - const unsigned* facet_data = extract_int_data(*mesh); - - rtcSetSharedGeometryBuffer( - geom, - RTC_BUFFER_TYPE_VERTEX, - 0, - RTC_FORMAT_FLOAT3, - vertex_data, - 0, - sizeof(float) * 3, - num_vertices); - rtcSetSharedGeometryBuffer( - geom, - RTC_BUFFER_TYPE_INDEX, - 0, - RTC_FORMAT_UINT3, - facet_data, - 0, - sizeof(int) * 3, - num_facets); - - set_intersection_filter(geom, m_filters[FILTER_INTERSECT][i], is_mask_supported); - set_occlusion_filter(geom, m_filters[FILTER_OCCLUDED][i], is_mask_supported); - - rtcCommitGeometry(geom); - rtcAttachGeometry(embree_mesh_scene, geom); - rtcReleaseGeometry(geom); - ensure_no_errors_internal(); - - // Initialize RTC instances - for (Index instance_index = m_instance_index_ranges[i]; - instance_index < m_instance_index_ranges[i + 1]; - ++instance_index) { - const auto& trans = m_transforms[instance_index]; - - RTCGeometry geom_inst = rtcNewGeometry( - m_device, - RTC_GEOMETRY_TYPE_INSTANCE); // EMBREE_FIXME: check if geometry gets properly - // committed - rtcSetGeometryInstancedScene(geom_inst, embree_mesh_scene); - rtcSetGeometryTimeStepCount(geom_inst, 1); - - Eigen::Matrix T = trans.template cast(); - rtcSetGeometryTransform(geom_inst, 0, RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR, T.data()); - ensure_no_errors_internal(); - - if (is_mask_supported) { - rtcSetGeometryMask( - geom_inst, - m_visibility[instance_index] ? 0xFFFFFFFF : 0x00000000); - } - ensure_no_errors_internal(); - - rtcCommitGeometry(geom_inst); - unsigned rtc_instance_id = rtcAttachGeometry(m_embree_world_scene, geom_inst); - rtcReleaseGeometry(geom_inst); - la_runtime_assert(safe_cast(rtc_instance_id) == instance_index); - ensure_no_errors_internal(); - } - - rtcCommitScene(embree_mesh_scene); - ensure_no_errors_internal(); - } - rtcCommitScene(m_embree_world_scene); - ensure_no_errors_internal(); - - m_need_rebuild = m_need_commit = false; - } - - /** Get the vertex data of a mesh as an array of floats. */ - const float* extract_float_data(const RaycasterMesh& mesh) - { - auto float_data = mesh.vertices_to_float(); - // Due to Embree bug, we have to have at least one more entry - // after the bound. Sigh... - // See https://github.com/embree/embree/issues/124 - float_data.push_back(0.0); - m_float_data.emplace_back(std::move(float_data)); - return m_float_data.back().data(); - } - - /** Get the index data of a mesh as an array of integers. */ - const unsigned* extract_int_data(const RaycasterMesh& mesh) - { - auto int_data = mesh.indices_to_int(); - // Due to Embree bug, we have to have at least one more entry - // after the bound. Sigh... - // See https://github.com/embree/embree/issues/124 - int_data.push_back(0); - m_int_data.emplace_back(std::move(int_data)); - return m_int_data.back().data(); - } - -private: - /** - * Helper function for setting intersection filters. Does NOT commit the geometry. The caller - * must explicitly call `rtcCommitGeometry()` afterwards. - */ - void set_intersection_filter(RTCGeometry geom, FilterFunction filter, bool is_mask_supported) - { - if (is_mask_supported) { - if (filter) { - rtcSetGeometryUserData(geom, this); - rtcSetGeometryIntersectFilterFunction(geom, &wrap_filter); - } else { - rtcSetGeometryIntersectFilterFunction(geom, nullptr); - } - } else { - rtcSetGeometryUserData(geom, this); - rtcSetGeometryIntersectFilterFunction(geom, &wrap_filter_and_mask); - } - } - - /** - * Helper function for setting occlusion filters. Does NOT commit the geometry. The caller must - * explicitly call `rtcCommitGeometry()` afterwards. - */ - void set_occlusion_filter(RTCGeometry geom, FilterFunction filter, bool is_mask_supported) - { - if (is_mask_supported) { - if (filter) { - rtcSetGeometryUserData(geom, this); - rtcSetGeometryOccludedFilterFunction(geom, &wrap_filter); - } else { - rtcSetGeometryOccludedFilterFunction(geom, nullptr); - } - } else { - rtcSetGeometryUserData(geom, this); - rtcSetGeometryOccludedFilterFunction(geom, &wrap_filter_and_mask); - } - } - - /** - * Embree-compatible callback function that computes indices specific to this object and then - * delegates to the user-specified filter function. - */ - template // 0: intersection, 1: occlusion - static void wrap_filter(const RTCFilterFunctionNArguments* args) - { - // Embree never actually calls a filter callback with different geometry or instance IDs - // So we can assume they are the same for all the hits in this batch. Also, every single - // mesh in this class is instanced (never used raw), so we can ignore geomID. - const auto* obj = reinterpret_cast(args->geometryUserPtr); - auto rtc_inst_id = RTCHitN_instID(args->hit, args->N, 0, 0); - assert(rtc_inst_id < obj->m_instance_to_user_mesh.size()); - - auto filter = obj->m_filters[IntersectionOrOcclusion][rtc_inst_id]; - if (!filter) { - return; - } - - Index mesh_index = obj->m_instance_to_user_mesh[rtc_inst_id]; - assert(mesh_index + 1 < obj->m_instance_index_ranges.size()); - assert(mesh_index < safe_cast(obj->m_meshes.size())); - Index instance_index = rtc_inst_id - obj->m_instance_index_ranges[mesh_index]; - - // In case Embree's implementation changes in the future, the callback should be written - // generally, without assuming the single geometry/instance condition above. - Index4 mesh_index4; - mesh_index4.fill(mesh_index); - Index4 instance_index4; - instance_index4.fill(instance_index); - - // Call the wrapped filter with the indices specific to this object - filter(obj, mesh_index4.data(), instance_index4.data(), args); - } - - /** - * Embree-compatible callback function that checks if the intersected object is visible or not, - * computes indices specific to this object, and then delegates to the user-specified filter - * function. - */ - template // 0: intersection, 1: occlusion - static void wrap_filter_and_mask(const RTCFilterFunctionNArguments* args) - { - // Embree never actually calls a filter callback with different geometry or instance IDs - // So we can assume they are the same for all the hits in this batch. Also, every single - // mesh in this class is instanced (never used raw), so we can ignore geomID. - const auto* obj = reinterpret_cast(args->geometryUserPtr); - auto rtc_inst_id = RTCHitN_instID(args->hit, args->N, 0, 0); - if (!obj->m_visibility[rtc_inst_id]) { - // Object is invisible. Make the hits of all the rays with this object invalid. - std::fill(args->valid, args->valid + args->N, 0); - return; - } - - // Delegate to the regular filtering after having checked visibility - wrap_filter(args); - } - -protected: - RTCSceneFlags m_scene_flags; - RTCBuildQuality m_build_quality; - RTCDevice m_device; - RTCScene m_embree_world_scene; - bool m_need_rebuild; // full rebuild of the scene? - bool m_need_commit; // just call rtcCommitScene() on the scene? - - // Data reservoirs for holding temporary/casted/per-geometry data. - // Length = Number of polygonal meshes - std::vector m_float_data; - std::vector m_int_data; - std::vector> m_meshes; - std::vector m_mesh_build_qualities; - std::vector m_embree_mesh_scenes; - std::vector m_mesh_vertex_counts; // for bounds-checking of buffer updates - std::vector m_filters[2]; // 0: intersection filters, 1: occlusion filters - - // Ranges of instance indices corresponding to a specific - // Mesh. For example, in a scenario with 3 meshes each of - // which has 1, 2, 5 instances, this array would be - // [0, 1, 3, 8]. - // Length = Number of user meshes + 1 - std::vector m_instance_index_ranges; - - // Mapping from (RTC-)instanced mesh to user mesh. For - // example, in a scenario with 3 meshes each of - // which has 1, 2, 5 instances, this array would be - // [0, 1, 1, 2, 2, 2, 2, 2] - // Length = Number of instanced meshes - // Note: This array is only used internally. We shouldn't - // allow the users to access anything with the indices - // used in those RTC functions. - std::vector m_instance_to_user_mesh; - - // Data reservoirs for holding instanced mesh data - // Length = Number of (world-space) instanced meshes - std::vector m_transforms; - std::vector m_visibility; - - // error checking function used internally - void ensure_no_errors_internal() const - { -#ifdef LAGRANGE_EMBREE_DEBUG - EmbreeHelper::ensure_no_errors(m_device); -#endif - } -}; - -//////////////////////////////////////////////////////////////////////////////// -// IMPLEMENTATION -//////////////////////////////////////////////////////////////////////////////// - -template -auto EmbreeRayCaster::query_closest_point(const Point& p) const -> ClosestPoint -{ - RTCPointQuery query; - query.x = (float)(p.x()); - query.y = (float)(p.y()); - query.z = (float)(p.z()); - query.radius = std::numeric_limits::max(); - query.time = 0.f; - ensure_no_errors_internal(); - - ClosestPoint result; - - // Callback to retrieve triangle corner positions - result.populate_triangle = - [&](unsigned mesh_index, unsigned facet_index, Point& v0, Point& v1, Point& v2) { - // TODO: There's no way to call this->get_mesh<> since we need to template the function - // by the (derived) type, which we don't know here... This means our only choice is so - // use the float data instead of the (maybe) double point coordinate if available. Note - // that we could also call rtcSetGeometryPointQueryFunction() when we register our mesh, - // since we know the derived type at this point. - const unsigned* face = m_int_data[mesh_index].data() + 3 * facet_index; - const float* vertices = m_float_data[mesh_index].data(); - v0 = Point(vertices[3 * face[0]], vertices[3 * face[0] + 1], vertices[3 * face[0] + 2]); - v1 = Point(vertices[3 * face[1]], vertices[3 * face[1] + 1], vertices[3 * face[1] + 2]); - v2 = Point(vertices[3 * face[2]], vertices[3 * face[2] + 1], vertices[3 * face[2] + 2]); - }; - - { - RTCPointQueryContext context; - rtcInitPointQueryContext(&context); - rtcPointQuery( - m_embree_world_scene, - &query, - &context, - &embree_closest_point, - reinterpret_cast(&result)); - assert( - result.mesh_index != RTC_INVALID_GEOMETRY_ID || - result.facet_index != RTC_INVALID_GEOMETRY_ID); - assert( - result.mesh_index != invalid() || result.facet_index != invalid()); - } - ensure_no_errors_internal(); - - return result; -} - -} // namespace raycasting -} // namespace lagrange -======= #ifdef LAGRANGE_ENABLE_LEGACY_FUNCTIONS #include #endif ->>>>>>> origin/main diff --git a/modules/raycasting/include/lagrange/raycasting/embree_closest_point.h b/modules/raycasting/include/lagrange/raycasting/embree_closest_point.h index 1c70701f..65bd2561 100644 --- a/modules/raycasting/include/lagrange/raycasting/embree_closest_point.h +++ b/modules/raycasting/include/lagrange/raycasting/embree_closest_point.h @@ -11,105 +11,6 @@ */ #pragma once -<<<<<<< HEAD -#include - -#include - -#ifdef LAGRANGE_WITH_EMBREE_4 - #include - #include - #include -#else - #include - #include - #include -#endif - -#include - -RTC_NAMESPACE_USE - -namespace lagrange { -namespace raycasting { - -template -bool embree_closest_point(RTCPointQueryFunctionArguments* args) -{ - using Point = typename ClosestPointResult::Point; - using MapType = Eigen::Map; - using AffineMat = Eigen::Transform; - - assert(args->userPtr); - auto result = reinterpret_cast*>(args->userPtr); - - const unsigned int geomID = args->geomID; - const unsigned int primID = args->primID; - - RTCPointQueryContext* context = args->context; - const unsigned int stack_size = args->context->instStackSize; - const unsigned int stack_ptr = stack_size - 1; - - AffineMat inst2world = - (stack_size > 0 ? AffineMat(MapType(context->inst2world[stack_ptr]).template cast()) - : AffineMat::Identity()); - - // Query position in world space - Point q(args->query->x, args->query->y, args->query->z); - - // Get triangle information in local space - Point v0, v1, v2; - assert(result->populate_triangle); - result->populate_triangle(geomID, primID, v0, v1, v2); - - // Bring query and primitive data in the same space if necessary. - if (stack_size > 0 && args->similarityScale > 0) { - // Instance transform is a similarity transform, therefore we - // can compute distance information in instance space. Therefore, - // transform query position into local instance space. - AffineMat world2inst(MapType(context->world2inst[stack_ptr]).template cast()); - q = world2inst * q; - } else if (stack_size > 0) { - // Instance transform is not a similarity tranform. We have to transform the - // primitive data into world space and perform distance computations in - // world space to ensure correctness. - v0 = inst2world * v0; - v1 = inst2world * v1; - v2 = inst2world * v2; - } else { - // Primitive is not instanced, therefore point query and primitive are - // already in the same space. - } - - // Determine distance to closest point on triangle, and transform in - // world space if necessary. - Point p; - Scalar l1, l2, l3; - Scalar d2 = point_triangle_squared_distance(q, v0, v1, v2, p, l1, l2, l3); - float d = std::sqrt(static_cast(d2)); - if (args->similarityScale > 0) { - d = d / args->similarityScale; - } - - // Store result in userPtr and update the query radius if we found a point - // closer to the query position. This is optional but allows for faster - // traversal (due to better culling). - if (d < args->query->radius) { - args->query->radius = d; - result->closest_point = (args->similarityScale > 0 ? (inst2world * p).eval() : p); - result->mesh_index = geomID; - result->facet_index = primID; - result->barycentric_coord = Point(l1, l2, l3); - return true; // Return true to indicate that the query radius changed. - } - - return false; -} - -} // namespace raycasting -} // namespace lagrange -======= #ifdef LAGRANGE_ENABLE_LEGACY_FUNCTIONS #include #endif ->>>>>>> origin/main diff --git a/modules/raycasting/src/legacy/EmbreeHelper.cpp b/modules/raycasting/src/legacy/EmbreeHelper.cpp index f8e872af..9ad36768 100644 --- a/modules/raycasting/src/legacy/EmbreeHelper.cpp +++ b/modules/raycasting/src/legacy/EmbreeHelper.cpp @@ -9,17 +9,10 @@ * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ -<<<<<<< HEAD:modules/raycasting/src/EmbreeHelper.cpp -#ifdef LAGRANGE_WITH_EMBREE_4 - #include -#else - #include -======= #ifdef LAGRANGE_WITH_EMBREE_3 #include #else #include ->>>>>>> origin/main:modules/raycasting/src/legacy/EmbreeHelper.cpp #endif #include From 1385250f11e6807a9f73e77040618f8bdcb5c993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Mon, 9 Mar 2026 10:16:28 -0700 Subject: [PATCH 36/66] Cleanup. --- cmake/recipes/external/embree.cmake | 175 ++++++++++++++++++ .../external/{embree3.patch => embree.patch} | 0 2 files changed, 175 insertions(+) create mode 100644 cmake/recipes/external/embree.cmake rename cmake/recipes/external/{embree3.patch => embree.patch} (100%) diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree.cmake new file mode 100644 index 00000000..a323f51c --- /dev/null +++ b/cmake/recipes/external/embree.cmake @@ -0,0 +1,175 @@ +# +# Copyright 2019 Adobe. All rights reserved. +# This file is licensed to you under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under +# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +# OF ANY KIND, either express or implied. See the License for the specific language +# governing permissions and limitations under the License. +# +if(TARGET embree::embree) + return() +endif() + +message(STATUS "Third-party (external): creating target 'embree::embree'") + +# Set Embree's default options +option(EMBREE_ISPC_SUPPORT "Build Embree with support for ISPC applications." OFF) +option(EMBREE_TUTORIALS "Enable to build Embree tutorials" OFF) +option(EMBREE_STATIC_LIB "Build Embree as a static library." ON) +set(EMBREE_TESTING_INTENSITY 0 CACHE STRING "Intensity of testing (0 = no testing, 1 = verify and tutorials, 2 = light testing, 3 = intensive testing.") +set(EMBREE_TASKING_SYSTEM "TBB" CACHE STRING "Selects tasking system") +option(EMBREE_IGNORE_CMAKE_CXX_FLAGS "When enabled Embree ignores default CMAKE_CXX_FLAGS." OFF) + +# Set C++ namespace to ensure support for user-defined namespaces +# TODO: Not supported yet by other internal dependencies. +# set(EMBREE_API_NAMESPACE "embree" CACHE STRING "C++ namespace to put API symbols into.") + +# The following options are necessary to ensure packed-ray support +option(EMBREE_RAY_MASK "Enable the usage of mask for packed ray." ON) +option(EMBREE_RAY_PACKETS "Enable the usage packed ray." ON) + +# Match embree's platform detection logic for arm +if(APPLE AND CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" AND CMAKE_OSX_ARCHITECTURES STREQUAL "") OR ("arm64" IN_LIST CMAKE_OSX_ARCHITECTURES)) + set(EMBREE_ARM ON) +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") + set(EMBREE_ARM ON) +endif() + +if(EMSCRIPTEN) + set(EMBREE_MAX_ISA "SSE2" CACHE STRING "Selects highest ISA to support.") + set(FLAGS_SSE2 "-msse -msse2 -msimd128") # set to non-empty to prevent embree from using incorrect flags +else() + if(APPLE AND NOT EMBREE_ARM) + set(EMBREE_MAX_ISA "DEFAULT" CACHE STRING "Selects highest ISA to support.") + else() + set(EMBREE_MAX_ISA "NONE" CACHE STRING "Selects highest ISA to support.") + endif() +endif() + +# We want to compile Embree with TBB support, so we need to overwrite Embree's +# `find_package()` and provide variables. The following discussion provide some +# context on how to achieve this: +# - https://gitlab.kitware.com/cmake/cmake/issues/17735 +# - https://crascit.com/2018/09/14/do-not-redefine-cmake-commands/ +function(embree_import_target) + macro(push_variable var value) + if(DEFINED CACHE{${var}}) + set(LAGRANGE_OLD_${var}_VALUE "${${var}}") + set(LAGRANGE_OLD_${var}_TYPE CACHE_TYPE) + elseif(DEFINED ${var}) + set(LAGRANGE_OLD_${var}_VALUE "${${var}}") + set(LAGRANGE_OLD_${var}_TYPE NORMAL_TYPE) + else() + set(LAGRANGE_OLD_${var}_TYPE NONE_TYPE) + endif() + set(${var} "${value}") + endmacro() + + macro(pop_variable var) + if(LAGRANGE_OLD_${var}_TYPE STREQUAL CACHE_TYPE) + set(${var} "${LAGRANGE_OLD_${var}_VALUE}" CACHE PATH "" FORCE) + elseif(LAGRANGE_OLD_${var}_TYPE STREQUAL NORMAL_TYPE) + unset(${var} CACHE) + set(${var} "${LAGRANGE_OLD_${var}_VALUE}") + elseif(LAGRANGE_OLD_${var}_TYPE STREQUAL NONE_TYPE) + unset(${var} CACHE) + else() + message(FATAL_ERROR "Trying to pop a variable that has not been pushed: ${var}") + endif() + endmacro() + + macro(ignore_package NAME) + set(LAGRANGE_DUMMY_DIR "${CMAKE_CURRENT_BINARY_DIR}/embree_cmake/${NAME}") + file(WRITE ${LAGRANGE_DUMMY_DIR}/${NAME}Config.cmake "") + push_variable(${NAME}_DIR ${LAGRANGE_DUMMY_DIR}) + push_variable(${NAME}_ROOT ${LAGRANGE_DUMMY_DIR}) + endmacro() + + macro(unignore_package NAME) + pop_variable(${NAME}_DIR) + pop_variable(${NAME}_ROOT) + endmacro() + + # Prefer Config mode before Module mode to prevent embree from loading its own FindTBB.cmake + set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) + + # Embree wants to be able to export() its target, and expects a target named `TBB` to exist. + # Somehow we stil need to define `TBB_INCLUDE_DIRS`, and linking against `TBB` isn't sufficient + # to compile embree targets properly. + lagrange_find_package(TBB CONFIG REQUIRED) + ignore_package(TBB) + get_target_property(TBB_INCLUDE_DIRS TBB::tbb INTERFACE_INCLUDE_DIRECTORIES) + if(NOT TARGET TBB) + add_library(TBB INTERFACE) + target_link_libraries(TBB INTERFACE TBB::tbb) + endif() + set(TBB_LIBRARIES TBB) + + # Ready to include embree's atrocious CMake + include(CPM) + set(EMBREE_VERSION v4.4.0) + set(EMBREE_PATCHES "") + if(LAGRANGE_WITH_EMBREE_3) + set(CMAKE_POLICY_VERSION_MINIMUM 3.5) + set(EMBREE_VERSION v3.13.5) + # Patch for emscripten compatibility. Fix available upstream in Embree 4+. + # https://github.com/RenderKit/embree/pull/365 + # https://github.com/RenderKit/embree/issues/486 + set(EMBREE_PATCHES PATCHES embree.patch) + endif() + CPMAddPackage( + NAME embree + GITHUB_REPOSITORY RenderKit/embree + GIT_TAG ${EMBREE_VERSION} + ${EMBREE_PATCHES} + ) + + unignore_package(TBB) + + # Disable warnings + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # Embree's subgrid.h is known for causing array subscript out of bound + # warning. Embree dev claim the code is correct and it is a GCC bug + # for misfiring warnings. See https://github.com/embree/embree/issues/271 + # + # The issue should be fixed for gcc 9.2.1 and later. + target_compile_options(embree PRIVATE "-Wno-array-bounds") + endif() + + # Warning setting + set(unix_compilers "AppleClang;Clang;GNU") + if(CMAKE_CXX_COMPILER_ID IN_LIST unix_compilers) # IN_LIST wants the second arg to be a var + target_compile_options(embree PRIVATE "-Wno-unused-private-field") + target_compile_options(embree PRIVATE "-Wno-unused-but-set-variable") + endif() + + # Now we need to do some juggling to propagate the include directory properties + # along with the `embree` target + add_library(embree::embree INTERFACE IMPORTED GLOBAL) + target_include_directories(embree::embree SYSTEM INTERFACE ${embree_SOURCE_DIR}/include) + target_link_libraries(embree::embree INTERFACE embree) + + # Generate a dummy .cpp for embree's math library, to workaround a weird link issue with + # LLVM-Clang on macOS + # Generate implementation file + file(WRITE "${embree_BINARY_DIR}/embree_math_dummy.cpp.in" [[ + namespace embree { + void math_dummy() {} + } + ]]) + configure_file(${embree_BINARY_DIR}/embree_math_dummy.cpp.in ${embree_BINARY_DIR}/embree_math_dummy.cpp COPYONLY) + target_sources(math PRIVATE ${embree_BINARY_DIR}/embree_math_dummy.cpp) +endfunction() + +# Call via a proper function in order to scope variables such as CMAKE_FIND_PACKAGE_PREFER_CONFIG and TBB_DIR +embree_import_target() + +# Cleanup for IDEs +foreach(name IN ITEMS embree algorithms lexers math simd sys tasking uninstall) + if(TARGET ${name}) + set_target_properties(${name} PROPERTIES FOLDER "third_party//embree") + endif() +endforeach() diff --git a/cmake/recipes/external/embree3.patch b/cmake/recipes/external/embree.patch similarity index 100% rename from cmake/recipes/external/embree3.patch rename to cmake/recipes/external/embree.patch From be33f2e13cbfe3dcf3f6b31eda91f6d62ed67fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Mon, 4 May 2026 08:21:54 -0700 Subject: [PATCH 37/66] Testing Adobe fork for embree winarm. --- cmake/recipes/external/embree.cmake | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree.cmake index a323f51c..c66399f8 100644 --- a/cmake/recipes/external/embree.cmake +++ b/cmake/recipes/external/embree.cmake @@ -120,9 +120,14 @@ function(embree_import_target) # https://github.com/RenderKit/embree/issues/486 set(EMBREE_PATCHES PATCHES embree.patch) endif() + set(EMBREE_URL RenderKit/embree) + if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND EMBREE_VERSION STREQUAL "v4.4.0") + set(EMBREE_VERSION 03d8ec87213176a7e91c92a18d42e15a8a9bbbc8) + set(EMBREE_URL dousse-adobe/embree) + endif() CPMAddPackage( NAME embree - GITHUB_REPOSITORY RenderKit/embree + GITHUB_REPOSITORY ${EMBREE_URL} GIT_TAG ${EMBREE_VERSION} ${EMBREE_PATCHES} ) From 650921bf71a070e19fed1b03e4a4a34c314072d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Mon, 4 May 2026 08:54:19 -0700 Subject: [PATCH 38/66] Add debug message. --- cmake/recipes/external/embree.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree.cmake index c66399f8..50376be7 100644 --- a/cmake/recipes/external/embree.cmake +++ b/cmake/recipes/external/embree.cmake @@ -122,6 +122,7 @@ function(embree_import_target) endif() set(EMBREE_URL RenderKit/embree) if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND EMBREE_VERSION STREQUAL "v4.4.0") + message(STATUS "Testing winarm version of embree 4") set(EMBREE_VERSION 03d8ec87213176a7e91c92a18d42e15a8a9bbbc8) set(EMBREE_URL dousse-adobe/embree) endif() From b353250e91dc803b843e73d4753c519740ec38a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Tue, 5 May 2026 07:24:08 -0700 Subject: [PATCH 39/66] Don't set embree isa manually. --- .github/workflows/continuous.yaml | 18 ------------------ cmake/recipes/external/embree.cmake | 2 ++ 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index dd16c58a..f88adfdb 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -147,18 +147,6 @@ jobs: with: xcode-version: '26.0.1' - - name: Select embree isa (Linux) - if: runner.os == 'Linux' - run: echo "embree_max_isa=SSE2" >> $GITHUB_ENV - - - name: Select embree isa (macOS x64) - if: runner.os == 'macOS' && runner.arch == 'X64' - run: echo "embree_max_isa=DEFAULT" >> $GITHUB_ENV - - - name: Select embree isa (macOS arm64) - if: runner.os == 'macOS' && runner.arch == 'ARM64' - run: echo "embree_max_isa=NONE" >> $GITHUB_ENV - - name: Get number of CPU cores uses: SimenB/github-actions-cpu-cores@v1 id: cpu-cores @@ -175,7 +163,6 @@ jobs: -DOPENVDB_CORE_STATIC=OFF \ -DUSE_EXPLICIT_INSTANTIATION=OFF \ -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON \ - -DEMBREE_MAX_ISA=${{ env.embree_max_isa }} \ -DUSE_SANITIZER="${{ matrix.sanitizer }}" - name: Build @@ -228,10 +215,6 @@ jobs: # starving sccache of requests until the default 600s timeout kills the server. echo "SCCACHE_IDLE_TIMEOUT=0" >> ${env:GITHUB_ENV} - - name: Select embree isa (Windows) - if: runner.os == 'Windows' - run: echo "embree_max_isa=AVX2" >> ${env:GITHUB_ENV} - - name: Get number of CPU cores uses: SimenB/github-actions-cpu-cores@v1 id: cpu-cores @@ -265,7 +248,6 @@ jobs: -DLAGRANGE_JENKINS=ON ` -DLAGRANGE_ALL=ON ` -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON ` - -DEMBREE_MAX_ISA=${{ env.embree_max_isa }} ` -B ${{ env.BUILD_DIR }} ` -S . diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree.cmake index 50376be7..5646bc38 100644 --- a/cmake/recipes/external/embree.cmake +++ b/cmake/recipes/external/embree.cmake @@ -33,8 +33,10 @@ option(EMBREE_RAY_PACKETS "Enable the usage packed ray." # Match embree's platform detection logic for arm if(APPLE AND CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" AND CMAKE_OSX_ARCHITECTURES STREQUAL "") OR ("arm64" IN_LIST CMAKE_OSX_ARCHITECTURES)) + message(STATUS "Setting arm version of Embree") set(EMBREE_ARM ON) elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") + message(STATUS "Setting arm version of Embree") set(EMBREE_ARM ON) endif() From de35c0166a1d7660431cabcd38f197def06ab40d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Tue, 5 May 2026 13:16:14 -0700 Subject: [PATCH 40/66] Update gklib version. --- cmake/recipes/external/gklib.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/recipes/external/gklib.cmake b/cmake/recipes/external/gklib.cmake index d62b7ad5..3d0cfee7 100644 --- a/cmake/recipes/external/gklib.cmake +++ b/cmake/recipes/external/gklib.cmake @@ -19,7 +19,7 @@ include(CPM) CPMAddPackage( NAME gklib GITHUB_REPOSITORY KarypisLab/GKlib - GIT_TAG 67c6e4322bb326a04727995775c3eafc47d7a252 + GIT_TAG e2856c2f595b153ca1ce9258c5301dbabc4f39f5 DOWNLOAD_ONLY ON ) From 7d44b9c513ffb767935e91d111e751836f51156e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Tue, 5 May 2026 17:15:32 -0700 Subject: [PATCH 41/66] Update gklib cmake. --- cmake/recipes/external/gklib.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/recipes/external/gklib.cmake b/cmake/recipes/external/gklib.cmake index 3d0cfee7..4b9a109c 100644 --- a/cmake/recipes/external/gklib.cmake +++ b/cmake/recipes/external/gklib.cmake @@ -23,10 +23,10 @@ CPMAddPackage( DOWNLOAD_ONLY ON ) -file(GLOB INC_FILES "${gklib_SOURCE_DIR}/*.h" ) -file(GLOB SRC_FILES "${gklib_SOURCE_DIR}/*.c" ) +file(GLOB INC_FILES "${gklib_SOURCE_DIR}/include/*.h" ) +file(GLOB SRC_FILES "${gklib_SOURCE_DIR}/src/*.c" ) if(NOT MSVC) - list(REMOVE_ITEM SRC_FILES "${gklib_SOURCE_DIR}/gkregex.c") + list(REMOVE_ITEM SRC_FILES "${gklib_SOURCE_DIR}/src/gkregex.c") endif() add_library(GKlib STATIC ${INC_FILES} ${SRC_FILES}) @@ -39,7 +39,7 @@ endif() include(GNUInstallDirs) target_include_directories(GKlib SYSTEM PUBLIC - "$" + "$" "$" ) From d0e3f340ed1417355ed4f27e66da5f2d53cbc263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Tue, 5 May 2026 20:08:17 -0700 Subject: [PATCH 42/66] Restore isa selection on unix platforms. --- .github/workflows/continuous.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index f88adfdb..f802e308 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -147,6 +147,18 @@ jobs: with: xcode-version: '26.0.1' + - name: Select embree isa (Linux) + if: runner.os == 'Linux' + run: echo "embree_max_isa=SSE2" >> $GITHUB_ENV + + - name: Select embree isa (macOS x64) + if: runner.os == 'macOS' && runner.arch == 'X64' + run: echo "embree_max_isa=DEFAULT" >> $GITHUB_ENV + + - name: Select embree isa (macOS arm64) + if: runner.os == 'macOS' && runner.arch == 'ARM64' + run: echo "embree_max_isa=NONE" >> $GITHUB_ENV + - name: Get number of CPU cores uses: SimenB/github-actions-cpu-cores@v1 id: cpu-cores @@ -163,6 +175,7 @@ jobs: -DOPENVDB_CORE_STATIC=OFF \ -DUSE_EXPLICIT_INSTANTIATION=OFF \ -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON \ + -DEMBREE_MAX_ISA=${{ env.embree_max_isa }} \ -DUSE_SANITIZER="${{ matrix.sanitizer }}" - name: Build From 1933a58e94951d2974d21ae65bb73fc543eada60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Tue, 5 May 2026 22:36:17 -0700 Subject: [PATCH 43/66] Fix for winarm gklib. --- cmake/recipes/external/gklib.cmake | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cmake/recipes/external/gklib.cmake b/cmake/recipes/external/gklib.cmake index 4b9a109c..322eb070 100644 --- a/cmake/recipes/external/gklib.cmake +++ b/cmake/recipes/external/gklib.cmake @@ -35,6 +35,13 @@ add_library(GKlib::GKlib ALIAS GKlib) if(MSVC) target_compile_definitions(GKlib PUBLIC USE_GKREGEX) target_compile_definitions(GKlib PUBLIC "__thread=__declspec(thread)") + # gk_ms_stdint.h / gk_ms_inttypes.h are 2006-era polyfills for pre-VS2010 MSVC. + # Modern MSVC (VS2010+) ships natively, but on ARM64 it defines + # int_fast16_t as 'int' (32-bit) while the polyfill defines it as 'int16_t', + # causing a redefinition error. Suppress the polyfills via their include guards + # and force-include the real system header so the types are still available. + target_compile_definitions(GKlib PUBLIC _MSC_STDINT_H_ _MSC_INTTYPES_H_) + target_compile_options(GKlib PUBLIC "/FIstdint.h" "/FIinttypes.h") endif() include(GNUInstallDirs) From 95c2ad6b0fe9b9ab31dfb9a1993fa18a9cedea35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Tue, 5 May 2026 23:03:40 -0700 Subject: [PATCH 44/66] Update simde. --- cmake/recipes/external/simde.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/recipes/external/simde.cmake b/cmake/recipes/external/simde.cmake index cffa746e..fa658f06 100644 --- a/cmake/recipes/external/simde.cmake +++ b/cmake/recipes/external/simde.cmake @@ -19,7 +19,7 @@ include(CPM) CPMAddPackage( NAME simde GITHUB_REPOSITORY simd-everywhere/simde - GIT_TAG 48edfa906d835525e2061fbf6062b7c326d66840 + GIT_TAG 1747b2482589fe894d49989159421da08c2a8bcd ) add_library(simde::simde INTERFACE IMPORTED GLOBAL) From cf508503ba827bb81b6f432222ffda8a3f5623f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 07:41:25 -0700 Subject: [PATCH 45/66] Update simde. --- cmake/recipes/external/simde.cmake | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cmake/recipes/external/simde.cmake b/cmake/recipes/external/simde.cmake index fa658f06..f7e86de6 100644 --- a/cmake/recipes/external/simde.cmake +++ b/cmake/recipes/external/simde.cmake @@ -22,11 +22,8 @@ CPMAddPackage( GIT_TAG 1747b2482589fe894d49989159421da08c2a8bcd ) -add_library(simde::simde INTERFACE IMPORTED GLOBAL) -target_include_directories(simde::simde INTERFACE "${simde_SOURCE_DIR}") - # Enables native aliases. Not ideal but makes it easier to convert old code. -target_compile_definitions(simde::simde INTERFACE SIMDE_ENABLE_NATIVE_ALIASES) +target_compile_definitions(simde INTERFACE SIMDE_ENABLE_NATIVE_ALIASES) # Uncomment this line to ensure code can be compiled without native SIMD (i.e. emulates everything) -# target_compile_definitions(simde::simde INTERFACE SIMDE_NO_NATIVE) +# target_compile_definitions(simde INTERFACE SIMDE_NO_NATIVE) From 6a8ecec90e8ea4c3027d875cd405b1e72a6c1892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 11:45:06 -0700 Subject: [PATCH 46/66] Winarm patch. --- cmake/recipes/external/embree.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree.cmake index 5646bc38..d6d01927 100644 --- a/cmake/recipes/external/embree.cmake +++ b/cmake/recipes/external/embree.cmake @@ -127,6 +127,9 @@ function(embree_import_target) message(STATUS "Testing winarm version of embree 4") set(EMBREE_VERSION 03d8ec87213176a7e91c92a18d42e15a8a9bbbc8) set(EMBREE_URL dousse-adobe/embree) + # intrinsics.h guards x86 BMI/LZCNT intrinsics with !defined(__aarch64__) but misses + # _M_ARM64 (the MSVC macro for ARM64), causing build failures on Windows ARM64. + set(EMBREE_PATCHES PATCHES embree-winarm.patch) endif() CPMAddPackage( NAME embree From ca6ad6873a0de4202e7aa38778f41860de0fddce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 11:55:51 -0700 Subject: [PATCH 47/66] =?UTF-8?q?=F0=9F=90=9B=20Fix=20Windows=20ARM64=20bu?= =?UTF-8?q?ild:=20Embree=20intrinsics=20patch=20+=20SIMDe=20types?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add embree-winarm.patch: guards _tzcnt_u64, _lzcnt_u64, _pext_u32/_pdep_u32 with !defined(_M_ARM64) (MSVC ARM64 macro, missing alongside __aarch64__) - simde.cmake: disable SIMDE native NEON on MSVC ARM64 to avoid __m128/__m128i being the same underlying __n128 type, which breaks WindingNumber overloads Co-Authored-By: Claude Sonnet 4.6 --- cmake/recipes/external/embree-winarm.patch | 24 ++++++++++++++++++++++ cmake/recipes/external/simde.cmake | 9 ++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 cmake/recipes/external/embree-winarm.patch diff --git a/cmake/recipes/external/embree-winarm.patch b/cmake/recipes/external/embree-winarm.patch new file mode 100644 index 00000000..f2a534e9 --- /dev/null +++ b/cmake/recipes/external/embree-winarm.patch @@ -0,0 +1,24 @@ +diff --git i/common/sys/intrinsics.h w/common/sys/intrinsics.h +--- i/common/sys/intrinsics.h ++++ w/common/sys/intrinsics.h +@@ -91,7 +91,7 @@ + #if defined(__X86_64__) || defined (__aarch64__) || defined(_M_ARM64) + __forceinline size_t bsf(size_t v) { +-#if defined(__AVX2__) ++#if defined(__AVX2__) && !defined(_M_ARM64) + return _tzcnt_u64(v); + #else + unsigned long r = 0; _BitScanForward64(&r,v); return r; +@@ -141,7 +141,7 @@ + __forceinline size_t bsr(size_t v) { +-#if defined(__AVX2__) ++#if defined(__AVX2__) && !defined(_M_ARM64) + return 63 -_lzcnt_u64(v); + #else + unsigned long r = 0; _BitScanReverse64(&r, v); return r; +@@ -534,7 +534,7 @@ +-#if defined(__AVX2__) && !defined(__aarch64__) ++#if defined(__AVX2__) && !defined(__aarch64__) && !defined(_M_ARM64) + __forceinline unsigned int pext(unsigned int a, unsigned int b) { return _pext_u32(a, b); } + __forceinline unsigned int pdep(unsigned int a, unsigned int b) { return _pdep_u32(a, b); } + #if defined(__X86_64__) diff --git a/cmake/recipes/external/simde.cmake b/cmake/recipes/external/simde.cmake index f7e86de6..a989990b 100644 --- a/cmake/recipes/external/simde.cmake +++ b/cmake/recipes/external/simde.cmake @@ -25,5 +25,10 @@ CPMAddPackage( # Enables native aliases. Not ideal but makes it easier to convert old code. target_compile_definitions(simde INTERFACE SIMDE_ENABLE_NATIVE_ALIASES) -# Uncomment this line to ensure code can be compiled without native SIMD (i.e. emulates everything) -# target_compile_definitions(simde INTERFACE SIMDE_NO_NATIVE) +# On MSVC ARM64, all NEON vector types (float32x4_t, int64x2_t, ...) are typedefs of the same +# __n128 type, so simde__m128 and simde__m128i would be identical to the type system. This breaks +# code that overloads on __m128 vs __m128i (e.g. WindingNumber's VM_SSEFunc.h). Disabling native +# NEON forces SIMDe to use its own distinct union types instead. +if(MSVC AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") + target_compile_definitions(simde INTERFACE SIMDE_NO_NATIVE) +endif() From f92d2f8e2b001ea1844fa3b8f6c003c738453ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 12:12:07 -0700 Subject: [PATCH 48/66] =?UTF-8?q?=F0=9F=90=9B=20Fix=20embree-winarm.patch?= =?UTF-8?q?=20hunk=20line=20counts=20for=20strict=20patch.exe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- cmake/recipes/external/embree-winarm.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/recipes/external/embree-winarm.patch b/cmake/recipes/external/embree-winarm.patch index f2a534e9..cba735a0 100644 --- a/cmake/recipes/external/embree-winarm.patch +++ b/cmake/recipes/external/embree-winarm.patch @@ -1,7 +1,7 @@ diff --git i/common/sys/intrinsics.h w/common/sys/intrinsics.h --- i/common/sys/intrinsics.h +++ w/common/sys/intrinsics.h -@@ -91,7 +91,7 @@ +@@ -91,6 +91,6 @@ #if defined(__X86_64__) || defined (__aarch64__) || defined(_M_ARM64) __forceinline size_t bsf(size_t v) { -#if defined(__AVX2__) @@ -9,14 +9,14 @@ diff --git i/common/sys/intrinsics.h w/common/sys/intrinsics.h return _tzcnt_u64(v); #else unsigned long r = 0; _BitScanForward64(&r,v); return r; -@@ -141,7 +141,7 @@ +@@ -141,5 +141,5 @@ __forceinline size_t bsr(size_t v) { -#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(_M_ARM64) return 63 -_lzcnt_u64(v); #else unsigned long r = 0; _BitScanReverse64(&r, v); return r; -@@ -534,7 +534,7 @@ +@@ -534,4 +534,4 @@ -#if defined(__AVX2__) && !defined(__aarch64__) +#if defined(__AVX2__) && !defined(__aarch64__) && !defined(_M_ARM64) __forceinline unsigned int pext(unsigned int a, unsigned int b) { return _pext_u32(a, b); } From 645a118fd59c513cc412f42492301aa60835052b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 12:29:01 -0700 Subject: [PATCH 49/66] =?UTF-8?q?=F0=9F=90=9B=20Replace=20patch-file=20app?= =?UTF-8?q?roach=20with=20CMake=20string=20replacement=20for=20embree=20AR?= =?UTF-8?q?M64=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Strawberry patch.exe is strict about hunk line counts and running offsets, causing hunk 3 to search at the wrong line. Use file(READ)+string(REGEX REPLACE)+file(WRITE) instead to apply _M_ARM64 guards in intrinsics.h. Co-Authored-By: Claude Sonnet 4.6 --- cmake/recipes/external/embree.cmake | 32 ++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree.cmake index d6d01927..16a587ba 100644 --- a/cmake/recipes/external/embree.cmake +++ b/cmake/recipes/external/embree.cmake @@ -127,9 +127,6 @@ function(embree_import_target) message(STATUS "Testing winarm version of embree 4") set(EMBREE_VERSION 03d8ec87213176a7e91c92a18d42e15a8a9bbbc8) set(EMBREE_URL dousse-adobe/embree) - # intrinsics.h guards x86 BMI/LZCNT intrinsics with !defined(__aarch64__) but misses - # _M_ARM64 (the MSVC macro for ARM64), causing build failures on Windows ARM64. - set(EMBREE_PATCHES PATCHES embree-winarm.patch) endif() CPMAddPackage( NAME embree @@ -138,6 +135,35 @@ function(embree_import_target) ${EMBREE_PATCHES} ) + # Fix intrinsics.h for MSVC ARM64: the dousse-adobe fork defines __AVX2__ on ARM64 to trigger + # SIMDe, but uses !defined(__aarch64__) (GCC/Clang) instead of !defined(_M_ARM64) (MSVC) to + # guard x86 BMI/LZCNT/PEXT intrinsics, causing build failures. We apply this fix via CMake + # string replacement rather than a patch file to avoid dependency on Strawberry's patch.exe, + # which is strict about unified-diff line counts and offsets. + if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND DEFINED embree_SOURCE_DIR) + set(_intrinsics "${embree_SOURCE_DIR}/common/sys/intrinsics.h") + if(EXISTS "${_intrinsics}") + file(READ "${_intrinsics}" _content) + string(ASCII 13 _cr) + string(ASCII 10 _lf) + # Two bsf/bsr instances end with a trailing space before the newline. + string(REGEX REPLACE + "#if defined\\(__AVX2__\\) ([${_cr}${_lf}])" + "#if defined(__AVX2__) && !defined(_M_ARM64)\\1" + _content "${_content}") + # pext/pdep instance uses the __aarch64__ guard without the trailing space. + string(REPLACE + "#if defined(__AVX2__) && !defined(__aarch64__)" + "#if defined(__AVX2__) && !defined(__aarch64__) && !defined(_M_ARM64)" + _content "${_content}") + file(WRITE "${_intrinsics}" "${_content}") + unset(_content) + endif() + unset(_intrinsics) + unset(_cr) + unset(_lf) + endif() + unignore_package(TBB) # Disable warnings From 2b4ca1ebbabdd65400d310adf632e4cf23166cc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 13:34:58 -0700 Subject: [PATCH 50/66] =?UTF-8?q?=F0=9F=90=9B=20Disable=20Python=20binding?= =?UTF-8?q?s=20on=20Windows=20ARM64=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ARM64 Python on GitHub Actions hostedtoolcache lacks development files (headers + import lib). CMake falls back to x64 Python's Development.Module, but MSVC in ARM64 mode cannot link against the x64 python313.lib, producing hundreds of unresolved __imp_Py* linker errors. Fix: split the Windows configure step to pass -DLAGRANGE_MODULE_PYTHON=OFF for windows-11-arm, and update CMakeLists.txt to honor an explicit -DLAGRANGE_MODULE_PYTHON=OFF even when LAGRANGE_ALL=ON. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/continuous.yaml | 17 +++++++++++++++++ CMakeLists.txt | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index f802e308..7eed5845 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -254,6 +254,7 @@ jobs: # Cmd uses ^ to break commands into multiple lines, powershell uses ` - name: Configure + if: matrix.os != 'windows-11-arm' run: | cmake --version cmake -G Ninja ` @@ -264,6 +265,22 @@ jobs: -B ${{ env.BUILD_DIR }} ` -S . + # Python bindings are disabled on ARM64: the hostedtoolcache ARM64 Python lacks + # development files, causing CMake to fall back to x64 Python headers that the + # ARM64 MSVC toolchain cannot link against. + - name: Configure (ARM64) + if: matrix.os == 'windows-11-arm' + run: | + cmake --version + cmake -G Ninja ` + -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` + -DLAGRANGE_JENKINS=ON ` + -DLAGRANGE_ALL=ON ` + -DLAGRANGE_MODULE_PYTHON=OFF ` + -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON ` + -B ${{ env.BUILD_DIR }} ` + -S . + - name: Build run: cmake --build ${{ env.BUILD_DIR }} -j ${{ steps.cpu-cores.outputs.count }} diff --git a/CMakeLists.txt b/CMakeLists.txt index c34b82cc..81361c2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -269,8 +269,8 @@ if(BUILD_SHARED_LIBS) ) endif() -# Force LAGRANGE_MODULE_PYTHON when LAGRANGE_ALL is set -if(LAGRANGE_ALL) +# Force LAGRANGE_MODULE_PYTHON when LAGRANGE_ALL is set (unless explicitly disabled via -D) +if(LAGRANGE_ALL AND NOT (DEFINED CACHE{LAGRANGE_MODULE_PYTHON} AND NOT LAGRANGE_MODULE_PYTHON)) set(LAGRANGE_MODULE_PYTHON ON) endif() From 41a38ab1254a7b6d08bdbd842a9a9a5c910c56ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 14:38:59 -0700 Subject: [PATCH 51/66] =?UTF-8?q?=F0=9F=90=9B=20Allow=20-DLAGRANGE=5FMODUL?= =?UTF-8?q?E=5FX=3DOFF=20to=20override=20LAGRANGE=5FALL=3DON?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The module-inclusion loop unconditionally honored LAGRANGE_ALL, so passing -DLAGRANGE_MODULE_PYTHON=OFF together with -DLAGRANGE_ALL=ON still pulled modules/python into the build. Capture the cache state before option() materializes the default value, then skip modules the user explicitly disabled even when LAGRANGE_ALL is set. Co-Authored-By: Claude Sonnet 4.6 --- modules/CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 6aeda78e..56c1ae65 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -48,6 +48,14 @@ foreach(name IN ITEMS ${module_names}) string(TOUPPER ${name} MODULE_FLAG) set(MODULE_OPTION LAGRANGE_MODULE_${MODULE_FLAG}) + # Capture whether the user explicitly disabled this module before option() materializes + # the cache variable (the default-OFF cache value would otherwise be indistinguishable + # from an explicit -DLAGRANGE_MODULE_X=OFF on the command line). + set(_user_disabled_module FALSE) + if(DEFINED CACHE{${MODULE_OPTION}} AND NOT ${${MODULE_OPTION}}) + set(_user_disabled_module TRUE) + endif() + # Allows setting the option option(${MODULE_OPTION} "Build module lagrange::${name}" OFF) @@ -61,7 +69,7 @@ foreach(name IN ITEMS ${module_names}) "Please use the helper function lagrange_include_modules() instead.") endif() - if(${MODULE_OPTION} OR LAGRANGE_ALL) + if(${MODULE_OPTION} OR (LAGRANGE_ALL AND NOT _user_disabled_module)) lagrange_include_modules(${name}) endif() endforeach() From 7ca8b10babcb551f94bfb3a076a469a5d52a88bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 14:48:23 -0700 Subject: [PATCH 52/66] =?UTF-8?q?=F0=9F=90=9B=20Fix=20Python=20bindings=20?= =?UTF-8?q?on=20Windows=20ARM64=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of disabling Python, install the ARM64 Python with its full development files by passing architecture: arm64 to setup-python. Without this, setup-python only installs the ARM64 interpreter (no python313.lib or headers), causing CMake FindPython to fall back to the x64 Python for Development.Module -- which the ARM64 MSVC toolchain cannot link against. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/continuous.yaml | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 7eed5845..33838785 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -215,9 +215,20 @@ jobs: fetch-depth: 0 - uses: actions/setup-python@v5 + if: matrix.os != 'windows-11-arm' with: python-version: 3.13 + # Explicitly request arm64 architecture so that the Python dev files + # (headers + python313.lib) are installed for ARM64, not just the interpreter. + # Without this, CMake falls back to the x64 Python for Development.Module, + # which the ARM64 MSVC toolchain cannot link against. + - uses: actions/setup-python@v5 + if: matrix.os == 'windows-11-arm' + with: + python-version: 3.13 + architecture: arm64 + - name: Install Ninja uses: seanmiddleditch/gha-setup-ninja@master @@ -254,29 +265,12 @@ jobs: # Cmd uses ^ to break commands into multiple lines, powershell uses ` - name: Configure - if: matrix.os != 'windows-11-arm' - run: | - cmake --version - cmake -G Ninja ` - -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` - -DLAGRANGE_JENKINS=ON ` - -DLAGRANGE_ALL=ON ` - -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON ` - -B ${{ env.BUILD_DIR }} ` - -S . - - # Python bindings are disabled on ARM64: the hostedtoolcache ARM64 Python lacks - # development files, causing CMake to fall back to x64 Python headers that the - # ARM64 MSVC toolchain cannot link against. - - name: Configure (ARM64) - if: matrix.os == 'windows-11-arm' run: | cmake --version cmake -G Ninja ` -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` -DLAGRANGE_JENKINS=ON ` -DLAGRANGE_ALL=ON ` - -DLAGRANGE_MODULE_PYTHON=OFF ` -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON ` -B ${{ env.BUILD_DIR }} ` -S . From 5bd94896f82b46713c87716a1aa4eceb4bedb7c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 16:02:13 -0700 Subject: [PATCH 53/66] =?UTF-8?q?=F0=9F=90=9B=20Fix=20Python=20bindings=20?= =?UTF-8?q?on=20Windows=20ARM64=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The windows-11-arm hostedtoolcache Python only ships the interpreter; it lacks python3XX.lib and headers needed for extension module linking. After MSVC dev-cmd setup, synthesize the ARM64 import library from the ARM64 python3XX.dll using lib.exe /DEF /MACHINE:ARM64, and copy the architecture-neutral headers from the x64 Python install if absent. Then pass -DPython_EXECUTABLE and -DPython_FIND_REGISTRY=NEVER to CMake so FindPython uses the now-complete ARM64 Python rather than falling back to the x64 install (which the ARM64 MSVC toolchain cannot link). Co-Authored-By: Claude Opus 4.7 --- .github/workflows/continuous.yaml | 62 +++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 33838785..327ea64e 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -263,8 +263,68 @@ jobs: with: arch: ${{ env.ARCH }} + # The windows-11-arm hostedtoolcache Python ships only the interpreter; it lacks + # python3XX.lib and headers. We synthesize the import library from the ARM64 DLL + # using MSVC lib.exe (available after msvc-dev-cmd), and copy arch-neutral headers + # from the x64 Python if the arm64 install doesn't have them. + - name: Fix Python ARM64 development files + if: matrix.os == 'windows-11-arm' + shell: pwsh + run: | + $pyDir = $env:pythonLocation + + # Locate the Python DLL (e.g. python313.dll) + $dll = Get-ChildItem -Path $pyDir -Filter "python3*.dll" | Select-Object -First 1 + if (-not $dll) { Write-Error "No python3*.dll in $pyDir"; exit 1 } + $dllBase = $dll.BaseName + + # Generate ARM64 import library if missing + $libsDir = Join-Path $pyDir "libs" + $libFile = Join-Path $libsDir "$dllBase.lib" + if (-not (Test-Path $libFile)) { + New-Item -ItemType Directory -Force -Path $libsDir | Out-Null + $raw = & dumpbin /EXPORTS $dll.FullName 2>&1 + $exports = $raw | Where-Object { $_ -match '^\s+\d+\s+[0-9A-F]+\s+[0-9A-F]+\s+\w' } | + ForEach-Object { if ($_ -match '^\s+\d+\s+[0-9A-F]+\s+[0-9A-F]+\s+(\S+)') { $Matches[1] } } + $defPath = "$env:TEMP\$dllBase.def" + @("LIBRARY $dllBase", "EXPORTS") + $exports | Set-Content $defPath -Encoding ASCII + & lib /DEF:$defPath /MACHINE:ARM64 /OUT:$libFile + if ($LASTEXITCODE -ne 0) { Write-Error "lib.exe failed"; exit 1 } + Write-Host "Generated $libFile" + } else { Write-Host "$libFile already present" } + + # Ensure Python headers exist (they are architecture-neutral) + $includeDir = Join-Path $pyDir "include" + if (-not (Test-Path $includeDir)) { + $ver = Split-Path (Split-Path $pyDir -Parent) -Leaf + $x64Include = "C:\hostedtoolcache\windows\Python\$ver\x64\include" + if (Test-Path $x64Include) { + Copy-Item -Recurse $x64Include $includeDir + Write-Host "Copied headers from x64 to $includeDir" + } else { Write-Error "No Python headers found at $x64Include"; exit 1 } + } else { Write-Host "Headers already present at $includeDir" } + + # Expose the ARM64 Python executable path for the CMake configure step + $exePath = (Join-Path $pyDir "python.exe") -replace "\\", "/" + echo "PYTHON_ARM64_EXE=$exePath" >> $env:GITHUB_ENV + # Cmd uses ^ to break commands into multiple lines, powershell uses ` - name: Configure + if: matrix.os != 'windows-11-arm' + run: | + cmake --version + cmake -G Ninja ` + -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` + -DLAGRANGE_JENKINS=ON ` + -DLAGRANGE_ALL=ON ` + -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON ` + -B ${{ env.BUILD_DIR }} ` + -S . + + # Force CMake to use the ARM64 Python (now complete with dev files) + # and skip the Windows registry so it doesn't fall back to x64 Python. + - name: Configure (ARM64) + if: matrix.os == 'windows-11-arm' run: | cmake --version cmake -G Ninja ` @@ -272,6 +332,8 @@ jobs: -DLAGRANGE_JENKINS=ON ` -DLAGRANGE_ALL=ON ` -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON ` + -DPython_EXECUTABLE="$env:PYTHON_ARM64_EXE" ` + -DPython_FIND_REGISTRY=NEVER ` -B ${{ env.BUILD_DIR }} ` -S . From 7dd8ddbd5c93e81869c0029b28b3bc0f57852a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 16:16:10 -0700 Subject: [PATCH 54/66] =?UTF-8?q?=F0=9F=90=9B=20Fix=20Python=20bindings=20?= =?UTF-8?q?on=20Windows=20ARM64=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The windows-11-arm hostedtoolcache Python ships only the interpreter binary — no include/ headers and no libs/python3XX.lib — so CMake's FindPython falls back to x64 Python for Development.Module, which the ARM64 MSVC toolchain cannot link against. Use astral-sh/setup-uv + uv python install to pull a python-build-standalone distribution instead. These distributions include full dev files. uv intentionally defaults to x64-emulated Python on Windows ARM64 runners (uv PR #13724), so we pin the cpython-3.13-windows-aarch64 specifier to get the native build. Pass -DPython_EXECUTABLE and -DPython_FIND_REGISTRY=NEVER to CMake so FindPython uses the uv-managed ARM64 Python and does not fall back to the registry-registered x64 Python. Co-Authored-By: Claude Opus 4.7 --- .github/workflows/continuous.yaml | 67 +++++++------------------------ 1 file changed, 14 insertions(+), 53 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 327ea64e..504829ae 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -219,15 +219,21 @@ jobs: with: python-version: 3.13 - # Explicitly request arm64 architecture so that the Python dev files - # (headers + python313.lib) are installed for ARM64, not just the interpreter. - # Without this, CMake falls back to the x64 Python for Development.Module, - # which the ARM64 MSVC toolchain cannot link against. - - uses: actions/setup-python@v5 + # On windows-11-arm the hostedtoolcache Python ships only the interpreter binary; + # it lacks include/ headers and libs/python3XX.lib, so CMake cannot satisfy the + # Development.Module component. Use uv instead: it pulls python-build-standalone + # distributions which include full dev files. uv defaults to x64-emulated Python + # on ARM64 Windows (uv PR #13724), so we must pin the aarch64 specifier. + - uses: astral-sh/setup-uv@v6 if: matrix.os == 'windows-11-arm' - with: - python-version: 3.13 - architecture: arm64 + + - name: Install native ARM64 Python via uv + if: matrix.os == 'windows-11-arm' + shell: pwsh + run: | + uv python install cpython-3.13-windows-aarch64 + $pyExe = (uv python find cpython-3.13-windows-aarch64).Trim() + echo "PYTHON_ARM64_EXE=$($pyExe -replace '\\', '/')" >> $env:GITHUB_ENV - name: Install Ninja uses: seanmiddleditch/gha-setup-ninja@master @@ -263,51 +269,6 @@ jobs: with: arch: ${{ env.ARCH }} - # The windows-11-arm hostedtoolcache Python ships only the interpreter; it lacks - # python3XX.lib and headers. We synthesize the import library from the ARM64 DLL - # using MSVC lib.exe (available after msvc-dev-cmd), and copy arch-neutral headers - # from the x64 Python if the arm64 install doesn't have them. - - name: Fix Python ARM64 development files - if: matrix.os == 'windows-11-arm' - shell: pwsh - run: | - $pyDir = $env:pythonLocation - - # Locate the Python DLL (e.g. python313.dll) - $dll = Get-ChildItem -Path $pyDir -Filter "python3*.dll" | Select-Object -First 1 - if (-not $dll) { Write-Error "No python3*.dll in $pyDir"; exit 1 } - $dllBase = $dll.BaseName - - # Generate ARM64 import library if missing - $libsDir = Join-Path $pyDir "libs" - $libFile = Join-Path $libsDir "$dllBase.lib" - if (-not (Test-Path $libFile)) { - New-Item -ItemType Directory -Force -Path $libsDir | Out-Null - $raw = & dumpbin /EXPORTS $dll.FullName 2>&1 - $exports = $raw | Where-Object { $_ -match '^\s+\d+\s+[0-9A-F]+\s+[0-9A-F]+\s+\w' } | - ForEach-Object { if ($_ -match '^\s+\d+\s+[0-9A-F]+\s+[0-9A-F]+\s+(\S+)') { $Matches[1] } } - $defPath = "$env:TEMP\$dllBase.def" - @("LIBRARY $dllBase", "EXPORTS") + $exports | Set-Content $defPath -Encoding ASCII - & lib /DEF:$defPath /MACHINE:ARM64 /OUT:$libFile - if ($LASTEXITCODE -ne 0) { Write-Error "lib.exe failed"; exit 1 } - Write-Host "Generated $libFile" - } else { Write-Host "$libFile already present" } - - # Ensure Python headers exist (they are architecture-neutral) - $includeDir = Join-Path $pyDir "include" - if (-not (Test-Path $includeDir)) { - $ver = Split-Path (Split-Path $pyDir -Parent) -Leaf - $x64Include = "C:\hostedtoolcache\windows\Python\$ver\x64\include" - if (Test-Path $x64Include) { - Copy-Item -Recurse $x64Include $includeDir - Write-Host "Copied headers from x64 to $includeDir" - } else { Write-Error "No Python headers found at $x64Include"; exit 1 } - } else { Write-Host "Headers already present at $includeDir" } - - # Expose the ARM64 Python executable path for the CMake configure step - $exePath = (Join-Path $pyDir "python.exe") -replace "\\", "/" - echo "PYTHON_ARM64_EXE=$exePath" >> $env:GITHUB_ENV - # Cmd uses ^ to break commands into multiple lines, powershell uses ` - name: Configure if: matrix.os != 'windows-11-arm' From 2f03d2d71bf4b2fba612d04e8647869ddf6e62f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 17:23:23 -0700 Subject: [PATCH 55/66] =?UTF-8?q?=F0=9F=90=9B=20Use=20Eigen=20solver=20on?= =?UTF-8?q?=20Windows=20ARM64=20(no=20MKL=20support)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intel MKL has no Windows ARM64 support — skip MKL/BLAS setup on that platform. DirectSolver.h already falls back to Eigen::SimplicialLDLT when LA_SOLVER_MKL is not defined, so no header changes are needed. Co-Authored-By: Claude Opus 4.7 --- modules/solver/CMakeLists.txt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/modules/solver/CMakeLists.txt b/modules/solver/CMakeLists.txt index f7a2dd56..8c6a65e1 100644 --- a/modules/solver/CMakeLists.txt +++ b/modules/solver/CMakeLists.txt @@ -21,13 +21,17 @@ if(NOT EMSCRIPTEN AND (NOT LAGRANGE_NO_INTERNAL OR NOT SKBUILD)) # Note: For now we avoid using MKL in our open-source Python bindings, to avoid bloating up the size of # the uploaded wheels. The long-term solution is to depend on the PyPI package for MKL at build-time. - include(blas) # Accelerate on macOS, MKL on other platforms - if(APPLE) - target_compile_definitions(lagrange_solver INTERFACE LA_SOLVER_ACCELERATE) - else() - target_compile_definitions(lagrange_solver INTERFACE LA_SOLVER_MKL) + # Intel MKL has no Windows ARM64 support; fall back to Eigen's SimplicialLDLT on that platform + # (DirectSolver.h uses SimplicialLDLT when LA_SOLVER_MKL is not defined). + if(NOT (WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64")) + include(blas) # Accelerate on macOS, MKL on other platforms + if(APPLE) + target_compile_definitions(lagrange_solver INTERFACE LA_SOLVER_ACCELERATE) + else() + target_compile_definitions(lagrange_solver INTERFACE LA_SOLVER_MKL) + endif() + target_link_libraries(lagrange_solver INTERFACE BLAS::BLAS) endif() - target_link_libraries(lagrange_solver INTERFACE BLAS::BLAS) endif() if(USE_SANITIZER MATCHES "([Tt]hread)") From 5d520a30e1b4a6d0329a541b89627c02fda6ead7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 19:01:21 -0700 Subject: [PATCH 56/66] =?UTF-8?q?=F0=9F=8E=A8=20Cleanup=20WinARM=20fixes:?= =?UTF-8?q?=20proper=20patches,=20no=20hacks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - modules/CMakeLists.txt: revert _user_disabled_module mechanism; the Eigen solver fix means no modules need explicit ARM64 exclusions - CMakeLists.txt: revert LAGRANGE_MODULE_PYTHON guard back to the simple LAGRANGE_ALL check (same motivation) - embree.cmake: replace string(REPLACE) hack with git apply on a corrected embree-winarm.patch (fixed hunk offsets 91→92, 141→142); use --ignore-whitespace to handle CRLF from git-cloned sources on Windows - simde.cmake: remove global SIMDE_NO_NATIVE for MSVC ARM64; the issue was specific to WindingNumber, not all simde consumers - winding_number.cmake + winding-number-winarm.patch: fix VM_SSEFunc.h at source level — on MSVC ARM64, simde__m128 and simde__m128i are both __n128, making plain typedefs identical and breaking all overloaded functions (vm_shuffle, vm_extract, vm_v4sf/vm_v4si). Replace typedefs with distinct wrapper structs that carry implicit conversions, and guard the union-based MSVC cast functions with !defined(_M_ARM64) Co-Authored-By: Claude Opus 4.7 --- CMakeLists.txt | 4 +- cmake/recipes/external/embree-winarm.patch | 8 ++-- cmake/recipes/external/embree.cmake | 36 ++++------------ cmake/recipes/external/simde.cmake | 8 ---- .../external/winding-number-winarm.patch | 42 +++++++++++++++++++ cmake/recipes/external/winding_number.cmake | 10 +++++ modules/CMakeLists.txt | 10 +---- 7 files changed, 66 insertions(+), 52 deletions(-) create mode 100644 cmake/recipes/external/winding-number-winarm.patch diff --git a/CMakeLists.txt b/CMakeLists.txt index 81361c2b..c34b82cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -269,8 +269,8 @@ if(BUILD_SHARED_LIBS) ) endif() -# Force LAGRANGE_MODULE_PYTHON when LAGRANGE_ALL is set (unless explicitly disabled via -D) -if(LAGRANGE_ALL AND NOT (DEFINED CACHE{LAGRANGE_MODULE_PYTHON} AND NOT LAGRANGE_MODULE_PYTHON)) +# Force LAGRANGE_MODULE_PYTHON when LAGRANGE_ALL is set +if(LAGRANGE_ALL) set(LAGRANGE_MODULE_PYTHON ON) endif() diff --git a/cmake/recipes/external/embree-winarm.patch b/cmake/recipes/external/embree-winarm.patch index cba735a0..5357af1a 100644 --- a/cmake/recipes/external/embree-winarm.patch +++ b/cmake/recipes/external/embree-winarm.patch @@ -1,17 +1,17 @@ diff --git i/common/sys/intrinsics.h w/common/sys/intrinsics.h --- i/common/sys/intrinsics.h +++ w/common/sys/intrinsics.h -@@ -91,6 +91,6 @@ +@@ -92,6 +92,6 @@ #if defined(__X86_64__) || defined (__aarch64__) || defined(_M_ARM64) __forceinline size_t bsf(size_t v) { --#if defined(__AVX2__) +-#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(_M_ARM64) return _tzcnt_u64(v); #else unsigned long r = 0; _BitScanForward64(&r,v); return r; -@@ -141,5 +141,5 @@ +@@ -142,5 +142,5 @@ __forceinline size_t bsr(size_t v) { --#if defined(__AVX2__) +-#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(_M_ARM64) return 63 -_lzcnt_u64(v); #else diff --git a/cmake/recipes/external/embree.cmake b/cmake/recipes/external/embree.cmake index 16a587ba..129c9b90 100644 --- a/cmake/recipes/external/embree.cmake +++ b/cmake/recipes/external/embree.cmake @@ -127,6 +127,13 @@ function(embree_import_target) message(STATUS "Testing winarm version of embree 4") set(EMBREE_VERSION 03d8ec87213176a7e91c92a18d42e15a8a9bbbc8) set(EMBREE_URL dousse-adobe/embree) + # The dousse-adobe fork guards x86 BMI/LZCNT/PEXT intrinsics with !defined(__aarch64__) + # (GCC/Clang macro) but misses _M_ARM64 (MSVC macro), causing build failures on Windows + # ARM64. We use git apply --ignore-whitespace instead of CPM's PATCHES (patch -p1) because + # git-cloned files may have CRLF line endings on Windows, which confuses patch.exe. + find_package(Git REQUIRED QUIET) + set(EMBREE_ARM64_PATCH "${CMAKE_CURRENT_LIST_DIR}/embree-winarm.patch") + set(EMBREE_PATCHES PATCH_COMMAND "${GIT_EXECUTABLE}" apply --ignore-whitespace "${EMBREE_ARM64_PATCH}") endif() CPMAddPackage( NAME embree @@ -135,35 +142,6 @@ function(embree_import_target) ${EMBREE_PATCHES} ) - # Fix intrinsics.h for MSVC ARM64: the dousse-adobe fork defines __AVX2__ on ARM64 to trigger - # SIMDe, but uses !defined(__aarch64__) (GCC/Clang) instead of !defined(_M_ARM64) (MSVC) to - # guard x86 BMI/LZCNT/PEXT intrinsics, causing build failures. We apply this fix via CMake - # string replacement rather than a patch file to avoid dependency on Strawberry's patch.exe, - # which is strict about unified-diff line counts and offsets. - if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND DEFINED embree_SOURCE_DIR) - set(_intrinsics "${embree_SOURCE_DIR}/common/sys/intrinsics.h") - if(EXISTS "${_intrinsics}") - file(READ "${_intrinsics}" _content) - string(ASCII 13 _cr) - string(ASCII 10 _lf) - # Two bsf/bsr instances end with a trailing space before the newline. - string(REGEX REPLACE - "#if defined\\(__AVX2__\\) ([${_cr}${_lf}])" - "#if defined(__AVX2__) && !defined(_M_ARM64)\\1" - _content "${_content}") - # pext/pdep instance uses the __aarch64__ guard without the trailing space. - string(REPLACE - "#if defined(__AVX2__) && !defined(__aarch64__)" - "#if defined(__AVX2__) && !defined(__aarch64__) && !defined(_M_ARM64)" - _content "${_content}") - file(WRITE "${_intrinsics}" "${_content}") - unset(_content) - endif() - unset(_intrinsics) - unset(_cr) - unset(_lf) - endif() - unignore_package(TBB) # Disable warnings diff --git a/cmake/recipes/external/simde.cmake b/cmake/recipes/external/simde.cmake index a989990b..9a5f6cae 100644 --- a/cmake/recipes/external/simde.cmake +++ b/cmake/recipes/external/simde.cmake @@ -24,11 +24,3 @@ CPMAddPackage( # Enables native aliases. Not ideal but makes it easier to convert old code. target_compile_definitions(simde INTERFACE SIMDE_ENABLE_NATIVE_ALIASES) - -# On MSVC ARM64, all NEON vector types (float32x4_t, int64x2_t, ...) are typedefs of the same -# __n128 type, so simde__m128 and simde__m128i would be identical to the type system. This breaks -# code that overloads on __m128 vs __m128i (e.g. WindingNumber's VM_SSEFunc.h). Disabling native -# NEON forces SIMDe to use its own distinct union types instead. -if(MSVC AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") - target_compile_definitions(simde INTERFACE SIMDE_NO_NATIVE) -endif() diff --git a/cmake/recipes/external/winding-number-winarm.patch b/cmake/recipes/external/winding-number-winarm.patch new file mode 100644 index 00000000..50099b2d --- /dev/null +++ b/cmake/recipes/external/winding-number-winarm.patch @@ -0,0 +1,42 @@ +diff --git i/VM_SSEFunc.h w/VM_SSEFunc.h +--- i/VM_SSEFunc.h ++++ w/VM_SSEFunc.h +@@ -39,8 +39,26 @@ + #include + #include + +-typedef simde__m128 v4sf; +-typedef simde__m128i v4si; ++#if defined(_MSC_VER) && defined(_M_ARM64) ++// On MSVC ARM64, simde__m128 and simde__m128i are both __n128 (the native NEON type). ++// Plain typedefs make v4sf==v4si, breaking all overloaded functions (vm_shuffle, vm_extract, ++// etc.). Use distinct wrapper structs with implicit conversions to/from the simde types. ++struct v4sf { ++ simde__m128 _v; ++ v4sf() = default; ++ SYS_FORCE_INLINE v4sf(simde__m128 v) noexcept : _v(v) {} ++ SYS_FORCE_INLINE operator simde__m128() const noexcept { return _v; } ++}; ++struct v4si { ++ simde__m128i _v; ++ v4si() = default; ++ SYS_FORCE_INLINE v4si(simde__m128i v) noexcept : _v(v) {} ++ SYS_FORCE_INLINE operator simde__m128i() const noexcept { return _v; } ++}; ++#else ++typedef simde__m128 v4sf; ++typedef simde__m128i v4si; ++#endif + + #define CPU_HAS_SIMD_INSTR 1 + #define VM_SSE_STYLE 1 +@@ -59,7 +77,7 @@ + // Plain casting (no conversion) + // MSVC has problems casting between __m128 and __m128i, so we implement a + // custom casting routine specifically for windows. + +-#if defined(_MSC_VER) ++#if defined(_MSC_VER) && !defined(_M_ARM64) + + static SYS_FORCE_INLINE v4sf + vm_v4sf(const v4si &a) diff --git a/cmake/recipes/external/winding_number.cmake b/cmake/recipes/external/winding_number.cmake index 970709f4..7e703d4c 100644 --- a/cmake/recipes/external/winding_number.cmake +++ b/cmake/recipes/external/winding_number.cmake @@ -19,10 +19,20 @@ lagrange_find_package(TBB CONFIG REQUIRED) include(simde) include(CPM) +set(WINDINGNUMBER_PATCHES "") +if(MSVC AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") + # On MSVC ARM64, simde__m128 and simde__m128i are both __n128, making plain typedefs + # identical and breaking all overloaded functions. Patch VM_SSEFunc.h to use distinct + # wrapper structs instead. Use git apply --ignore-whitespace for robust CRLF handling. + find_package(Git REQUIRED QUIET) + set(_wn_patch "${CMAKE_CURRENT_LIST_DIR}/winding-number-winarm.patch") + set(WINDINGNUMBER_PATCHES PATCH_COMMAND "${GIT_EXECUTABLE}" apply --ignore-whitespace "${_wn_patch}") +endif() CPMAddPackage( NAME WindingNumber GITHUB_REPOSITORY jdumas/WindingNumber GIT_TAG a48b8f555b490afe7aab9159c7daaf83fa2cdf8e + ${WINDINGNUMBER_PATCHES} ) set_target_properties(WindingNumber PROPERTIES FOLDER third_party) diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 56c1ae65..6aeda78e 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -48,14 +48,6 @@ foreach(name IN ITEMS ${module_names}) string(TOUPPER ${name} MODULE_FLAG) set(MODULE_OPTION LAGRANGE_MODULE_${MODULE_FLAG}) - # Capture whether the user explicitly disabled this module before option() materializes - # the cache variable (the default-OFF cache value would otherwise be indistinguishable - # from an explicit -DLAGRANGE_MODULE_X=OFF on the command line). - set(_user_disabled_module FALSE) - if(DEFINED CACHE{${MODULE_OPTION}} AND NOT ${${MODULE_OPTION}}) - set(_user_disabled_module TRUE) - endif() - # Allows setting the option option(${MODULE_OPTION} "Build module lagrange::${name}" OFF) @@ -69,7 +61,7 @@ foreach(name IN ITEMS ${module_names}) "Please use the helper function lagrange_include_modules() instead.") endif() - if(${MODULE_OPTION} OR (LAGRANGE_ALL AND NOT _user_disabled_module)) + if(${MODULE_OPTION} OR LAGRANGE_ALL) lagrange_include_modules(${name}) endif() endforeach() From 286cc6619852a6725d0d3acc9712bcee6f799a30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Wed, 6 May 2026 19:28:28 -0700 Subject: [PATCH 57/66] =?UTF-8?q?=F0=9F=90=9B=20Fix=20embree-winarm.patch?= =?UTF-8?q?=20minus=20lines=20to=20match=20trailing=20spaces=20in=20dousse?= =?UTF-8?q?-adobe=20fork?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dousse-adobe fork's intrinsics.h has trailing spaces on the AVX2 preprocessor guards at lines 94 and 143. The patch's minus lines must match exactly (git apply --ignore-whitespace only ignores trailing whitespace in context lines, not in minus lines). Co-Authored-By: Claude Sonnet 4.6 --- cmake/recipes/external/embree-winarm.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/recipes/external/embree-winarm.patch b/cmake/recipes/external/embree-winarm.patch index 5357af1a..9102a25b 100644 --- a/cmake/recipes/external/embree-winarm.patch +++ b/cmake/recipes/external/embree-winarm.patch @@ -4,14 +4,14 @@ diff --git i/common/sys/intrinsics.h w/common/sys/intrinsics.h @@ -92,6 +92,6 @@ #if defined(__X86_64__) || defined (__aarch64__) || defined(_M_ARM64) __forceinline size_t bsf(size_t v) { --#if defined(__AVX2__) +-#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(_M_ARM64) return _tzcnt_u64(v); #else unsigned long r = 0; _BitScanForward64(&r,v); return r; @@ -142,5 +142,5 @@ __forceinline size_t bsr(size_t v) { --#if defined(__AVX2__) +-#if defined(__AVX2__) +#if defined(__AVX2__) && !defined(_M_ARM64) return 63 -_lzcnt_u64(v); #else From b3ff8471361ffe0f6db5a48807f11e3fc144661e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 7 May 2026 06:59:16 -0700 Subject: [PATCH 58/66] =?UTF-8?q?=F0=9F=90=9B=20Fix=20winding-number-winar?= =?UTF-8?q?m.patch:=20use=20space=20for=20empty=20context=20lines,=20fix?= =?UTF-8?q?=20hunk=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- cmake/recipes/external/winding-number-winarm.patch | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cmake/recipes/external/winding-number-winarm.patch b/cmake/recipes/external/winding-number-winarm.patch index 50099b2d..a765d38a 100644 --- a/cmake/recipes/external/winding-number-winarm.patch +++ b/cmake/recipes/external/winding-number-winarm.patch @@ -4,7 +4,7 @@ diff --git i/VM_SSEFunc.h w/VM_SSEFunc.h @@ -39,8 +39,26 @@ #include #include - + -typedef simde__m128 v4sf; -typedef simde__m128i v4si; +#if defined(_MSC_VER) && defined(_M_ARM64) @@ -27,16 +27,15 @@ diff --git i/VM_SSEFunc.h w/VM_SSEFunc.h +typedef simde__m128 v4sf; +typedef simde__m128i v4si; +#endif - + #define CPU_HAS_SIMD_INSTR 1 #define VM_SSE_STYLE 1 @@ -59,7 +77,7 @@ - // Plain casting (no conversion) // MSVC has problems casting between __m128 and __m128i, so we implement a // custom casting routine specifically for windows. - + -#if defined(_MSC_VER) +#if defined(_MSC_VER) && !defined(_M_ARM64) - + static SYS_FORCE_INLINE v4sf vm_v4sf(const v4si &a) From f5b8d57e3c4892c4923d52f09cd304d499b0c0fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 7 May 2026 07:37:04 -0700 Subject: [PATCH 59/66] =?UTF-8?q?=F0=9F=90=9B=20Fix=20vm=5Fshuffle=20ambig?= =?UTF-8?q?uity:=20add=20explicit=20V4SF()=20casts=20at=20ambiguous=20call?= =?UTF-8?q?=20sites?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- cmake/recipes/external/winding-number-winarm.patch | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cmake/recipes/external/winding-number-winarm.patch b/cmake/recipes/external/winding-number-winarm.patch index a765d38a..23d22d36 100644 --- a/cmake/recipes/external/winding-number-winarm.patch +++ b/cmake/recipes/external/winding-number-winarm.patch @@ -39,3 +39,12 @@ diff --git i/VM_SSEFunc.h w/VM_SSEFunc.h static SYS_FORCE_INLINE v4sf vm_v4sf(const v4si &a) +@@ -249,6 +267,6 @@ + vm_splats(float a, float b, float c, float d) + { + return vm_shuffle<0,2,0,2>( +- vm_shuffle<0>(simde_mm_set_ss(a), simde_mm_set_ss(b)), +- vm_shuffle<0>(simde_mm_set_ss(c), simde_mm_set_ss(d))); ++ vm_shuffle<0>(V4SF(simde_mm_set_ss(a)), V4SF(simde_mm_set_ss(b))), ++ vm_shuffle<0>(V4SF(simde_mm_set_ss(c)), V4SF(simde_mm_set_ss(d)))); + } From 694fa212f980ec179d204dfbfb02c54f80701987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 7 May 2026 12:46:33 -0700 Subject: [PATCH 60/66] =?UTF-8?q?=F0=9F=94=8D=20[TEMP]=20Diagnose=20Eigen?= =?UTF-8?q?=20alignment=20assert=20on=20Windows=20ARM64?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Force-include a non-fatal eigen_assert override that logs each alignment failure to stderr (first 30 hits) instead of aborting/popping a CRT dialog. Disable Unix and non-ARM64 Windows jobs to iterate fast on the only failing config. Co-Authored-By: Claude Opus 4.7 --- .github/workflows/continuous.yaml | 6 ++- cmake/recipes/external/Eigen3.cmake | 9 +++++ cmake/recipes/external/eigen_alignment_diag.h | 39 +++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 cmake/recipes/external/eigen_alignment_diag.h diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 504829ae..8dea8875 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -21,6 +21,7 @@ jobs: Unix: name: ${{ matrix.os }} (${{ matrix.compiler }}, ${{ matrix.config }}, ${{ matrix.sanitizer }}Sanitizer) runs-on: ${{ matrix.os }} + if: false # TEMPORARY: disabled while iterating on Windows ARM64 Eigen alignment diagnostics strategy: fail-fast: false matrix: @@ -202,8 +203,9 @@ jobs: strategy: fail-fast: false matrix: - os: [windows-2025, windows-11-arm] - config: [Release, Debug] + # TEMPORARY: only windows-11-arm Debug while iterating on Eigen alignment diagnostics + os: [windows-11-arm] + config: [Debug] steps: - name: Show disk space run: Get-PSDrive diff --git a/cmake/recipes/external/Eigen3.cmake b/cmake/recipes/external/Eigen3.cmake index 726e6053..c1aa125b 100644 --- a/cmake/recipes/external/Eigen3.cmake +++ b/cmake/recipes/external/Eigen3.cmake @@ -46,6 +46,15 @@ if(EIGEN_DONT_VECTORIZE) target_compile_definitions(Eigen3_Eigen INTERFACE EIGEN_DONT_VECTORIZE) endif() +# Diagnostic only — TEMPORARY: force-include a header that replaces eigen_assert with a +# non-fatal logger so we can capture every Eigen alignment failure on Windows ARM64 Debug +# (the runtime dialog otherwise hangs CI). Remove once the underlying issue is fixed. +if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND MSVC) + set(_lagrange_eigen_diag_header "${CMAKE_CURRENT_LIST_DIR}/eigen_alignment_diag.h") + target_compile_options(Eigen3_Eigen INTERFACE "/FI${_lagrange_eigen_diag_header}") + target_compile_definitions(Eigen3_Eigen INTERFACE LAGRANGE_DIAG_EIGEN_ALIGN=1) +endif() + if(EIGEN_WITH_MKL) # TODO: Checks that, on 64bits systems, `MKL::MKL` is using the LP64 interface # (by looking at the compile definition of the target) diff --git a/cmake/recipes/external/eigen_alignment_diag.h b/cmake/recipes/external/eigen_alignment_diag.h new file mode 100644 index 00000000..83362957 --- /dev/null +++ b/cmake/recipes/external/eigen_alignment_diag.h @@ -0,0 +1,39 @@ +// Diagnostic eigen_assert override for Windows ARM64 investigation. +// Prints the address, alignment, and call site, then continues so we can see +// every misaligned construction without aborting the process. +#pragma once + +#ifdef LAGRANGE_DIAG_EIGEN_ALIGN + +#include +#include +#include +#include + +namespace lagrange_diag { +inline std::atomic& eigen_diag_count() +{ + static std::atomic n{0}; + return n; +} + +inline void log_eigen_assert(const char* expr, const char* file, int line) +{ + int n = eigen_diag_count().fetch_add(1); + if (n < 30) { + std::fprintf(stderr, "[EIGEN_DIAG #%d] %s:%d %s\n", n, file, line, expr); + std::fflush(stderr); + } +} +} // namespace lagrange_diag + +// Replace eigen_assert with a non-fatal diagnostic version. We must define this BEFORE +// any Eigen header is included; this file is force-included via /FI on MSVC and -include on GCC/Clang. +#define eigen_assert(x) \ + do { \ + if (!(x)) { \ + ::lagrange_diag::log_eigen_assert(#x, __FILE__, __LINE__); \ + } \ + } while (0) + +#endif // LAGRANGE_DIAG_EIGEN_ALIGN From a6b32dbdcc876f37af1e588dc40563a87ab27951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 7 May 2026 15:12:28 -0700 Subject: [PATCH 61/66] =?UTF-8?q?=F0=9F=94=8D=20Diagnose=20Eigen=20alignme?= =?UTF-8?q?nt=20assert=20with=20cpptrace=20on=20Win=20ARM64?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the temporary EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT workaround with a non-fatal eigen_assert override that uses cpptrace::generate_trace() to print a full stack trace whenever the failing assertion originates from DenseStorage.h (the plain_array<> alignment check). All other eigen_assert failures still abort to keep unrelated invariants surfaced. Trim CI to the smallest possible reproducer: - Disable Unix matrix. - Windows matrix reduced to windows-11-arm Debug only. - Configure only LAGRANGE_MODULE_SERIALIZATION2 (no LAGRANGE_ALL, no Python). - Scope ctest to -R 'serialization2|serialize_'. Co-Authored-By: Claude Opus 4.7 --- .github/workflows/continuous.yaml | 21 +++--- cmake/recipes/external/Eigen3.cmake | 24 +++++-- .../recipes/external/eigen_alignment_diag.cpp | 68 +++++++++++++++++++ cmake/recipes/external/eigen_alignment_diag.h | 44 ++++-------- 4 files changed, 115 insertions(+), 42 deletions(-) create mode 100644 cmake/recipes/external/eigen_alignment_diag.cpp diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index 8dea8875..f532ae2c 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -19,9 +19,9 @@ jobs: #################### Unix: + if: false # DIAGNOSTIC: temporarily disabled to iterate fast on Windows ARM64 Debug Eigen alignment investigation name: ${{ matrix.os }} (${{ matrix.compiler }}, ${{ matrix.config }}, ${{ matrix.sanitizer }}Sanitizer) runs-on: ${{ matrix.os }} - if: false # TEMPORARY: disabled while iterating on Windows ARM64 Eigen alignment diagnostics strategy: fail-fast: false matrix: @@ -203,7 +203,8 @@ jobs: strategy: fail-fast: false matrix: - # TEMPORARY: only windows-11-arm Debug while iterating on Eigen alignment diagnostics + # DIAGNOSTIC: only the failing config (Win ARM64 Debug) while we hunt the + # Eigen alignment issue in serialization2. os: [windows-11-arm] config: [Debug] steps: @@ -284,8 +285,9 @@ jobs: -B ${{ env.BUILD_DIR }} ` -S . - # Force CMake to use the ARM64 Python (now complete with dev files) - # and skip the Windows registry so it doesn't fall back to x64 Python. + # DIAGNOSTIC: minimal configure for Win ARM64 — enable only the failing module + # (serialization2) so we get a fast iteration loop while we capture cpptrace + # stack traces for the Eigen alignment assertion. LAGRANGE_ALL=OFF, no Python. - name: Configure (ARM64) if: matrix.os == 'windows-11-arm' run: | @@ -293,10 +295,9 @@ jobs: cmake -G Ninja ` -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` -DLAGRANGE_JENKINS=ON ` - -DLAGRANGE_ALL=ON ` - -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON ` - -DPython_EXECUTABLE="$env:PYTHON_ARM64_EXE" ` - -DPython_FIND_REGISTRY=NEVER ` + -DLAGRANGE_ALL=OFF ` + -DLAGRANGE_MODULE_SERIALIZATION2=ON ` + -DLAGRANGE_MODULE_PYTHON=OFF ` -B ${{ env.BUILD_DIR }} ` -S . @@ -313,4 +314,6 @@ jobs: run: Get-PSDrive - name: Tests - run: cd ${{ env.BUILD_DIR }}; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} + # DIAGNOSTIC: scope ctest to the serialization2 suite (the only one firing the assert). + # --verbose is critical: cpptrace writes to stderr and we need it captured in the log. + run: cd ${{ env.BUILD_DIR }}; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} -R "serialization2|serialize_" diff --git a/cmake/recipes/external/Eigen3.cmake b/cmake/recipes/external/Eigen3.cmake index c1aa125b..398686dd 100644 --- a/cmake/recipes/external/Eigen3.cmake +++ b/cmake/recipes/external/Eigen3.cmake @@ -46,13 +46,29 @@ if(EIGEN_DONT_VECTORIZE) target_compile_definitions(Eigen3_Eigen INTERFACE EIGEN_DONT_VECTORIZE) endif() -# Diagnostic only — TEMPORARY: force-include a header that replaces eigen_assert with a -# non-fatal logger so we can capture every Eigen alignment failure on Windows ARM64 Debug -# (the runtime dialog otherwise hangs CI). Remove once the underlying issue is fixed. -if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND MSVC) +# Diagnostic only — TEMPORARY: on Windows ARM64 Debug, force-include a header that overrides +# eigen_assert with a non-fatal handler. When the assertion comes from DenseStorage.h (i.e. the +# plain_array<> alignment check) we capture a cpptrace stack trace so we can pinpoint the call +# site that constructs a misaligned fixed-size Eigen object. All other eigen_assert failures +# still abort, so unrelated invariants are not masked. +# +# The cpptrace dependency stays in a separate static library (lagrange_eigen_align_diag) so it +# does not leak into every Eigen consumer's interface. +if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND MSVC AND CMAKE_BUILD_TYPE STREQUAL "Debug") + include(cpptrace) + add_library(lagrange_eigen_align_diag STATIC + ${CMAKE_CURRENT_LIST_DIR}/eigen_alignment_diag.cpp + ${CMAKE_CURRENT_LIST_DIR}/eigen_alignment_diag.h + ) + target_include_directories(lagrange_eigen_align_diag PUBLIC ${CMAKE_CURRENT_LIST_DIR}) + target_compile_definitions(lagrange_eigen_align_diag PUBLIC LAGRANGE_DIAG_EIGEN_ALIGN=1) + target_link_libraries(lagrange_eigen_align_diag PRIVATE cpptrace::cpptrace) + set_target_properties(lagrange_eigen_align_diag PROPERTIES FOLDER third_party) + set(_lagrange_eigen_diag_header "${CMAKE_CURRENT_LIST_DIR}/eigen_alignment_diag.h") target_compile_options(Eigen3_Eigen INTERFACE "/FI${_lagrange_eigen_diag_header}") target_compile_definitions(Eigen3_Eigen INTERFACE LAGRANGE_DIAG_EIGEN_ALIGN=1) + target_link_libraries(Eigen3_Eigen INTERFACE lagrange_eigen_align_diag) endif() if(EIGEN_WITH_MKL) diff --git a/cmake/recipes/external/eigen_alignment_diag.cpp b/cmake/recipes/external/eigen_alignment_diag.cpp new file mode 100644 index 00000000..a70944eb --- /dev/null +++ b/cmake/recipes/external/eigen_alignment_diag.cpp @@ -0,0 +1,68 @@ +// See eigen_alignment_diag.h. Defined in a separate translation unit so the +// cpptrace dependency stays private to this static library and does not leak +// into every consumer of Eigen3::Eigen. +#include "eigen_alignment_diag.h" + +#ifdef LAGRANGE_DIAG_EIGEN_ALIGN + +#include + +#include +#include +#include +#include +#include + +namespace lagrange_diag { + +namespace { +std::atomic& trace_count() +{ + static std::atomic n{0}; + return n; +} + +std::mutex& trace_mutex() +{ + static std::mutex m; + return m; +} + +bool is_alignment_assert(const char* file) +{ + if (!file) return false; + return std::strstr(file, "DenseStorage") != nullptr; +} +} // namespace + +void eigen_assert_handler(const char* expr, const char* file, int line) +{ + if (is_alignment_assert(file)) { + // Alignment assertion: log + capture trace, but DO NOT abort. ARM64 NEON + // tolerates unaligned access; we only need to find where the misaligned + // plain_array<> is being constructed. + int n = trace_count().fetch_add(1); + if (n < 30) { + std::lock_guard lock(trace_mutex()); + std::fprintf( + stderr, + "\n[EIGEN_DIAG #%d] %s:%d %s\n", + n, + file, + line, + expr ? expr : "(null)"); + cpptrace::generate_trace(/*skip*/ 1, /*max*/ 64).print(std::cerr); + std::fflush(stderr); + } + return; + } + // Any other Eigen invariant violation: preserve original assert() behavior + // so unrelated bugs still surface (and tests fail) rather than being masked. + std::fprintf(stderr, "Eigen assertion failed: %s at %s:%d\n", expr, file, line); + std::fflush(stderr); + std::abort(); +} + +} // namespace lagrange_diag + +#endif // LAGRANGE_DIAG_EIGEN_ALIGN diff --git a/cmake/recipes/external/eigen_alignment_diag.h b/cmake/recipes/external/eigen_alignment_diag.h index 83362957..f14bb931 100644 --- a/cmake/recipes/external/eigen_alignment_diag.h +++ b/cmake/recipes/external/eigen_alignment_diag.h @@ -1,39 +1,25 @@ -// Diagnostic eigen_assert override for Windows ARM64 investigation. -// Prints the address, alignment, and call site, then continues so we can see -// every misaligned construction without aborting the process. +// Diagnostic Eigen assertion override for Windows ARM64 Debug investigation. +// Replaces eigen_assert with a non-fatal handler that captures a stack trace +// via cpptrace whenever the failing call originates from DenseStorage.h (i.e. +// the alignment check on plain_array<>). The actual cpptrace call lives in +// eigen_alignment_diag.cpp so this header has no dependency on cpptrace. +// +// Force-included via /FI on MSVC (see cmake/recipes/external/Eigen3.cmake). +// Pre-defining eigen_assert here works because Eigen/src/Core/util/Macros.h +// guards its own definition with #ifndef eigen_assert. #pragma once #ifdef LAGRANGE_DIAG_EIGEN_ALIGN -#include -#include -#include -#include - namespace lagrange_diag { -inline std::atomic& eigen_diag_count() -{ - static std::atomic n{0}; - return n; -} - -inline void log_eigen_assert(const char* expr, const char* file, int line) -{ - int n = eigen_diag_count().fetch_add(1); - if (n < 30) { - std::fprintf(stderr, "[EIGEN_DIAG #%d] %s:%d %s\n", n, file, line, expr); - std::fflush(stderr); - } -} +void eigen_assert_handler(const char* expr, const char* file, int line); } // namespace lagrange_diag -// Replace eigen_assert with a non-fatal diagnostic version. We must define this BEFORE -// any Eigen header is included; this file is force-included via /FI on MSVC and -include on GCC/Clang. -#define eigen_assert(x) \ - do { \ - if (!(x)) { \ - ::lagrange_diag::log_eigen_assert(#x, __FILE__, __LINE__); \ - } \ +#define eigen_assert(x) \ + do { \ + if (!(x)) { \ + ::lagrange_diag::eigen_assert_handler(#x, __FILE__, __LINE__); \ + } \ } while (0) #endif // LAGRANGE_DIAG_EIGEN_ALIGN From 00661ba8b1f5e0266118a59d7883ed4f7b4f7308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 7 May 2026 15:17:47 -0700 Subject: [PATCH 62/66] =?UTF-8?q?=F0=9F=94=A7=20Diag:=20scope=20Eigen3=20l?= =?UTF-8?q?ink=20to=20lagrange=5Feigen=5Falign=5Fdiag=20with=20BUILD=5FINT?= =?UTF-8?q?ERFACE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit install(EXPORT Eigen_Targets ...) was failing because Eigen3_Eigen INTERFACE linked a target outside the export set. Wrap the diagnostic compile options, defines, and link with $ so they only apply during the local build and are stripped from the install/export. Co-Authored-By: Claude Opus 4.7 --- cmake/recipes/external/Eigen3.cmake | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/cmake/recipes/external/Eigen3.cmake b/cmake/recipes/external/Eigen3.cmake index 398686dd..d328b5d6 100644 --- a/cmake/recipes/external/Eigen3.cmake +++ b/cmake/recipes/external/Eigen3.cmake @@ -66,9 +66,14 @@ if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND MSVC AND CMAKE_BUILD_TY set_target_properties(lagrange_eigen_align_diag PROPERTIES FOLDER third_party) set(_lagrange_eigen_diag_header "${CMAKE_CURRENT_LIST_DIR}/eigen_alignment_diag.h") - target_compile_options(Eigen3_Eigen INTERFACE "/FI${_lagrange_eigen_diag_header}") - target_compile_definitions(Eigen3_Eigen INTERFACE LAGRANGE_DIAG_EIGEN_ALIGN=1) - target_link_libraries(Eigen3_Eigen INTERFACE lagrange_eigen_align_diag) + # Wrap with $ so install(EXPORT Eigen_Targets) does not see the + # diagnostic target (which is intentionally not part of the export set). + target_compile_options(Eigen3_Eigen INTERFACE + "$") + target_compile_definitions(Eigen3_Eigen INTERFACE + $) + target_link_libraries(Eigen3_Eigen INTERFACE + $) endif() if(EIGEN_WITH_MKL) From ff4ad3b266f3467d5ea48581d7bbf47c0a8e837f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 7 May 2026 15:29:14 -0700 Subject: [PATCH 63/66] =?UTF-8?q?=F0=9F=94=A7=20Diag:=20add=20missing=20=20for=20std::cerr=20in=20eigen=5Falignment=5Fdiag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 --- cmake/recipes/external/eigen_alignment_diag.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/recipes/external/eigen_alignment_diag.cpp b/cmake/recipes/external/eigen_alignment_diag.cpp index a70944eb..26f1ac1c 100644 --- a/cmake/recipes/external/eigen_alignment_diag.cpp +++ b/cmake/recipes/external/eigen_alignment_diag.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace lagrange_diag { From 5028be8ad3cd126a0ed23e16c44469dc027ebf48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Thu, 7 May 2026 15:58:19 -0700 Subject: [PATCH 64/66] =?UTF-8?q?=F0=9F=94=8D=20Diag:=20route=20cpptrace?= =?UTF-8?q?=20through=20fprintf=20with=20frame=20count=20+=20exception=20g?= =?UTF-8?q?uard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Last run produced [EIGEN_DIAG #N] header lines but no cpptrace frames followed. Switch to to_string(false) + fprintf(stderr) so output uses the same C stream as the header, log frame count, and catch exceptions in case symbol resolution or unwinding fails on Win ARM64. Co-Authored-By: Claude Opus 4.7 --- cmake/recipes/external/eigen_alignment_diag.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/cmake/recipes/external/eigen_alignment_diag.cpp b/cmake/recipes/external/eigen_alignment_diag.cpp index 26f1ac1c..7a64c885 100644 --- a/cmake/recipes/external/eigen_alignment_diag.cpp +++ b/cmake/recipes/external/eigen_alignment_diag.cpp @@ -11,8 +11,9 @@ #include #include #include -#include +#include #include +#include namespace lagrange_diag { @@ -52,7 +53,17 @@ void eigen_assert_handler(const char* expr, const char* file, int line) file, line, expr ? expr : "(null)"); - cpptrace::generate_trace(/*skip*/ 1, /*max*/ 64).print(std::cerr); + std::fflush(stderr); + try { + auto trace = cpptrace::generate_trace(/*skip*/ 1, /*max*/ 64); + std::string s = trace.to_string(/*color*/ false); + std::fprintf(stderr, "%s\n", s.c_str()); + std::fprintf(stderr, "[EIGEN_DIAG #%d] frames=%zu\n", n, trace.frames.size()); + } catch (const std::exception& e) { + std::fprintf(stderr, "[EIGEN_DIAG #%d] cpptrace exception: %s\n", n, e.what()); + } catch (...) { + std::fprintf(stderr, "[EIGEN_DIAG #%d] cpptrace unknown exception\n", n); + } std::fflush(stderr); } return; From e7717453c548ef487ca73bd7727122de4ecc7a5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Sun, 17 May 2026 16:42:26 -0700 Subject: [PATCH 65/66] =?UTF-8?q?=F0=9F=90=9B=20Pass-by-const-ref=20Eigen?= =?UTF-8?q?=20fixed-size=20parameters?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MSVC ARM64 Debug does not guarantee 16-byte alignment for parameter slots on the stack. Passing fixed-size vectorizable Eigen objects (alignof >= 16: Vector2d, Vector4f, Matrix4f, Matrix, etc.) by value triggers the plain_array<> alignment assertion at the call site, before the function body even runs. Switch the following public APIs to const-ref parameters, which sidesteps the issue and matches the rest of the codebase: - internal::point_on_segment_2d / 3d - mesh_cleanup unflip_uv_triangles 'update_uv' lambda - ui::ShaderValue::operator= overloads (Vec/Mat/Affine/Projective) - ui::Camera::set_ortho_viewport / rotate_turntable / get_frustum - ui::AABB::intersects_ray - ui::utils::render::compute_perpendicular_plane - python transform_mesh binding lambda Also drop the temporary Win ARM64 Debug eigen_assert override diagnostic introduced to chase this bug (Eigen3.cmake block plus eigen_alignment_diag.{h,cpp}). --- cmake/recipes/external/Eigen3.cmake | 30 ------- .../recipes/external/eigen_alignment_diag.cpp | 80 ------------------- cmake/recipes/external/eigen_alignment_diag.h | 25 ------ .../include/lagrange/utils/point_on_segment.h | 10 ++- modules/core/python/src/bind_utilities.h | 2 +- .../src/mesh_cleanup/unflip_uv_triangles.cpp | 2 +- modules/core/src/utils/point_on_segment.cpp | 23 ++++-- modules/primitive/src/primitive_utils.h | 4 +- modules/ui/include/lagrange/ui/types/AABB.h | 4 +- modules/ui/include/lagrange/ui/types/Camera.h | 6 +- modules/ui/include/lagrange/ui/types/Shader.h | 18 ++--- modules/ui/include/lagrange/ui/utils/render.h | 2 +- modules/ui/src/types/AABB.cpp | 4 +- modules/ui/src/types/Camera.cpp | 9 ++- modules/ui/src/types/Shader.cpp | 16 ++-- modules/ui/src/utils/render.cpp | 5 +- 16 files changed, 61 insertions(+), 179 deletions(-) delete mode 100644 cmake/recipes/external/eigen_alignment_diag.cpp delete mode 100644 cmake/recipes/external/eigen_alignment_diag.h diff --git a/cmake/recipes/external/Eigen3.cmake b/cmake/recipes/external/Eigen3.cmake index d328b5d6..726e6053 100644 --- a/cmake/recipes/external/Eigen3.cmake +++ b/cmake/recipes/external/Eigen3.cmake @@ -46,36 +46,6 @@ if(EIGEN_DONT_VECTORIZE) target_compile_definitions(Eigen3_Eigen INTERFACE EIGEN_DONT_VECTORIZE) endif() -# Diagnostic only — TEMPORARY: on Windows ARM64 Debug, force-include a header that overrides -# eigen_assert with a non-fatal handler. When the assertion comes from DenseStorage.h (i.e. the -# plain_array<> alignment check) we capture a cpptrace stack trace so we can pinpoint the call -# site that constructs a misaligned fixed-size Eigen object. All other eigen_assert failures -# still abort, so unrelated invariants are not masked. -# -# The cpptrace dependency stays in a separate static library (lagrange_eigen_align_diag) so it -# does not leak into every Eigen consumer's interface. -if(WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" AND MSVC AND CMAKE_BUILD_TYPE STREQUAL "Debug") - include(cpptrace) - add_library(lagrange_eigen_align_diag STATIC - ${CMAKE_CURRENT_LIST_DIR}/eigen_alignment_diag.cpp - ${CMAKE_CURRENT_LIST_DIR}/eigen_alignment_diag.h - ) - target_include_directories(lagrange_eigen_align_diag PUBLIC ${CMAKE_CURRENT_LIST_DIR}) - target_compile_definitions(lagrange_eigen_align_diag PUBLIC LAGRANGE_DIAG_EIGEN_ALIGN=1) - target_link_libraries(lagrange_eigen_align_diag PRIVATE cpptrace::cpptrace) - set_target_properties(lagrange_eigen_align_diag PROPERTIES FOLDER third_party) - - set(_lagrange_eigen_diag_header "${CMAKE_CURRENT_LIST_DIR}/eigen_alignment_diag.h") - # Wrap with $ so install(EXPORT Eigen_Targets) does not see the - # diagnostic target (which is intentionally not part of the export set). - target_compile_options(Eigen3_Eigen INTERFACE - "$") - target_compile_definitions(Eigen3_Eigen INTERFACE - $) - target_link_libraries(Eigen3_Eigen INTERFACE - $) -endif() - if(EIGEN_WITH_MKL) # TODO: Checks that, on 64bits systems, `MKL::MKL` is using the LP64 interface # (by looking at the compile definition of the target) diff --git a/cmake/recipes/external/eigen_alignment_diag.cpp b/cmake/recipes/external/eigen_alignment_diag.cpp deleted file mode 100644 index 7a64c885..00000000 --- a/cmake/recipes/external/eigen_alignment_diag.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// See eigen_alignment_diag.h. Defined in a separate translation unit so the -// cpptrace dependency stays private to this static library and does not leak -// into every consumer of Eigen3::Eigen. -#include "eigen_alignment_diag.h" - -#ifdef LAGRANGE_DIAG_EIGEN_ALIGN - -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace lagrange_diag { - -namespace { -std::atomic& trace_count() -{ - static std::atomic n{0}; - return n; -} - -std::mutex& trace_mutex() -{ - static std::mutex m; - return m; -} - -bool is_alignment_assert(const char* file) -{ - if (!file) return false; - return std::strstr(file, "DenseStorage") != nullptr; -} -} // namespace - -void eigen_assert_handler(const char* expr, const char* file, int line) -{ - if (is_alignment_assert(file)) { - // Alignment assertion: log + capture trace, but DO NOT abort. ARM64 NEON - // tolerates unaligned access; we only need to find where the misaligned - // plain_array<> is being constructed. - int n = trace_count().fetch_add(1); - if (n < 30) { - std::lock_guard lock(trace_mutex()); - std::fprintf( - stderr, - "\n[EIGEN_DIAG #%d] %s:%d %s\n", - n, - file, - line, - expr ? expr : "(null)"); - std::fflush(stderr); - try { - auto trace = cpptrace::generate_trace(/*skip*/ 1, /*max*/ 64); - std::string s = trace.to_string(/*color*/ false); - std::fprintf(stderr, "%s\n", s.c_str()); - std::fprintf(stderr, "[EIGEN_DIAG #%d] frames=%zu\n", n, trace.frames.size()); - } catch (const std::exception& e) { - std::fprintf(stderr, "[EIGEN_DIAG #%d] cpptrace exception: %s\n", n, e.what()); - } catch (...) { - std::fprintf(stderr, "[EIGEN_DIAG #%d] cpptrace unknown exception\n", n); - } - std::fflush(stderr); - } - return; - } - // Any other Eigen invariant violation: preserve original assert() behavior - // so unrelated bugs still surface (and tests fail) rather than being masked. - std::fprintf(stderr, "Eigen assertion failed: %s at %s:%d\n", expr, file, line); - std::fflush(stderr); - std::abort(); -} - -} // namespace lagrange_diag - -#endif // LAGRANGE_DIAG_EIGEN_ALIGN diff --git a/cmake/recipes/external/eigen_alignment_diag.h b/cmake/recipes/external/eigen_alignment_diag.h deleted file mode 100644 index f14bb931..00000000 --- a/cmake/recipes/external/eigen_alignment_diag.h +++ /dev/null @@ -1,25 +0,0 @@ -// Diagnostic Eigen assertion override for Windows ARM64 Debug investigation. -// Replaces eigen_assert with a non-fatal handler that captures a stack trace -// via cpptrace whenever the failing call originates from DenseStorage.h (i.e. -// the alignment check on plain_array<>). The actual cpptrace call lives in -// eigen_alignment_diag.cpp so this header has no dependency on cpptrace. -// -// Force-included via /FI on MSVC (see cmake/recipes/external/Eigen3.cmake). -// Pre-defining eigen_assert here works because Eigen/src/Core/util/Macros.h -// guards its own definition with #ifndef eigen_assert. -#pragma once - -#ifdef LAGRANGE_DIAG_EIGEN_ALIGN - -namespace lagrange_diag { -void eigen_assert_handler(const char* expr, const char* file, int line); -} // namespace lagrange_diag - -#define eigen_assert(x) \ - do { \ - if (!(x)) { \ - ::lagrange_diag::eigen_assert_handler(#x, __FILE__, __LINE__); \ - } \ - } while (0) - -#endif // LAGRANGE_DIAG_EIGEN_ALIGN diff --git a/modules/core/include/lagrange/utils/point_on_segment.h b/modules/core/include/lagrange/utils/point_on_segment.h index ed768115..ae68e81d 100644 --- a/modules/core/include/lagrange/utils/point_on_segment.h +++ b/modules/core/include/lagrange/utils/point_on_segment.h @@ -19,10 +19,16 @@ namespace lagrange { namespace internal { /// @internal -bool LA_CORE_API point_on_segment_2d(Eigen::Vector2d p, Eigen::Vector2d a, Eigen::Vector2d b); +bool LA_CORE_API point_on_segment_2d( + const Eigen::Vector2d& p, + const Eigen::Vector2d& a, + const Eigen::Vector2d& b); /// @internal -bool LA_CORE_API point_on_segment_3d(Eigen::Vector3d p, Eigen::Vector3d a, Eigen::Vector3d b); +bool LA_CORE_API point_on_segment_3d( + const Eigen::Vector3d& p, + const Eigen::Vector3d& a, + const Eigen::Vector3d& b); } // namespace internal diff --git a/modules/core/python/src/bind_utilities.h b/modules/core/python/src/bind_utilities.h index 8a372d54..40bced17 100644 --- a/modules/core/python/src/bind_utilities.h +++ b/modules/core/python/src/bind_utilities.h @@ -1620,7 +1620,7 @@ oriented. m.def( "transform_mesh", [](MeshType& mesh, - Eigen::Matrix affine_transform, + const Eigen::Matrix& affine_transform, bool normalize_normals, bool normalize_tangents_bitangents, bool in_place) -> std::optional { diff --git a/modules/core/src/mesh_cleanup/unflip_uv_triangles.cpp b/modules/core/src/mesh_cleanup/unflip_uv_triangles.cpp index fe3cef9e..3b7969ef 100644 --- a/modules/core/src/mesh_cleanup/unflip_uv_triangles.cpp +++ b/modules/core/src/mesh_cleanup/unflip_uv_triangles.cpp @@ -59,7 +59,7 @@ void unflip_uv_triangles(SurfaceMesh& mesh, const UnflipUVOptions }; std::vector additional_uv_values; - auto update_uv = [&](Index fid, Index lv, Eigen::Matrix new_uv) { + auto update_uv = [&](Index fid, Index lv, const Eigen::Matrix& new_uv) { additional_uv_values.insert(additional_uv_values.end(), new_uv.data(), new_uv.data() + 2); Index old_id = uv_indices(fid, lv); uv_indices(fid, lv) = static_cast(uv_values_attr.get_num_elements()) + diff --git a/modules/core/src/utils/point_on_segment.cpp b/modules/core/src/utils/point_on_segment.cpp index 1cca2b4f..ad8bba26 100644 --- a/modules/core/src/utils/point_on_segment.cpp +++ b/modules/core/src/utils/point_on_segment.cpp @@ -17,24 +17,31 @@ namespace lagrange { namespace internal { -bool point_on_segment_2d(Eigen::Vector2d p, Eigen::Vector2d a, Eigen::Vector2d b) +bool point_on_segment_2d( + const Eigen::Vector2d& p, + const Eigen::Vector2d& a, + const Eigen::Vector2d& b) { ExactPredicatesShewchuk pred; auto res = pred.orient2D(p.data(), a.data(), b.data()); if (res != 0) { return false; } - if (a.x() > b.x()) { - std::swap(a.x(), b.x()); + double ax = a.x(), ay = a.y(); + double bx = b.x(), by = b.y(); + if (ax > bx) { + std::swap(ax, bx); } - if (a.y() > b.y()) { - std::swap(a.y(), b.y()); + if (ay > by) { + std::swap(ay, by); } - auto ret = (a.x() <= p.x() && p.x() <= b.x() && a.y() <= p.y() && p.y() <= b.y()); - return ret; + return (ax <= p.x() && p.x() <= bx && ay <= p.y() && p.y() <= by); } -bool point_on_segment_3d(Eigen::Vector3d p, Eigen::Vector3d a, Eigen::Vector3d b) +bool point_on_segment_3d( + const Eigen::Vector3d& p, + const Eigen::Vector3d& a, + const Eigen::Vector3d& b) { for (int d = 0; d < 3; ++d) { Eigen::Vector2d p2d(p(d), p((d + 1) % 3)); diff --git a/modules/primitive/src/primitive_utils.h b/modules/primitive/src/primitive_utils.h index d16a1e85..125d0fe1 100644 --- a/modules/primitive/src/primitive_utils.h +++ b/modules/primitive/src/primitive_utils.h @@ -92,8 +92,8 @@ void add_semantic_label( template void normalize_uv( SurfaceMesh& mesh, - Eigen::Matrix min_uv, - Eigen::Matrix max_uv) + const Eigen::Matrix& min_uv, + const Eigen::Matrix& max_uv) { auto uv_mesh = uv_mesh_ref(mesh); auto uvs = vertex_ref(uv_mesh); diff --git a/modules/ui/include/lagrange/ui/types/AABB.h b/modules/ui/include/lagrange/ui/types/AABB.h index a66f7132..6d2b2ec9 100644 --- a/modules/ui/include/lagrange/ui/types/AABB.h +++ b/modules/ui/include/lagrange/ui/types/AABB.h @@ -61,8 +61,8 @@ class LA_UI_API AABB : public Eigen::AlignedBox3f AABB transformed(const Eigen::Affine3f& transform) const; bool intersects_ray( - Eigen::Vector3f origin, - Eigen::Vector3f dir, + const Eigen::Vector3f& origin, + const Eigen::Vector3f& dir, float* tmin_out = nullptr, float* tmax_out = nullptr) const; diff --git a/modules/ui/include/lagrange/ui/types/Camera.h b/modules/ui/include/lagrange/ui/types/Camera.h index 3e518b38..e1e7a1a9 100644 --- a/modules/ui/include/lagrange/ui/types/Camera.h +++ b/modules/ui/include/lagrange/ui/types/Camera.h @@ -199,7 +199,7 @@ class LA_UI_API Camera void rotate_turntable( float yaw_delta, float pitch_delta, - Eigen::Vector3f primary_axis = Eigen::Vector3f::Zero()); + const Eigen::Vector3f& primary_axis = Eigen::Vector3f::Zero()); void rotate_arcball( @@ -227,7 +227,7 @@ class LA_UI_API Camera /// /// @param viewport Orthographic rectangle /// - void set_ortho_viewport(Eigen::Vector4f viewport); + void set_ortho_viewport(const Eigen::Vector4f& viewport); Eigen::Vector4f get_ortho_viewport() const; @@ -314,7 +314,7 @@ class LA_UI_API Camera /// /// @return Frustum planes of a region /// - Frustum get_frustum(Eigen::Vector2f min, Eigen::Vector2f max) const; + Frustum get_frustum(const Eigen::Vector2f& min, const Eigen::Vector2f& max) const; protected: void update_view(); diff --git a/modules/ui/include/lagrange/ui/types/Shader.h b/modules/ui/include/lagrange/ui/types/Shader.h index 9eab156d..f3c5628c 100644 --- a/modules/ui/include/lagrange/ui/types/Shader.h +++ b/modules/ui/include/lagrange/ui/types/Shader.h @@ -153,15 +153,15 @@ struct LA_UI_API ShaderValue int size; GLenum type; ShaderInterface shaderInterface; - const ShaderValue& operator=(Eigen::Vector2f val) const; - const ShaderValue& operator=(Eigen::Vector3f val) const; - const ShaderValue& operator=(Eigen::Vector4f val) const; - - const ShaderValue& operator=(Eigen::Matrix2f val) const; - const ShaderValue& operator=(Eigen::Matrix3f val) const; - const ShaderValue& operator=(Eigen::Matrix4f val) const; - const ShaderValue& operator=(Eigen::Affine3f val) const; - const ShaderValue& operator=(Eigen::Projective3f val) const; + const ShaderValue& operator=(const Eigen::Vector2f& val) const; + const ShaderValue& operator=(const Eigen::Vector3f& val) const; + const ShaderValue& operator=(const Eigen::Vector4f& val) const; + + const ShaderValue& operator=(const Eigen::Matrix2f& val) const; + const ShaderValue& operator=(const Eigen::Matrix3f& val) const; + const ShaderValue& operator=(const Eigen::Matrix4f& val) const; + const ShaderValue& operator=(const Eigen::Affine3f& val) const; + const ShaderValue& operator=(const Eigen::Projective3f& val) const; const ShaderValue& operator=(double val) const; diff --git a/modules/ui/include/lagrange/ui/utils/render.h b/modules/ui/include/lagrange/ui/utils/render.h index 426f72e9..4cd421dc 100644 --- a/modules/ui/include/lagrange/ui/utils/render.h +++ b/modules/ui/include/lagrange/ui/utils/render.h @@ -54,7 +54,7 @@ LA_UI_API void set_render_pass_defaults(GLScope& scope); /// /// Returns a pair of orthogonal directions, that together with direction form a orthogonal basis LA_UI_API std::pair compute_perpendicular_plane( - Eigen::Vector3f direction); + const Eigen::Vector3f& direction); } // namespace render diff --git a/modules/ui/src/types/AABB.cpp b/modules/ui/src/types/AABB.cpp index 158d657f..6093919d 100644 --- a/modules/ui/src/types/AABB.cpp +++ b/modules/ui/src/types/AABB.cpp @@ -43,8 +43,8 @@ Eigen::Affine3f AABB::get_normalization_transform(bool preserve_aspect) const } bool AABB::intersects_ray( - Eigen::Vector3f origin, - Eigen::Vector3f dir, + const Eigen::Vector3f& origin, + const Eigen::Vector3f& dir, float* tmin_out /* = nullptr*/, float* tmax_out /* = nullptr*/) const { diff --git a/modules/ui/src/types/Camera.cpp b/modules/ui/src/types/Camera.cpp index c8ce0f7a..4ce4c85a 100644 --- a/modules/ui/src/types/Camera.cpp +++ b/modules/ui/src/types/Camera.cpp @@ -311,7 +311,10 @@ void Camera::rotate_tumble(float yaw_delta, float pitch_delta) } -void Camera::rotate_turntable(float yaw_delta, float pitch_delta, Eigen::Vector3f primary_axis) +void Camera::rotate_turntable( + float yaw_delta, + float pitch_delta, + const Eigen::Vector3f& primary_axis) { if (primary_axis.x() != 0 || primary_axis.y() != 0 || primary_axis.z() != 0) { set_up(primary_axis); @@ -400,7 +403,7 @@ void Camera::move_up(float delta) update_view(); } -void Camera::set_ortho_viewport(Eigen::Vector4f viewport) +void Camera::set_ortho_viewport(const Eigen::Vector4f& viewport) { if (std::isnan(viewport.x()) || std::isnan(viewport.y()) || std::isnan(viewport.z()) || std::isnan(viewport.w())) @@ -514,7 +517,7 @@ Frustum Camera::get_frustum() const return get_frustum(Eigen::Vector2f(0), Eigen::Vector2f(get_window_size())); } -Frustum Camera::get_frustum(Eigen::Vector2f min, Eigen::Vector2f max) const +Frustum Camera::get_frustum(const Eigen::Vector2f& min, const Eigen::Vector2f& max) const { auto ray_bottom_left = cast_ray(min); auto ray_top_left = cast_ray({min.x(), max.y()}); diff --git a/modules/ui/src/types/Shader.cpp b/modules/ui/src/types/Shader.cpp index 4c4b9c4a..c0ae2009 100644 --- a/modules/ui/src/types/Shader.cpp +++ b/modules/ui/src/types/Shader.cpp @@ -783,7 +783,7 @@ ShaderValue::set_matrices(const Eigen::Affine3f* data, int n, bool transpose /*= ShaderValue ShaderValue::none = {-1, 0, 0, SHADER_INTERFACE_NONE}; -const ShaderValue& ShaderValue::operator=(Eigen::Vector2f val) const +const ShaderValue& ShaderValue::operator=(const Eigen::Vector2f& val) const { if (location == -1) return *this; assert(type == GL_FLOAT_VEC2); @@ -797,7 +797,7 @@ const ShaderValue& ShaderValue::operator=(Eigen::Vector2f val) const return *this; } -const ShaderValue& ShaderValue::operator=(Eigen::Vector3f val) const +const ShaderValue& ShaderValue::operator=(const Eigen::Vector3f& val) const { if (location == -1) return *this; assert(type == GL_FLOAT_VEC3); @@ -811,7 +811,7 @@ const ShaderValue& ShaderValue::operator=(Eigen::Vector3f val) const return *this; } -const ShaderValue& ShaderValue::operator=(Eigen::Vector4f val) const +const ShaderValue& ShaderValue::operator=(const Eigen::Vector4f& val) const { if (location == -1) return *this; @@ -837,7 +837,7 @@ const ShaderValue& ShaderValue::operator=(Eigen::Vector4f val) const return *this; } -const ShaderValue& ShaderValue::operator=(Eigen::Matrix2f val) const +const ShaderValue& ShaderValue::operator=(const Eigen::Matrix2f& val) const { if (location == -1) return *this; assert(type == GL_FLOAT_MAT2 && shaderInterface == SHADER_INTERFACE_UNIFORM); @@ -845,7 +845,7 @@ const ShaderValue& ShaderValue::operator=(Eigen::Matrix2f val) const return *this; } -const ShaderValue& ShaderValue::operator=(Eigen::Matrix3f val) const +const ShaderValue& ShaderValue::operator=(const Eigen::Matrix3f& val) const { if (location == -1) return *this; assert(type == GL_FLOAT_MAT3 && shaderInterface == SHADER_INTERFACE_UNIFORM); @@ -853,7 +853,7 @@ const ShaderValue& ShaderValue::operator=(Eigen::Matrix3f val) const return *this; } -const ShaderValue& ShaderValue::operator=(Eigen::Matrix4f val) const +const ShaderValue& ShaderValue::operator=(const Eigen::Matrix4f& val) const { if (location == -1) return *this; assert(type == GL_FLOAT_MAT4 && shaderInterface == SHADER_INTERFACE_UNIFORM); @@ -861,13 +861,13 @@ const ShaderValue& ShaderValue::operator=(Eigen::Matrix4f val) const return *this; } -const ShaderValue& ShaderValue::operator=(Eigen::Affine3f val) const +const ShaderValue& ShaderValue::operator=(const Eigen::Affine3f& val) const { // defer to Matrix4f return ((*this) = val.matrix()); } -const ShaderValue& ShaderValue::operator=(Eigen::Projective3f val) const +const ShaderValue& ShaderValue::operator=(const Eigen::Projective3f& val) const { // defer to Matrix4f return ((*this) = val.matrix()); diff --git a/modules/ui/src/utils/render.cpp b/modules/ui/src/utils/render.cpp index f0d80bc7..720b548e 100644 --- a/modules/ui/src/utils/render.cpp +++ b/modules/ui/src/utils/render.cpp @@ -25,9 +25,10 @@ namespace ui { namespace utils { namespace render { -std::pair compute_perpendicular_plane(Eigen::Vector3f direction) +std::pair compute_perpendicular_plane( + const Eigen::Vector3f& direction) { - Eigen::Vector3f& u1 = direction; + const Eigen::Vector3f& u1 = direction; Eigen::Vector3f v2; if (std::abs(direction.x()) == 1.0f && direction.y() == 0.0f && direction.z() == 0.0f) { From 74e03835f881ba0c0114ddf440a7230ecfe3b336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81mie=20Dumas?= Date: Sun, 17 May 2026 17:17:53 -0700 Subject: [PATCH 66/66] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Restore=20full=20CI?= =?UTF-8?q?=20matrix=20after=20Eigen=20alignment=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the underlying root cause (pass-by-value of fixed-size vectorizable Eigen types on MSVC ARM64 Debug) is fixed in e771745, restore the diagnostic-trimmed CI configuration to its full matrix: - Re-enable the Unix job (Linux + macOS, all compilers + sanitizers). - Restore Windows matrix to [windows-2025, windows-11-arm] x [Release, Debug]. - Restore LAGRANGE_ALL=ON + Python on windows-11-arm (uv-managed ARM64 Python pinned via Python_EXECUTABLE / Python_FIND_REGISTRY=NEVER). - Run full ctest suite (drop the serialization2-only -R filter). Verified by run 26006218827 (windows-11-arm Debug, serialization2 only) which passed cleanly after the const-ref refactor. --- .github/workflows/continuous.yaml | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/.github/workflows/continuous.yaml b/.github/workflows/continuous.yaml index f532ae2c..504829ae 100644 --- a/.github/workflows/continuous.yaml +++ b/.github/workflows/continuous.yaml @@ -19,7 +19,6 @@ jobs: #################### Unix: - if: false # DIAGNOSTIC: temporarily disabled to iterate fast on Windows ARM64 Debug Eigen alignment investigation name: ${{ matrix.os }} (${{ matrix.compiler }}, ${{ matrix.config }}, ${{ matrix.sanitizer }}Sanitizer) runs-on: ${{ matrix.os }} strategy: @@ -203,10 +202,8 @@ jobs: strategy: fail-fast: false matrix: - # DIAGNOSTIC: only the failing config (Win ARM64 Debug) while we hunt the - # Eigen alignment issue in serialization2. - os: [windows-11-arm] - config: [Debug] + os: [windows-2025, windows-11-arm] + config: [Release, Debug] steps: - name: Show disk space run: Get-PSDrive @@ -285,9 +282,8 @@ jobs: -B ${{ env.BUILD_DIR }} ` -S . - # DIAGNOSTIC: minimal configure for Win ARM64 — enable only the failing module - # (serialization2) so we get a fast iteration loop while we capture cpptrace - # stack traces for the Eigen alignment assertion. LAGRANGE_ALL=OFF, no Python. + # Force CMake to use the ARM64 Python (now complete with dev files) + # and skip the Windows registry so it doesn't fall back to x64 Python. - name: Configure (ARM64) if: matrix.os == 'windows-11-arm' run: | @@ -295,9 +291,10 @@ jobs: cmake -G Ninja ` -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` -DLAGRANGE_JENKINS=ON ` - -DLAGRANGE_ALL=OFF ` - -DLAGRANGE_MODULE_SERIALIZATION2=ON ` - -DLAGRANGE_MODULE_PYTHON=OFF ` + -DLAGRANGE_ALL=ON ` + -DLAGRANGE_POLYSCOPE_MOCK_BACKEND=ON ` + -DPython_EXECUTABLE="$env:PYTHON_ARM64_EXE" ` + -DPython_FIND_REGISTRY=NEVER ` -B ${{ env.BUILD_DIR }} ` -S . @@ -314,6 +311,4 @@ jobs: run: Get-PSDrive - name: Tests - # DIAGNOSTIC: scope ctest to the serialization2 suite (the only one firing the assert). - # --verbose is critical: cpptrace writes to stderr and we need it captured in the log. - run: cd ${{ env.BUILD_DIR }}; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }} -R "serialization2|serialize_" + run: cd ${{ env.BUILD_DIR }}; ctest --verbose -j ${{ steps.cpu-cores.outputs.count }}