diff --git a/.github/workflows/embree-cmake.yml b/.github/workflows/embree-cmake.yml index 68dfd6c..b6cc2b2 100644 --- a/.github/workflows/embree-cmake.yml +++ b/.github/workflows/embree-cmake.yml @@ -19,6 +19,11 @@ on: required: false type: string default: 'v4.4.1' + only-rid: + description: 'Build a single RID (e.g. win-arm64). Empty builds all five.' + required: false + type: string + default: '' jobs: build: @@ -27,55 +32,101 @@ jobs: fail-fast: false matrix: include: + # `parallel` is the compiler job count. An x64 build compiles the kernels once per + # ISA (SSE2, SSE4.2, AVX, AVX2) and Embree's templated translation units are heavy: + # four concurrent g++ processes exhaust the 16 GB of a standard runner and the OOM + # killer takes the runner down with them, which surfaces as a job that dies after + # 47 minutes with no logs at all rather than as a compiler error. The NEON legs + # build a single ISA and have room to spare. - os: ubuntu-24.04 rid: linux-x64 max-isa: AVX2 + parallel: 2 - os: ubuntu-24.04-arm rid: linux-arm64 max-isa: NEON + parallel: 4 + # `cmake-arch` feeds the Visual Studio generator's -A flag. Without it CMake picks + # the generator's default platform, which on the ARM64 runner is not ARM64: the + # build then compiled the x86 SIMD paths and immintrin.h rejected the target. - os: windows-latest rid: win-x64 max-isa: AVX2 - - os: windows-11-arm - rid: win-arm64 - max-isa: NEON + cmake-arch: x64 + parallel: 4 + # There is no win-arm64 leg. Embree 4.4.1 does not build for Windows on ARM with + # either toolset available on the runner, and the two failures are different walls: + # + # MSVC — Embree gates its ARM path on __ARM_NEON and __aarch64__, GCC/Clang + # predefines that MSVC does not define on ARM64, so + # common/sys/intrinsics.h takes its x86 branch and includes + # immintrin.h, which rejects the target. + # clang-cl — clears that wall, then Embree's own CMake feeds -msse2 to an + # arm64-pc-windows-msvc target and clang-cl refuses it. + # + # Both are upstream gaps in a configuration Embree neither supports nor tests. + # Getting past the second would mean patching Embree's CMake and carrying that + # patch, for a ray tracing kernel where a wrong SIMD path gives wrong intersections + # rather than a crash. See the tracking issue before trying again. - os: macos-latest rid: osx-arm64 max-isa: NEON + parallel: 4 steps: - name: Checkout Embree + if: inputs.only-rid == '' || inputs.only-rid == matrix.rid uses: actions/checkout@v4 with: repository: RenderKit/embree ref: ${{ inputs.embree-ref || 'v4.4.1' }} - name: Install build dependencies (Linux) - if: startsWith(matrix.os, 'ubuntu') + if: (inputs.only-rid == '' || inputs.only-rid == matrix.rid) && startsWith(matrix.os, 'ubuntu') run: | sudo apt-get update sudo apt-get install -y build-essential cmake - name: Configure + if: inputs.only-rid == '' || inputs.only-rid == matrix.rid shell: bash run: | + set -o pipefail cmake -S . -B build \ + ${{ matrix.cmake-arch && format('-A {0}', matrix.cmake-arch) || '' }} \ + ${{ matrix.toolset && format('-T {0}', matrix.toolset) || '' }} \ -DCMAKE_BUILD_TYPE=Release \ -DEMBREE_TASKING_SYSTEM=INTERNAL \ -DEMBREE_ISPC_SUPPORT=OFF \ -DEMBREE_TUTORIALS=OFF \ -DEMBREE_STATIC_LIB=OFF \ -DEMBREE_GEOMETRY_INSTANCE_ARRAY=ON \ - -DEMBREE_MAX_ISA=${{ matrix.max-isa }} + -DEMBREE_MAX_ISA=${{ matrix.max-isa }} 2>&1 | tee configure.log + + # Fail early and loudly if an ARM leg did not end up on the ARM code path: an x86 SIMD + # build for an ARM target dies deep inside immintrin.h with an error that says nothing + # about the real cause. + # + # This greps Embree's own configure output rather than CMakeCache.txt. EMBREE_ARM is a + # plain variable set with SET(), not a cache entry, so it never reaches the cache file + # and an assertion against it fails on a perfectly good build. + - name: Check ARM detection + if: (inputs.only-rid == '' || inputs.only-rid == matrix.rid) && matrix.max-isa == 'NEON' + shell: bash + run: | + grep -qE "Building for (AArch64|Apple silicon)" configure.log \ + || { echo "CMake did not take Embree's ARM path:"; grep -iE "Building for|CMAKE_GENERATOR_PLATFORM" configure.log; exit 1; } - name: Build - run: cmake --build build --config Release --parallel + if: inputs.only-rid == '' || inputs.only-rid == matrix.rid + run: cmake --build build --config Release --parallel ${{ matrix.parallel }} # On Linux and macOS CMake emits versioned names behind symlinks # (libembree4.so -> libembree4.so.4 -> libembree4.so.4.4.1). Symlinks do not survive # NuGet packaging, so the real file is copied out under the plain name that # [DllImport("embree4")] probes for. - name: Collect artifacts + if: inputs.only-rid == '' || inputs.only-rid == matrix.rid shell: bash run: | set -euo pipefail @@ -97,6 +148,7 @@ jobs: ls -l out - name: Upload + if: inputs.only-rid == '' || inputs.only-rid == matrix.rid uses: actions/upload-artifact@v4 with: name: embree-${{ matrix.rid }} diff --git a/EmbreeGen/Headers/embree4/rtcore_config.h b/EmbreeGen/Headers/embree4/rtcore_config.h index 87d9281..0ceb98e 100644 --- a/EmbreeGen/Headers/embree4/rtcore_config.h +++ b/EmbreeGen/Headers/embree4/rtcore_config.h @@ -1,24 +1,12 @@ // Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -// This file is normally generated by CMake from kernels/rtcore_config.h.in. -// It is vendored here so the binding generator produces code that matches the -// native binaries shipped in Evergine.Bindings.Embree/runtimes/. -// -// It corresponds to Embree v4.4.1 configured by .github/workflows/embree-cmake.yml: -// -DEMBREE_TASKING_SYSTEM=INTERNAL -// -DEMBREE_ISPC_SUPPORT=OFF -// -DEMBREE_TUTORIALS=OFF -// -DEMBREE_STATIC_LIB=OFF -// -DEMBREE_GEOMETRY_INSTANCE_ARRAY=ON -// and the upstream defaults EMBREE_MAX_INSTANCE_LEVEL_COUNT=1, EMBREE_MIN_WIDTH=OFF, -// EMBREE_SYCL_SUPPORT=OFF, EMBREE_API_NAMESPACE="". -// -// If any of those options change, regenerate this file from the build output and -// re-run the generator, otherwise struct layouts silently drift from the binaries. - #pragma once +#if !defined(EMBREE_SYCL_SUPPORT) +/* #undef EMBREE_SYCL_SUPPORT */ +#endif + #define RTC_VERSION_MAJOR 4 #define RTC_VERSION_MINOR 4 #define RTC_VERSION_PATCH 1 @@ -37,11 +25,13 @@ #define EMBREE_MIN_WIDTH 0 #define RTC_MIN_WIDTH EMBREE_MIN_WIDTH +#if !defined(EMBREE_STATIC_LIB) /* #undef EMBREE_STATIC_LIB */ +#endif /* #undef EMBREE_API_NAMESPACE */ #if defined(EMBREE_API_NAMESPACE) -# define RTC_NAMESPACE +# define RTC_NAMESPACE # define RTC_NAMESPACE_BEGIN namespace { # define RTC_NAMESPACE_END } # define RTC_NAMESPACE_USE using namespace ; @@ -110,3 +100,4 @@ # define RTC_SYCL_INDIRECTLY_CALLABLE # define RTC_SYCL_API RTC_API #endif + diff --git a/Evergine.Bindings.Embree/runtimes/linux-arm64/native/.gitkeep b/Evergine.Bindings.Embree/runtimes/linux-arm64/native/.gitkeep deleted file mode 100644 index a10cf3c..0000000 --- a/Evergine.Bindings.Embree/runtimes/linux-arm64/native/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -# Native Embree binary for linux-arm64 goes here (produced by .github/workflows/embree-cmake.yml). diff --git a/Evergine.Bindings.Embree/runtimes/linux-arm64/native/libembree4.so b/Evergine.Bindings.Embree/runtimes/linux-arm64/native/libembree4.so new file mode 100644 index 0000000..bf63c04 Binary files /dev/null and b/Evergine.Bindings.Embree/runtimes/linux-arm64/native/libembree4.so differ diff --git a/Evergine.Bindings.Embree/runtimes/linux-x64/native/.gitkeep b/Evergine.Bindings.Embree/runtimes/linux-x64/native/.gitkeep deleted file mode 100644 index 2711ff7..0000000 --- a/Evergine.Bindings.Embree/runtimes/linux-x64/native/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -# Native Embree binary for linux-x64 goes here (produced by .github/workflows/embree-cmake.yml). diff --git a/Evergine.Bindings.Embree/runtimes/linux-x64/native/libembree4.so b/Evergine.Bindings.Embree/runtimes/linux-x64/native/libembree4.so new file mode 100644 index 0000000..232e55c Binary files /dev/null and b/Evergine.Bindings.Embree/runtimes/linux-x64/native/libembree4.so differ diff --git a/Evergine.Bindings.Embree/runtimes/osx-arm64/native/.gitkeep b/Evergine.Bindings.Embree/runtimes/osx-arm64/native/.gitkeep deleted file mode 100644 index 80f877f..0000000 --- a/Evergine.Bindings.Embree/runtimes/osx-arm64/native/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -# Native Embree binary for osx-arm64 goes here (produced by .github/workflows/embree-cmake.yml). diff --git a/Evergine.Bindings.Embree/runtimes/osx-arm64/native/libembree4.dylib b/Evergine.Bindings.Embree/runtimes/osx-arm64/native/libembree4.dylib new file mode 100644 index 0000000..67a97d8 Binary files /dev/null and b/Evergine.Bindings.Embree/runtimes/osx-arm64/native/libembree4.dylib differ diff --git a/Evergine.Bindings.Embree/runtimes/win-arm64/native/.gitkeep b/Evergine.Bindings.Embree/runtimes/win-arm64/native/.gitkeep deleted file mode 100644 index bd72f80..0000000 --- a/Evergine.Bindings.Embree/runtimes/win-arm64/native/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -# Native Embree binary for win-arm64 goes here (produced by .github/workflows/embree-cmake.yml). diff --git a/Evergine.Bindings.Embree/runtimes/win-x64/native/.gitkeep b/Evergine.Bindings.Embree/runtimes/win-x64/native/.gitkeep deleted file mode 100644 index 18ad1f2..0000000 --- a/Evergine.Bindings.Embree/runtimes/win-x64/native/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -# Native Embree binary for win-x64 goes here (produced by .github/workflows/embree-cmake.yml). diff --git a/Evergine.Bindings.Embree/runtimes/win-x64/native/embree4.dll b/Evergine.Bindings.Embree/runtimes/win-x64/native/embree4.dll new file mode 100644 index 0000000..0e88630 Binary files /dev/null and b/Evergine.Bindings.Embree/runtimes/win-x64/native/embree4.dll differ diff --git a/README.md b/README.md index 919ff23..b3a4a96 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,13 @@ CPU ray tracing, lightmap baking, ambient occlusion and general geometric querie ## Supported Platforms -- [x] Windows x64, ARM64 +- [x] Windows x64 - [x] Linux x64, ARM64 - [x] MacOS ARM64 +- [ ] Windows ARM64 — Embree 4.4.1 does not build for this target with either toolset on the + runner: MSVC does not define the `__ARM_NEON`/`__aarch64__` macros Embree gates its ARM path + on, and clang-cl gets past that only to be handed `-msse2` for an ARM64 target by Embree's + own CMake. Both are upstream gaps. ## Usage notes