diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 48bde94a366..986ee010ea9 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -66,9 +66,8 @@ jobs: - name: Install dependencies run: | - brew install ccache glslang spirv-cross - # Fix gfortran not found issue. - brew install gcc + brew install ccache glslang spirv-cross gcc + # Fix gfortran not found issue ln -s $(brew --prefix gcc)/bin/gfortran-* /usr/local/bin/gfortran ccache -M 2G # See .github/workflows/readme.md for ccache strategy. diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 0b0882b8b6a..c2ea73b9a5a 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -4,7 +4,6 @@ # - PyTorch Ops in debug mode - DLL initialization error while loading open3d_torch_ops.dll # - CUDA - Draw.exe does not run due to CUDA DLL path issues - name: Windows permissions: {} @@ -15,6 +14,10 @@ on: description: "Set to OFF for Release wheels" required: false default: "ON" + oneapi_cmake_debug: + description: "Verbose oneAPI path diagnostics and CMAKE_FIND_DEBUG_MODE on xpu legs" + required: false + default: "OFF" push: branches: @@ -34,6 +37,8 @@ env: INSTALL_DIR: "C:\\Program Files\\Open3D" NPROC: 6 DEVELOPER_BUILD: ${{ github.event.inputs.developer_build || 'ON' }} + # workflow_dispatch oneapi_cmake_debug=ON enables -Verbose install logs and cmake --debug-find + OPEN3D_ONEAPI_DEBUG: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.oneapi_cmake_debug == 'ON' && '1' || '0' }} jobs: windows: @@ -45,25 +50,68 @@ jobs: runs-on: windows-2022 strategy: fail-fast: false + # Eight matrix legs (S=BUILD_SHARED_LIBS, R=STATIC_RUNTIME) plus build-wheel/test-wheel. + # Covers cpu/cuda/xpu once where needed; devel zips, viewer, SYCL, and /MD static smoke. matrix: - BUILD_SHARED_LIBS: [ON, OFF] - STATIC_RUNTIME: [ON, OFF] - BUILD_CUDA_MODULE: [ON, OFF] - CONFIG: [Release, Debug] - exclude: - - BUILD_SHARED_LIBS: ON + include: + # OFF/ON: static lib + /MT (WebRTC on Release); wheel-like linkage + - BUILD_SHARED_LIBS: OFF + STATIC_RUNTIME: ON + device: cpu + CONFIG: Release + + # Debug /MT, tests, import + - BUILD_SHARED_LIBS: OFF + STATIC_RUNTIME: ON + device: cpu + CONFIG: Debug + + # SYCL, oneAPI install, tests, import + - BUILD_SHARED_LIBS: OFF STATIC_RUNTIME: ON - - BUILD_CUDA_MODULE: ON # FIXME + device: xpu + CONFIG: Release + + # Single Windows CUDA compile leg + - BUILD_SHARED_LIBS: OFF + STATIC_RUNTIME: ON + device: cuda + CONFIG: Release + + # ON/OFF: shared + /MD devel packages (cpu Debug -> *-dbg.zip) + - BUILD_SHARED_LIBS: ON + STATIC_RUNTIME: OFF + device: cpu + CONFIG: Release + + # Shared SYCL devel zip + - BUILD_SHARED_LIBS: ON + STATIC_RUNTIME: OFF + device: xpu + CONFIG: Release + + # open3d-devel-*-dbg.zip + - BUILD_SHARED_LIBS: ON + STATIC_RUNTIME: OFF + device: cpu CONFIG: Debug + + # OFF/OFF: static lib + /MD linkage smoke + - BUILD_SHARED_LIBS: OFF + STATIC_RUNTIME: OFF + device: cpu + CONFIG: Release env: - BUILD_PYTORCH_OPS: ${{ ( matrix.BUILD_CUDA_MODULE == 'ON' || matrix.CONFIG == 'Debug' ) && 'OFF' || 'ON' }} # FIXME + BUILD_CUDA_MODULE: ${{ matrix.device == 'cuda' && 'ON' || 'OFF' }} + BUILD_SYCL_MODULE: ${{ matrix.device == 'xpu' && 'ON' || 'OFF' }} + BUILD_PYTORCH_OPS: ${{ ( matrix.device == 'cuda' || matrix.device == 'xpu' || matrix.CONFIG == 'Debug' ) && 'OFF' || 'ON' }} # FIXME steps: - name: Disk space used run: Get-PSDrive - name: Install CUDA - if: ${{ matrix.BUILD_CUDA_MODULE == 'ON' }} + if: ${{ matrix.device == 'cuda' }} run: | # Define variables $CUDA_VER_FULL = "${{ env.CUDA_VERSION }}" @@ -95,6 +143,25 @@ jobs: echo "CUDA_PATH_V$CUDA_VER_ID=$CUDA_PATH" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append echo "$CUDA_PATH\bin" | Out-File -FilePath $Env:GITHUB_PATH -Encoding utf8 -Append + - name: Checkout source code + uses: actions/checkout@v4 + + - name: Install Intel oneAPI + if: ${{ matrix.device == 'xpu' }} + shell: pwsh + working-directory: ${{ env.SRC_DIR }} + env: + OPEN3D_ONEAPI_DEBUG: ${{ env.OPEN3D_ONEAPI_DEBUG }} + run: ./util/install_oneapi_windows.ps1 + + - name: Debug oneAPI layout before CMake + if: ${{ matrix.device == 'xpu' }} + shell: pwsh + working-directory: ${{ env.SRC_DIR }} + env: + OPEN3D_ONEAPI_DEBUG: ${{ env.OPEN3D_ONEAPI_DEBUG }} + run: ./util/print_oneapi_windows_paths.ps1 + - name: Install glslang via vcpkg run: | vcpkg install glslang[tools]:x64-windows @@ -102,9 +169,6 @@ jobs: $glslangBinPath = Join-Path $env:VCPKG_INSTALLATION_ROOT "installed\x64-windows\tools\glslang" $glslangBinPath | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - name: Checkout source code - uses: actions/checkout@v4 - - name: Set up Python version uses: actions/setup-python@v5 with: @@ -119,9 +183,11 @@ jobs: - name: Install PyTorch requirements run: | - if ( '${{ matrix.BUILD_CUDA_MODULE }}' -eq 'ON' ) { + if ( '${{ matrix.device }}' -eq 'cuda' ) { # python -m pip install -r open3d_ml/requirements-torch-cuda.txt python -m pip install torch torchvision --index-url https://download.pytorch.org/whl/cu126 + } elseif ( '${{ matrix.device }}' -eq 'xpu' ) { + # No PyTorch requirement for SYCL (xpu) since PyTorch ops are disabled } else { python -m pip install -r open3d_ml/requirements-torch.txt } @@ -136,7 +202,49 @@ jobs: $Env:DEVELOPER_BUILD = "ON" } cmake --version - cmake -G "Visual Studio 17 2022" -A x64 ` + $CMAKE_ARGS = @() + if ('${{ matrix.device }}' -eq 'xpu') { + # Runs setvars.bat via cmd and imports all resulting env vars into + # the current PowerShell process AND into $GITHUB_ENV. The latter + # is required because each workflow step ("Config", "Build", + # "Package", ...) runs in a brand new process: env vars set only + # via [System.Environment]::SetEnvironmentVariable (default scope + # Process) do NOT survive past this step. Without $GITHUB_ENV, + # later steps (e.g. Build) lose LIB/INCLUDE/PATH set by + # setvars.bat, so icx fails to find its own runtime libs (e.g. + # libircmt.lib) when ExternalProject sub-builds (zlib, + # directxheaders, ...) run their own fresh compiler ABI detection + # during the Build step. + Write-Host "Initializing oneAPI environment via setvars.bat..." + $setOutput = cmd /c '"C:\Program Files (x86)\Intel\oneAPI\setvars.bat" && set 2>&1' + if ($LASTEXITCODE -ne 0) { throw "setvars.bat failed (exit $LASTEXITCODE)" } + $setOutput | ForEach-Object { + if ($_ -match '^([^=]+)=(.*)$') { + $varName = $Matches[1] + $varValue = $Matches[2] + [System.Environment]::SetEnvironmentVariable($varName, $varValue) + "$varName=$varValue" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append + } + } + $CMAKE_GENERATOR = "Ninja" + # On Windows, icx.exe (MSVC-compatible) handles C++ and SYCL (-fsycl). + # icpx.exe identifies as GNU-like in oneAPI 2025.3+ which conflicts with + # CMake generating MSVC-style flags when C compiler (icx) is MSVC-like. + $CMAKE_ARGS += "-DCMAKE_C_COMPILER=icx", "-DCMAKE_CXX_COMPILER=icx", ` + "-DCMAKE_BUILD_TYPE=${{ matrix.CONFIG }}" + if ($env:OPEN3D_ONEAPI_DEBUG -eq '1') { + Write-Host "OPEN3D_ONEAPI_DEBUG=1: enabling CMAKE_FIND_DEBUG_MODE and cmake --debug-find" + $CMAKE_ARGS += '-DCMAKE_FIND_DEBUG_MODE=ON' + } + } else { + $CMAKE_GENERATOR = "Visual Studio 17 2022" + $CMAKE_ARGS += "-A", "x64" + } + $cmakeExtraArgs = @() + if ($env:OPEN3D_ONEAPI_DEBUG -eq '1' -and '${{ matrix.device }}' -eq 'xpu') { + $cmakeExtraArgs += '--debug-find' + } + cmake -G $CMAKE_GENERATOR @CMAKE_ARGS @cmakeExtraArgs ` -DDEVELOPER_BUILD=$Env:DEVELOPER_BUILD ` -DBUILD_EXAMPLES=OFF ` -DCMAKE_INSTALL_PREFIX="$env:INSTALL_DIR" ` @@ -145,7 +253,8 @@ jobs: -DBUILD_COMMON_ISPC_ISAS=ON ` -DBUILD_LIBREALSENSE=ON ` -DBUILD_UNIT_TESTS=ON ` - -DBUILD_CUDA_MODULE=${{ matrix.BUILD_CUDA_MODULE }} ` + -DBUILD_CUDA_MODULE=${{ env.BUILD_CUDA_MODULE }} ` + -DBUILD_SYCL_MODULE=${{ env.BUILD_SYCL_MODULE }} ` -DBUILD_PYTORCH_OPS=${{ env.BUILD_PYTORCH_OPS }} ` ${{ env.SRC_DIR }} @@ -153,18 +262,26 @@ jobs: working-directory: ${{ env.BUILD_DIR }} run: | $ErrorActionPreference = 'Stop' - cmake --build . --parallel ${{ env.NPROC }} --config ${{ matrix.CONFIG }} ` - --target build-examples-iteratively - cmake --build . --parallel ${{ env.NPROC }} --config ${{ matrix.CONFIG }} ` - --target INSTALL + $buildArgs = @("--build", ".", "--parallel", "${{ env.NPROC }}") + if ('${{ matrix.device }}' -ne 'xpu') { + $buildArgs += "--config", "${{ matrix.CONFIG }}" + } + cmake @buildArgs --target build-examples-iteratively + # Use lowercase "install" (works case-insensitively for MSBuild/VS + # generator too) since Ninja's generated meta-target is lowercase + # only; uppercase "INSTALL" is unknown to Ninja. + cmake @buildArgs --target install - name: Package working-directory: ${{ env.BUILD_DIR }} - if: ${{ matrix.BUILD_SHARED_LIBS == 'ON' && matrix.BUILD_CUDA_MODULE == 'OFF' }} + if: ${{ matrix.BUILD_SHARED_LIBS == 'ON' && matrix.device != 'cuda' }} run: | $ErrorActionPreference = 'Stop' - cmake --build . --parallel ${{ env.NPROC }} --config ${{ matrix.CONFIG }} ` - --target package + $buildArgs = @("--build", ".", "--parallel", "${{ env.NPROC }}") + if ('${{ matrix.device }}' -ne 'xpu') { + $buildArgs += "--config", "${{ matrix.CONFIG }}" + } + cmake @buildArgs --target package if ("${{ matrix.CONFIG }}" -eq "Debug") { Get-ChildItem package/open3d-devel-*.zip | Rename-Item -NewName ` {$_.name -Replace '.zip','-dbg.zip'} @@ -180,7 +297,7 @@ jobs: subject-path: ${{ env.BUILD_DIR }}/package/${{ env.DEVEL_PKG_NAME }} - name: Upload Package - if: ${{ matrix.BUILD_SHARED_LIBS == 'ON' && matrix.BUILD_CUDA_MODULE == 'OFF' }} + if: ${{ matrix.BUILD_SHARED_LIBS == 'ON' && matrix.device != 'cuda' }} uses: actions/upload-artifact@v4 with: name: ${{ env.DEVEL_PKG_NAME }} @@ -188,7 +305,7 @@ jobs: if-no-files-found: error - name: Update devel release with package - if: ${{ github.ref == 'refs/heads/main' && matrix.BUILD_SHARED_LIBS == 'ON' && matrix.BUILD_CUDA_MODULE == 'OFF' }} + if: ${{ github.ref == 'refs/heads/main' && matrix.BUILD_SHARED_LIBS == 'ON' && matrix.device != 'cuda' }} env: GH_TOKEN: ${{ github.token }} shell: bash @@ -198,7 +315,7 @@ jobs: - name: Viewer App working-directory: ${{ env.BUILD_DIR }} - if: ${{ matrix.BUILD_SHARED_LIBS == 'OFF' && matrix.STATIC_RUNTIME == 'ON' && matrix.BUILD_CUDA_MODULE == 'OFF' && matrix.CONFIG == 'Release' }} + if: ${{ matrix.BUILD_SHARED_LIBS == 'OFF' && matrix.STATIC_RUNTIME == 'ON' && matrix.device == 'cpu' && matrix.CONFIG == 'Release' }} run: | $ErrorActionPreference = 'Stop' cmake --build . --parallel ${{ env.NPROC }} --config ${{ matrix.CONFIG }} ` @@ -220,7 +337,7 @@ jobs: subject-path: ${{ github.workspace }}/${{ env.VIEWER_ZIP_NAME }} - name: Upload Viewer - if: ${{ matrix.BUILD_SHARED_LIBS == 'OFF' && matrix.STATIC_RUNTIME == 'ON' && matrix.BUILD_CUDA_MODULE == 'OFF' && matrix.CONFIG == 'Release' }} + if: ${{ matrix.BUILD_SHARED_LIBS == 'OFF' && matrix.STATIC_RUNTIME == 'ON' && matrix.device == 'cpu' && matrix.CONFIG == 'Release' }} uses: actions/upload-artifact@v4 with: name: open3d-app-windows-amd64 @@ -228,31 +345,59 @@ jobs: if-no-files-found: error - name: Update devel release with viewer - if: ${{ github.ref == 'refs/heads/main' && matrix.BUILD_SHARED_LIBS == 'OFF' && matrix.STATIC_RUNTIME == 'ON' && matrix.BUILD_CUDA_MODULE == 'OFF' && matrix.CONFIG == 'Release' }} + if: ${{ github.ref == 'refs/heads/main' && matrix.BUILD_SHARED_LIBS == 'OFF' && matrix.STATIC_RUNTIME == 'ON' && matrix.device == 'cpu' && matrix.CONFIG == 'Release' }} env: GH_TOKEN: ${{ github.token }} run: | bash .github/workflows/update_release.sh "${{ env.VIEWER_ZIP_NAME }}" - name: Run C++ unit tests - if: ${{ matrix.BUILD_CUDA_MODULE == 'OFF' }} + if: ${{ matrix.device != 'cuda' }} working-directory: ${{ env.BUILD_DIR }} run: | echo "Add --gtest_random_seed=SEED to the test command to repeat this test sequence." - .\bin\${{ matrix.CONFIG }}\tests.exe --gtest_shuffle --gtest_filter=-*ReduceSum64bit2DCase0*:*ReduceSum64bit2DCase3* + $testExe = if ('${{ matrix.device }}' -eq 'xpu') { ".\bin\tests.exe" } else { ".\bin\${{ matrix.CONFIG }}\tests.exe" } + & $testExe --gtest_shuffle --gtest_filter=-*ReduceSum64bit2DCase0*:*ReduceSum64bit2DCase3* - name: Linking to Open3D working-directory: ${{ env.SRC_DIR }}/examples/cmake/open3d-cmake-find-package run: | $ErrorActionPreference = 'Stop' mkdir build cd build - cmake -G "Visual Studio 17 2022" -A x64 ` + $CMAKE_ARGS = @() + if ('${{ matrix.device }}' -eq 'xpu') { + # Initialize oneAPI environment in the same step as cmake (env vars + # don't persist across steps). Runs setvars.bat via cmd and imports + # all resulting env vars into the current PowerShell process. + Write-Host "Initializing oneAPI environment via setvars.bat..." + $setOutput = cmd /c '"C:\Program Files (x86)\Intel\oneAPI\setvars.bat" && set 2>&1' + if ($LASTEXITCODE -ne 0) { throw "setvars.bat failed (exit $LASTEXITCODE)" } + $setOutput | ForEach-Object { + if ($_ -match '^([^=]+)=(.*)$') { + [System.Environment]::SetEnvironmentVariable($Matches[1], $Matches[2]) + } + } + $CMAKE_GENERATOR = "Ninja" + # On Windows, icx.exe (MSVC-compatible) handles C++ and SYCL (-fsycl). + # See Config step for the reason icpx is not used. + $CMAKE_ARGS += "-DCMAKE_C_COMPILER=icx", "-DCMAKE_CXX_COMPILER=icx", ` + "-DCMAKE_BUILD_TYPE=${{ matrix.CONFIG }}" + } else { + $CMAKE_GENERATOR = "Visual Studio 17 2022" + $CMAKE_ARGS += "-A", "x64" + } + cmake -G $CMAKE_GENERATOR @CMAKE_ARGS ` -DCMAKE_INSTALL_PREFIX="$env:INSTALL_DIR" ` -DSTATIC_WINDOWS_RUNTIME=${{ matrix.STATIC_RUNTIME }} ` .. - cmake --build . --config ${{ matrix.CONFIG }} - if ( '${{ matrix.BUILD_CUDA_MODULE }}' -eq 'OFF' ) { # FIXME - .\${{ matrix.CONFIG }}\Draw.exe --skip-for-unit-test + $buildArgs = @("--build", ".") + if ('${{ matrix.device }}' -ne 'xpu') { + $buildArgs += "--config", "${{ matrix.CONFIG }}" + } + cmake @buildArgs + if ( '${{ matrix.device }}' -ne 'cuda' ) { # FIXME + $drawExe = if ('${{ matrix.device }}' -eq 'xpu') { ".\Draw.exe" } else { ".\${{ matrix.CONFIG }}\Draw.exe" } + & $drawExe --skip-for-unit-test } Remove-Item -LiteralPath $env:INSTALL_DIR -Recurse -Force -ErrorAction SilentlyContinue - name: Install Open3D python build requirements @@ -265,13 +410,18 @@ jobs: working-directory: ${{ env.BUILD_DIR }} run: | $ErrorActionPreference = 'Stop' - cmake --build . --config ${{ matrix.CONFIG }} --target install-pip-package + $buildArgs = @("--build", ".", "--target", "install-pip-package") + if ('${{ matrix.device }}' -ne 'xpu') { + $buildArgs += "--config", "${{ matrix.CONFIG }}" + } + cmake @buildArgs - name: Import python package # If BUILD_SHARED_LIBS == ON, Open3D.dll needs to be copied, which is not recommended for python. - if: ${{ matrix.BUILD_SHARED_LIBS == 'OFF' && matrix.BUILD_CUDA_MODULE == 'OFF' }} # FIXME + if: ${{ matrix.BUILD_SHARED_LIBS == 'OFF' && matrix.device != 'cuda' }} # FIXME run: | python -c "import open3d; print('Imported:', open3d)" python -c "import open3d; print('CUDA enabled: ', open3d.core.cuda.is_available())" + python -c "import open3d; print('SYCL enabled: ', open3d.core.sycl.is_available() if hasattr(open3d.core, 'sycl') else False)" - name: Disk space used run: Get-PSDrive @@ -288,6 +438,7 @@ jobs: # https://github.community/t/how-to-conditionally-include-exclude-items-in-matrix-eg-based-on-branch/16853/6 matrix: python_version: ['3.10', '3.11', '3.12', '3.13', '3.14'] + device: [cpu, xpu] is_main: - ${{ github.ref == 'refs/heads/main' }} exclude: @@ -301,10 +452,31 @@ jobs: python_version: '3.13' env: - BUILD_PYTORCH_OPS: 'ON' + BUILD_CUDA_MODULE: 'OFF' + BUILD_SYCL_MODULE: ${{ matrix.device == 'xpu' && 'ON' || 'OFF' }} + BUILD_PYTORCH_OPS: ${{ matrix.device == 'xpu' && 'OFF' || 'ON' }} steps: + - name: Checkout source code + uses: actions/checkout@v4 + + - name: Install Intel oneAPI + if: ${{ matrix.device == 'xpu' }} + shell: pwsh + working-directory: ${{ env.SRC_DIR }} + env: + OPEN3D_ONEAPI_DEBUG: ${{ env.OPEN3D_ONEAPI_DEBUG }} + run: ./util/install_oneapi_windows.ps1 + + - name: Debug oneAPI layout before CMake + if: ${{ matrix.device == 'xpu' }} + shell: pwsh + working-directory: ${{ env.SRC_DIR }} + env: + OPEN3D_ONEAPI_DEBUG: ${{ env.OPEN3D_ONEAPI_DEBUG }} + run: ./util/print_oneapi_windows_paths.ps1 + - name: Install glslang via vcpkg run: | vcpkg install glslang[tools]:x64-windows @@ -312,9 +484,6 @@ jobs: $glslangBinPath = Join-Path $env:VCPKG_INSTALLATION_ROOT "installed\x64-windows\tools\glslang" $glslangBinPath | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - name: Checkout source code - uses: actions/checkout@v4 - - name: Checkout Open3D-ML uses: actions/checkout@v4 with: @@ -342,16 +511,58 @@ jobs: python -m pip install -U -r open3d_ml/requirements-torch.txt } - - name: Config + # Move build directory to C: https://github.com/actions/virtual-environments/issues/1341 run: | $ErrorActionPreference = 'Stop' - New-Item -Path ${{ env.BUILD_DIR }} -ItemType Directory - cd ${{ env.BUILD_DIR }} + New-Item -Path '${{ env.BUILD_DIR }}' -ItemType Directory + cd '${{ env.BUILD_DIR }}' if ($Env:DEVELOPER_BUILD -ne "OFF") { $Env:DEVELOPER_BUILD = "ON" } - cmake -G "Visual Studio 17 2022" -A x64 ` + cmake --version + $CMAKE_ARGS = @() + if ('${{ matrix.device }}' -eq 'xpu') { + # Runs setvars.bat via cmd and imports all resulting env vars into + # the current PowerShell process AND into $GITHUB_ENV. The latter + # is required because each workflow step ("Config", "Build Python + # package", ...) runs in a brand new process: env vars set only + # via [System.Environment]::SetEnvironmentVariable (default scope + # Process) do NOT survive past this step. Without $GITHUB_ENV, + # later steps (e.g. Build) lose LIB/INCLUDE/PATH set by + # setvars.bat, so icx fails to find its own runtime libs (e.g. + # libircmt.lib) when ExternalProject sub-builds (uvatlas, zlib, + # directxheaders, ...) run their own fresh compiler ABI detection + # during the Build step. + Write-Host "Initializing oneAPI environment via setvars.bat..." + $setOutput = cmd /c '"C:\Program Files (x86)\Intel\oneAPI\setvars.bat" && set 2>&1' + if ($LASTEXITCODE -ne 0) { throw "setvars.bat failed (exit $LASTEXITCODE)" } + $setOutput | ForEach-Object { + if ($_ -match '^([^=]+)=(.*)$') { + $varName = $Matches[1] + $varValue = $Matches[2] + [System.Environment]::SetEnvironmentVariable($varName, $varValue) + "$varName=$varValue" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append + } + } + $CMAKE_GENERATOR = "Ninja" + # On Windows, icx.exe (MSVC-compatible) handles C++ and SYCL (-fsycl). + # See Config step for the reason icpx is not used. + $CMAKE_ARGS += "-DCMAKE_C_COMPILER=icx", "-DCMAKE_CXX_COMPILER=icx", ` + "-DCMAKE_BUILD_TYPE=Release" + if ($env:OPEN3D_ONEAPI_DEBUG -eq '1') { + Write-Host "OPEN3D_ONEAPI_DEBUG=1: enabling CMAKE_FIND_DEBUG_MODE and cmake --debug-find" + $CMAKE_ARGS += '-DCMAKE_FIND_DEBUG_MODE=ON' + } + } else { + $CMAKE_GENERATOR = "Visual Studio 17 2022" + $CMAKE_ARGS += "-A", "x64" + } + $cmakeExtraArgs = @() + if ($env:OPEN3D_ONEAPI_DEBUG -eq '1' -and '${{ matrix.device }}' -eq 'xpu') { + $cmakeExtraArgs += '--debug-find' + } + cmake -G $CMAKE_GENERATOR @CMAKE_ARGS @cmakeExtraArgs ` -DCMAKE_INSTALL_PREFIX="$env:INSTALL_DIR" ` -DDEVELOPER_BUILD="$Env:DEVELOPER_BUILD" ` -DBUILD_SHARED_LIBS=OFF ` @@ -360,6 +571,8 @@ jobs: -DBUILD_AZURE_KINECT=ON ` -DBUILD_LIBREALSENSE=ON ` -DBUILD_JUPYTER_EXTENSION=ON ` + -DBUILD_CUDA_MODULE=${{ env.BUILD_CUDA_MODULE }} ` + -DBUILD_SYCL_MODULE=${{ env.BUILD_SYCL_MODULE }} ` -DBUILD_PYTORCH_OPS=${{ env.BUILD_PYTORCH_OPS }} ` ${{ env.SRC_DIR }} @@ -367,7 +580,11 @@ jobs: working-directory: ${{ env.BUILD_DIR }} run: | $ErrorActionPreference = 'Stop' - cmake --build . --parallel ${{ env.NPROC }} --config Release --target pip-package + $buildArgs = @("--build", ".", "--parallel", "${{ env.NPROC }}", "--target", "pip-package") + if ('${{ matrix.device }}' -ne 'xpu') { + $buildArgs += "--config", "Release" + } + cmake @buildArgs $PIP_PKG_NAME=(Get-ChildItem lib/python_package/pip_package/open3d*.whl).Name echo "PIP_PKG_NAME=$PIP_PKG_NAME" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append @@ -402,6 +619,7 @@ jobs: fail-fast: false matrix: python_version: ['3.10', '3.11', '3.12', '3.13', '3.14'] + device: [cpu, xpu, cuda] is_main: - ${{ github.ref == 'refs/heads/main' }} exclude: @@ -414,7 +632,7 @@ jobs: - is_main: false python_version: '3.13' env: - BUILD_PYTORCH_OPS: 'ON' + BUILD_PYTORCH_OPS: ${{ matrix.device == 'cpu' && 'ON' || 'OFF' }} steps: - name: Checkout source code uses: actions/checkout@v4 @@ -450,15 +668,21 @@ jobs: python -m pip install -U -r open3d_ml/requirements-torch.txt } $py_tag=(python -c "import sys; print(f'cp{sys.version_info.major}{sys.version_info.minor}')") - if (Test-Path -Path "pip_package") { - $PIP_PKG_NAME=(Get-ChildItem pip_package\open3d*-$py_tag-*.whl).Name + $search_dir = if (Test-Path -Path "pip_package") { "pip_package" } else { "." } + if ('${{ matrix.device }}' -eq 'xpu') { + $PIP_PKG_NAME=(Get-ChildItem (Join-Path $search_dir "open3d_xpu*-$py_tag-*.whl") -ErrorAction SilentlyContinue).Name } else { - $PIP_PKG_NAME=(Get-ChildItem open3d*-$py_tag-*.whl).Name + $PIP_PKG_NAME=(Get-ChildItem (Join-Path $search_dir "open3d-*-$py_tag-*.whl") -ErrorAction SilentlyContinue | Where-Object { $_.Name -notlike "open3d_xpu*" }).Name + } + if (-not $PIP_PKG_NAME) { + Write-Error "Could not find a valid Open3D wheel in $search_dir matching the python version $py_tag and device!" + exit 1 } echo "Installing Open3D wheel $PIP_PKG_NAME in virtual environment..." - python -m pip install "$PIP_PKG_NAME" + python -m pip install (Join-Path $search_dir $PIP_PKG_NAME) python -c "import open3d; print('Imported:', open3d)" python -c "import open3d; print('CUDA enabled: ', open3d.core.cuda.is_available())" + python -c "import open3d; print('SYCL enabled: ', open3d.core.sycl.is_available() if hasattr(open3d.core, 'sycl') else False)" deactivate - name: Run Python unit tests diff --git a/.gitignore b/.gitignore index 66eaaea98e2..8a2e68745aa 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ cmake-build-release/ util/pip_package/dist/ doxygen/ node_modules/ +.yarn # Editor files *.*~ diff --git a/3rdparty/README_SYCL.md b/3rdparty/README_SYCL.md index 26549446616..bb04db44011 100644 --- a/3rdparty/README_SYCL.md +++ b/3rdparty/README_SYCL.md @@ -98,9 +98,15 @@ Open3D is designed to make use of the SYCL GPU devices. ## List of oneAPI Python packages -To make `pip install open3d` works out-of-the box on SYCL-enabled platforms, -we can utilize runtime libraries released via PyPI. This feature needs to be -implemented. +Open3D SYCL wheels declare a dependency on `dpcpp-cpp-rt` (see +`python/requirements_sycl.txt`). Pip installs the transitive Intel runtime +packages into the same Python environment. On Linux, ``pybind`` RPATH finds +``/lib``; on Windows, ``open3d/__init__.py`` registers +``site-packages/*.data/data/Library/bin`` with ``add_dll_directory``. + +Windows CI (xpu) installs build-time oneAPI from Intel Base + HPC webimages with +selective components only (``util/ci_install_oneapi_windows_sycl.ps1``, aligned +with `oneapi-ci `_). User: - https://pypi.org/user/IntelAutomationEngineering/ diff --git a/3rdparty/civetweb/civetweb.cmake b/3rdparty/civetweb/civetweb.cmake index 4a4c0de61c8..1b9d19cfcca 100644 --- a/3rdparty/civetweb/civetweb.cmake +++ b/3rdparty/civetweb/civetweb.cmake @@ -19,7 +19,16 @@ ExternalProject_Add( -DCIVETWEB_DISABLE_CGI=ON -DCMAKE_INSTALL_PREFIX= -DCMAKE_POLICY_VERSION_MINIMUM=3.5 - -DCMAKE_CXX_FLAGS="-D_GLIBCXX_USE_CXX11_ABI=$ $<$:/EHsc>" + # Note: on Windows, keep this as a single flag (no embedded space by + # combining with another flag in the same string). The Intel + # oneAPI DPC++/C++ compiler (icx), used when BUILD_SYCL_MODULE=ON, + # parses each CMAKE_ARGS string as one literal argv token; a + # combined "-D /EHsc" string gets misparsed by icx as the + # macro's value swallowing "/EHsc", silently leaving exceptions + # disabled (MSVC cl.exe tolerates this, icx does not). Since + # _GLIBCXX_USE_CXX11_ABI only matters for libstdc++ (not used on + # Windows/MSVC STL), it is safe to only set one flag per platform. + -DCMAKE_CXX_FLAGS=$,/EHsc,-D_GLIBCXX_USE_CXX11_ABI=$> ${ExternalProject_CMAKE_ARGS_hidden} BUILD_BYPRODUCTS /${Open3D_INSTALL_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}civetweb${CMAKE_STATIC_LIBRARY_SUFFIX} diff --git a/3rdparty/embree/embree.cmake b/3rdparty/embree/embree.cmake index 36df1b1db6b..b0a40b4e444 100644 --- a/3rdparty/embree/embree.cmake +++ b/3rdparty/embree/embree.cmake @@ -50,14 +50,28 @@ endif() if(WIN32) - set(WIN_CMAKE_ARGS "-DCMAKE_CXX_FLAGS_DEBUG=$,/MTd,/MDd> ${CMAKE_CXX_FLAGS_DEBUG_INIT}" - "-DCMAKE_CXX_FLAGS_RELEASE=$,/MT,/MD> ${CMAKE_CXX_FLAGS_RELEASE_INIT}" - "-DCMAKE_CXX_FLAGS_RELWITHDEBINFO=$,/MT,/MD> ${CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT}" - "-DCMAKE_CXX_FLAGS_MINSIZEREL=$,/MT,/MD> ${CMAKE_CXX_FLAGS_MINSIZEREL_INIT}" - "-DCMAKE_C_FLAGS_DEBUG=$,/MTd,/MDd> ${CMAKE_C_FLAGS_DEBUG_INIT}" - "-DCMAKE_C_FLAGS_RELEASE=$,/MT,/MD> ${CMAKE_C_FLAGS_RELEASE_INIT}" - "-DCMAKE_C_FLAGS_RELWITHDEBINFO=$,/MT,/MD> ${CMAKE_C_FLAGS_RELWITHDEBINFO_INIT}" - "-DCMAKE_C_FLAGS_MINSIZEREL=$,/MT,/MD> ${CMAKE_C_FLAGS_MINSIZEREL_INIT}" + # icx.exe hard-errors ("invalid argument 'MT' not allowed with + # '-fsycl'") when compiling any translation unit with -fsycl together + # with the static (/MT, /MTd) MSVC runtime. Since embree's SYCL support + # (embree4_sycl, ze_wrapper) is built in the same ExternalProject + # configure/build as the non-SYCL ISA libs, force the dynamic runtime + # (/MD, /MDd) for all of embree's libs when BUILD_SYCL_MODULE=ON, + # regardless of STATIC_WINDOWS_RUNTIME. This also matches upstream + # embree's own Windows SYCL build docs, which never enable + # USE_STATIC_RUNTIME (default OFF) together with EMBREE_SYCL_SUPPORT. + if(BUILD_SYCL_MODULE) + set(EMBREE_USE_STATIC_RUNTIME OFF) + else() + set(EMBREE_USE_STATIC_RUNTIME ${STATIC_WINDOWS_RUNTIME}) + endif() + set(WIN_CMAKE_ARGS "-DCMAKE_CXX_FLAGS_DEBUG=$,/MTd,/MDd> ${CMAKE_CXX_FLAGS_DEBUG_INIT}" + "-DCMAKE_CXX_FLAGS_RELEASE=$,/MT,/MD> ${CMAKE_CXX_FLAGS_RELEASE_INIT}" + "-DCMAKE_CXX_FLAGS_RELWITHDEBINFO=$,/MT,/MD> ${CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT}" + "-DCMAKE_CXX_FLAGS_MINSIZEREL=$,/MT,/MD> ${CMAKE_CXX_FLAGS_MINSIZEREL_INIT}" + "-DCMAKE_C_FLAGS_DEBUG=$,/MTd,/MDd> ${CMAKE_C_FLAGS_DEBUG_INIT}" + "-DCMAKE_C_FLAGS_RELEASE=$,/MT,/MD> ${CMAKE_C_FLAGS_RELEASE_INIT}" + "-DCMAKE_C_FLAGS_RELWITHDEBINFO=$,/MT,/MD> ${CMAKE_C_FLAGS_RELWITHDEBINFO_INIT}" + "-DCMAKE_C_FLAGS_MINSIZEREL=$,/MT,/MD> ${CMAKE_C_FLAGS_MINSIZEREL_INIT}" ) else() set(WIN_CMAKE_ARGS "") @@ -65,7 +79,14 @@ endif() if(BUILD_SYCL_MODULE) - set(ISA_ARGS ${ISA_ARGS} -DCMAKE_CXX_COMPILER=icpx) + # On Windows, icx.exe (MSVC-compatible) handles C++ and SYCL (-fsycl). + # icpx.exe (GNU-like in oneAPI 2025.3+) conflicts with MSVC-style flags + # generated by CMake when using Ninja on Windows. + if(WIN32) + set(ISA_ARGS ${ISA_ARGS} -DCMAKE_CXX_COMPILER=icx) + else() + set(ISA_ARGS ${ISA_ARGS} -DCMAKE_CXX_COMPILER=icpx) + endif() set(ISA_ARGS ${ISA_ARGS} -DCMAKE_C_COMPILER=icx) set(ISA_ARGS ${ISA_ARGS} -DEMBREE_SYCL_SUPPORT=ON) list(APPEND ISA_LIBS embree4_sycl ze_wrapper) @@ -102,7 +123,6 @@ ExternalProject_Add( /${Open3D_INSTALL_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}sys${CMAKE_STATIC_LIBRARY_SUFFIX} /${Open3D_INSTALL_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}math${CMAKE_STATIC_LIBRARY_SUFFIX} /${Open3D_INSTALL_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}tasking${CMAKE_STATIC_LIBRARY_SUFFIX} - /${Open3D_INSTALL_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}ze_wrapper${CMAKE_STATIC_LIBRARY_SUFFIX} ${ISA_BUILD_BYPRODUCTS} ) diff --git a/3rdparty/filament/filament_build.cmake b/3rdparty/filament/filament_build.cmake index ee520798111..ccb982f6b6b 100644 --- a/3rdparty/filament/filament_build.cmake +++ b/3rdparty/filament/filament_build.cmake @@ -70,7 +70,7 @@ ExternalProject_Add( -DCMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER} -DCMAKE_CXX_FLAGS:STRING=${filament_cxx_flags} -DCMAKE_INSTALL_PREFIX=${FILAMENT_ROOT} - -DUSE_STATIC_CRT=${STATIC_WINDOWS_RUNTIME} + -DUSE_STATIC_CRT=$,OFF,${STATIC_WINDOWS_RUNTIME}> -DUSE_STATIC_LIBCXX=ON -DFILAMENT_SKIP_SDL2=ON -DFILAMENT_SKIP_SAMPLES=ON diff --git a/3rdparty/filament/filament_download.cmake b/3rdparty/filament/filament_download.cmake index 8795e5bfb91..d2314802086 100644 --- a/3rdparty/filament/filament_download.cmake +++ b/3rdparty/filament/filament_download.cmake @@ -15,7 +15,11 @@ else() if(WIN32) set(FILAMENT_URL https://github.com/google/filament/releases/download/v1.54.0/filament-v1.54.0-windows.tgz) set(FILAMENT_SHA256 370b85dbaf1a3be26a5a80f60c912f11887748ddd1c42796a83fe989f5805f7b) - if (STATIC_WINDOWS_RUNTIME) + # Note: when BUILD_SYCL_MODULE is ON, Open3D forces the dynamic + # (/MD, /MDd) MSVC runtime for the whole project regardless of + # STATIC_WINDOWS_RUNTIME (icx rejects -fsycl combined with the + # static runtime), so the prebuilt Filament libs must match. + if (STATIC_WINDOWS_RUNTIME AND NOT BUILD_SYCL_MODULE) string(APPEND lib_dir /x86_64/mt) else() string(APPEND lib_dir /x86_64/md) diff --git a/3rdparty/find_dependencies.cmake b/3rdparty/find_dependencies.cmake index 7a1dc143172..eca3ae8bd2d 100644 --- a/3rdparty/find_dependencies.cmake +++ b/3rdparty/find_dependencies.cmake @@ -1356,7 +1356,10 @@ if(BUILD_GUI) set(FILAMENT_RUNTIME_VER x86_64) endif() else() # WIN32 - if (STATIC_WINDOWS_RUNTIME) + # Match the prebuilt Filament archive's runtime selection in + # filament_download.cmake: SYCL builds always use the dynamic + # runtime regardless of STATIC_WINDOWS_RUNTIME. + if (STATIC_WINDOWS_RUNTIME AND NOT BUILD_SYCL_MODULE) set(FILAMENT_RUNTIME_VER "x86_64/mt$<$:d>") else() set(FILAMENT_RUNTIME_VER "x86_64/md$<$:d>") @@ -1608,16 +1611,29 @@ if(OPEN3D_USE_ONEAPI_PACKAGES) set(MKL_THREADING tbb_thread) set(MKL_LINK static) find_package(MKL REQUIRED) + # oneAPI MKL's lib layout differs by platform: Linux nests libs under an + # "intel64" subdirectory, while Windows (verified with oneAPI 2025.3) + # places them directly in "lib". + if(WIN32) + set(MKL_LIB_DIR ${MKL_ROOT}/lib) + else() + set(MKL_LIB_DIR ${MKL_ROOT}/lib/intel64) + endif() open3d_import_3rdparty_library(3rdparty_mkl HIDDEN GROUPED INCLUDE_DIRS ${MKL_INCLUDE}/ - LIB_DIR ${MKL_ROOT}/lib/intel64 + LIB_DIR ${MKL_LIB_DIR} LIBRARIES $<$:mkl_sycl> mkl_intel_ilp64 mkl_tbb_thread mkl_core ) if (BUILD_SYCL_MODULE) # target_link_options(3rdparty_mkl INTERFACE "-Wl,-export-dynamic") - target_link_libraries(3rdparty_mkl INTERFACE OpenCL) + if (WIN32) + find_package(OpenCL REQUIRED) + target_link_libraries(3rdparty_mkl INTERFACE OpenCL::OpenCL) + else() + target_link_libraries(3rdparty_mkl INTERFACE OpenCL) + endif() endif() # MKL definitions target_compile_options(3rdparty_mkl INTERFACE "$<$:$<$:-m64>>") diff --git a/3rdparty/googletest/googletest.cmake b/3rdparty/googletest/googletest.cmake index 50666cc8896..b7a8211d3ab 100644 --- a/3rdparty/googletest/googletest.cmake +++ b/3rdparty/googletest/googletest.cmake @@ -14,3 +14,14 @@ FetchContent_Declare( FetchContent_MakeAvailable(ext_googletest) FetchContent_GetProperties(ext_googletest SOURCE_DIR GOOGLETEST_SOURCE_DIR) + +# Suppress -Wcharacter-conversion error in googletest when using IntelLLVM/ICX. +# ICX's Clang front-end treats the implicit char16_t->char32_t conversion in +# gtest-printers.h(524) as a hard error. Suppress it on FetchContent targets. +if(CMAKE_CXX_COMPILER_ID MATCHES "IntelLLVM") + foreach(_gt_tgt gtest gtest_main gmock gmock_main) + if(TARGET ${_gt_tgt}) + target_compile_options(${_gt_tgt} PRIVATE -Wno-character-conversion) + endif() + endforeach() +endif() diff --git a/3rdparty/jsoncpp/jsoncpp.cmake b/3rdparty/jsoncpp/jsoncpp.cmake index 2f5b48d428a..efd128c8ede 100644 --- a/3rdparty/jsoncpp/jsoncpp.cmake +++ b/3rdparty/jsoncpp/jsoncpp.cmake @@ -2,6 +2,15 @@ include(ExternalProject) find_package(Git QUIET REQUIRED) +# SYCL builds always force the dynamic (/MD, /MDd) MSVC runtime for the +# whole project regardless of STATIC_WINDOWS_RUNTIME (icx rejects -fsycl +# combined with the static runtime), so jsoncpp must match. +if(BUILD_SYCL_MODULE) + set(JSONCPP_USE_STATIC_RUNTIME OFF) +else() + set(JSONCPP_USE_STATIC_RUNTIME ${STATIC_WINDOWS_RUNTIME}) +endif() + ExternalProject_Add( ext_jsoncpp PREFIX jsoncpp @@ -19,7 +28,7 @@ ExternalProject_Add( -DBUILD_OBJECT_LIBS=OFF -DJSONCPP_WITH_TESTS=OFF -DJSONCPP_USE_CXX11_ABI=${GLIBCXX_USE_CXX11_ABI} - -DJSONCPP_STATIC_WINDOWS_RUNTIME=${STATIC_WINDOWS_RUNTIME} + -DJSONCPP_STATIC_WINDOWS_RUNTIME=${JSONCPP_USE_STATIC_RUNTIME} ${ExternalProject_CMAKE_ARGS_hidden} BUILD_BYPRODUCTS /${Open3D_INSTALL_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}jsoncpp${CMAKE_STATIC_LIBRARY_SUFFIX} diff --git a/3rdparty/libjpeg-turbo/libjpeg-turbo.cmake b/3rdparty/libjpeg-turbo/libjpeg-turbo.cmake index 32094ea9530..03f0b73308b 100644 --- a/3rdparty/libjpeg-turbo/libjpeg-turbo.cmake +++ b/3rdparty/libjpeg-turbo/libjpeg-turbo.cmake @@ -35,7 +35,7 @@ else() message(STATUS "NASM assembler not found - libjpeg-turbo performance may suffer") endif() -if (STATIC_WINDOWS_RUNTIME) +if (STATIC_WINDOWS_RUNTIME AND NOT BUILD_SYCL_MODULE) set(WITH_CRT_DLL OFF) else() set(WITH_CRT_DLL ON) diff --git a/3rdparty/librealsense/librealsense.cmake b/3rdparty/librealsense/librealsense.cmake index b4af1af2ff6..d7aadfc82b8 100644 --- a/3rdparty/librealsense/librealsense.cmake +++ b/3rdparty/librealsense/librealsense.cmake @@ -45,7 +45,25 @@ endif() set(LIBREALSENSE_CMAKE_C_FLAGS "") set(LIBREALSENSE_CMAKE_CXX_FLAGS "") set(LIBREALSENSE_EXTRA_CMAKE_ARGS "") -if(NOT WIN32) +if(WIN32) + # icx (IntelLLVM), used as the CXX/C compiler for Windows SYCL (xpu) builds, + # enforces target-feature checks that MSVC's cl.exe does not: librealsense's + # SSE helper files (sse-align.cpp, sse-pointcloud.cpp, sse imagery) call + # always_inline intrinsics like _mm_shuffle_epi8 without enabling ssse3 for + # the translation unit, which fails to compile under icx with "requires + # target feature 'ssse3'". Explicitly enable ssse3 for icx on Windows; Clang + # accepts -m flags even in its MSVC-compatible ("icx.exe") driver + # mode. Start from the inherited ${CMAKE_CXX_FLAGS} (which already carries + # CMake's standard Windows defaults, e.g. /DWIN32 /D_WINDOWS /EHsc) rather + # than a hardcoded literal, so librealsense's WIN32-guarded code (e.g. + # rostime's sys/timeb.h vs sys/time.h switch) keeps seeing WIN32 defined. + if(BUILD_SYCL_MODULE) + list(APPEND LIBREALSENSE_EXTRA_CMAKE_ARGS + "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS} -mssse3" + "-DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS} -mssse3" + ) + endif() +else() if(LIBUSB1_CMAKE_C_FLAGS_EXTRA) set(LIBREALSENSE_CMAKE_C_FLAGS "${LIBUSB1_CMAKE_C_FLAGS_EXTRA}") list(APPEND LIBREALSENSE_EXTRA_CMAKE_ARGS "-DCMAKE_C_FLAGS=${LIBUSB1_CMAKE_C_FLAGS_EXTRA}") @@ -55,6 +73,7 @@ if(NOT WIN32) if(LIBUSB1_CMAKE_CXX_FLAGS_EXTRA) set(LIBREALSENSE_CMAKE_CXX_FLAGS "${LIBREALSENSE_CMAKE_CXX_FLAGS} ${LIBUSB1_CMAKE_CXX_FLAGS_EXTRA}") endif() + list(APPEND LIBREALSENSE_EXTRA_CMAKE_ARGS "-DCMAKE_CXX_FLAGS=${LIBREALSENSE_CMAKE_CXX_FLAGS}") endif() ExternalProject_Add( @@ -84,7 +103,6 @@ ExternalProject_Add( -DCMAKE_POLICY_VERSION_MINIMUM=3.5 # Syncing GLIBCXX_USE_CXX11_ABI for MSVC causes problems, but directly # checking CXX_COMPILER_ID is not supported. - $,"",-DCMAKE_CXX_FLAGS=${LIBREALSENSE_CMAKE_CXX_FLAGS}> $<$:-DBUILD_WITH_OPENMP=OFF> $<$:-DHWM_OVER_XU=OFF> $<$:-DBUILD_WITH_STATIC_CRT=${STATIC_WINDOWS_RUNTIME}> diff --git a/3rdparty/vtk/vtk_build.cmake b/3rdparty/vtk/vtk_build.cmake index eb8430e8e46..062580d0655 100644 --- a/3rdparty/vtk/vtk_build.cmake +++ b/3rdparty/vtk/vtk_build.cmake @@ -313,7 +313,12 @@ else() #### download prebuilt vtk ) set(VTK_SHA256 28e36654ed18aa9f668a0486a6c3d26a0ca6cf6a593dbd15be4736b40880a82b) elseif(WIN32) - if (STATIC_WINDOWS_RUNTIME) + # Note: when BUILD_SYCL_MODULE is ON, Open3D's own CMakeLists.txt + # forces the dynamic (/MD, /MDd) MSVC runtime for the whole project + # regardless of STATIC_WINDOWS_RUNTIME (icx rejects -fsycl combined + # with the static runtime). The prebuilt VTK archive must match, or + # linking fails with LNK2038 "RuntimeLibrary mismatch" errors. + if (STATIC_WINDOWS_RUNTIME AND NOT BUILD_SYCL_MODULE) set(VTK_URL https://github.com/isl-org/open3d_downloads/releases/download/vtk/vtk_${VTK_VERSION}_win_staticrt.tar.gz ) diff --git a/3rdparty/webrtc/webrtc_download.cmake b/3rdparty/webrtc/webrtc_download.cmake index 0820579de9e..c5c9ab78b7b 100644 --- a/3rdparty/webrtc/webrtc_download.cmake +++ b/3rdparty/webrtc/webrtc_download.cmake @@ -19,12 +19,12 @@ if (APPLE) ) set(WEBRTC_SHA256 3c2592a3bd9efcee591924007857342fec3753e2ae68695baeb2b8774f0e3abc) elseif (WIN32) - if (BUILD_SHARED_LIBS AND STATIC_WINDOWS_RUNTIME) + if (BUILD_SHARED_LIBS AND STATIC_WINDOWS_RUNTIME AND NOT BUILD_SYCL_MODULE) message(FATAL_ERROR "Pre-built WebRTC does not support " "BUILD_SHARED_LIBS=ON with STATIC_WINDOWS_RUNTIME=ON. Use " "STATIC_WINDOWS_RUNTIME=OFF or BUILD_WEBRTC_FROM_SOURCE=ON.") endif() - if(STATIC_WINDOWS_RUNTIME) + if(STATIC_WINDOWS_RUNTIME AND NOT BUILD_SYCL_MODULE) set(WEBRTC_DEBUG_TAG Debug_mt) set(WEBRTC_DEBUG_SHA256 b537cce72f758fbcd214fbca80ecfb26228d23c728119abc499c4b333e5f0786) set(WEBRTC_RELEASE_TAG Release_mt) @@ -59,13 +59,14 @@ else() # Linux set(WEBRTC_URL ${WEBRTC_BASE_URL}/webrtc_${WEBRTC_VER}_linux_cxx-abi-1.tar.xz ) - set(WEBRTC_SHA256 0209f722974fa7b9da9d1c8e279694cf2c4db81e079a325bcadb1b6e0c3b6981) # 1b529bf448d5abd07ec1f8d310ee5c94bd79e84fe563ae1562420f8e478cc202 + set(WEBRTC_SHA256 0209f722974fa7b9da9d1c8e279694cf2c4db81e079a325bcadb1b6e0c3b6981) endif() if(WIN32 AND WEBRTC_MULTI_CONFIG) # ExternalProject_Add cannot vary URL per config; use add_custom_command + webrtc_fetch_variant.cmake. set(WEBRTC_PREBUILT_ROOT "${CMAKE_BINARY_DIR}/webrtc/$") set(WEBRTC_STAMP "${WEBRTC_PREBUILT_ROOT}/webrtc_fetch.stamp") + set(WEBRTC_LIB_DIR "${WEBRTC_PREBUILT_ROOT}/lib") add_custom_command( OUTPUT "${WEBRTC_STAMP}" COMMAND ${CMAKE_COMMAND} @@ -74,11 +75,13 @@ if(WIN32 AND WEBRTC_MULTI_CONFIG) "-DDEST=${WEBRTC_PREBUILT_ROOT}" "-DSTAMP=${WEBRTC_STAMP}" -P "${CMAKE_CURRENT_LIST_DIR}/webrtc_fetch_variant.cmake" + BYPRODUCTS + ${WEBRTC_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}webrtc${CMAKE_STATIC_LIBRARY_SUFFIX} + ${WEBRTC_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}webrtc_extra${CMAKE_STATIC_LIBRARY_SUFFIX} COMMENT "Downloading prebuilt WebRTC ($)" VERBATIM ) add_custom_target(ext_webrtc_all DEPENDS "${WEBRTC_STAMP}") - set(WEBRTC_LIB_DIR "${WEBRTC_PREBUILT_ROOT}/lib") else() ExternalProject_Add( ext_webrtc @@ -90,13 +93,14 @@ else() CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" - BUILD_BYPRODUCTS "" + BUILD_BYPRODUCTS + /lib/${CMAKE_STATIC_LIBRARY_PREFIX}webrtc${CMAKE_STATIC_LIBRARY_SUFFIX} + /lib/${CMAKE_STATIC_LIBRARY_PREFIX}webrtc_extra${CMAKE_STATIC_LIBRARY_SUFFIX} ) ExternalProject_Get_Property(ext_webrtc SOURCE_DIR) # Prebuilt layout: flat include/ and lib/ at archive root (M149 packages). set(WEBRTC_PREBUILT_ROOT ${SOURCE_DIR}) set(WEBRTC_LIB_DIR ${WEBRTC_PREBUILT_ROOT}/lib) - add_custom_target(ext_webrtc_all) add_dependencies(ext_webrtc_all ext_webrtc) endif() diff --git a/3rdparty/zeromq/zeromq_build.cmake b/3rdparty/zeromq/zeromq_build.cmake index f0bf964655d..d5d2b119e4a 100644 --- a/3rdparty/zeromq/zeromq_build.cmake +++ b/3rdparty/zeromq/zeromq_build.cmake @@ -5,14 +5,22 @@ include(ExternalProject) # Define the compile flags for Windows if(WIN32) - set(WIN_CMAKE_ARGS "-DCMAKE_CXX_FLAGS_DEBUG=$,/MTd,/MDd> ${CMAKE_CXX_FLAGS_DEBUG_INIT}" - "-DCMAKE_CXX_FLAGS_RELEASE=$,/MT,/MD> ${CMAKE_CXX_FLAGS_RELEASE_INIT}" - "-DCMAKE_CXX_FLAGS_RELWITHDEBINFO=$,/MT,/MD> ${CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT}" - "-DCMAKE_CXX_FLAGS_MINSIZEREL=$,/MT,/MD> ${CMAKE_CXX_FLAGS_MINSIZEREL_INIT}" - "-DCMAKE_C_FLAGS_DEBUG=$,/MTd,/MDd> ${CMAKE_C_FLAGS_DEBUG_INIT}" - "-DCMAKE_C_FLAGS_RELEASE=$,/MT,/MD> ${CMAKE_C_FLAGS_RELEASE_INIT}" - "-DCMAKE_C_FLAGS_RELWITHDEBINFO=$,/MT,/MD> ${CMAKE_C_FLAGS_RELWITHDEBINFO_INIT}" - "-DCMAKE_C_FLAGS_MINSIZEREL=$,/MT,/MD> ${CMAKE_C_FLAGS_MINSIZEREL_INIT}" + # SYCL builds always force the dynamic (/MD, /MDd) MSVC runtime for the + # whole project regardless of STATIC_WINDOWS_RUNTIME (icx rejects + # -fsycl combined with the static runtime), so zeromq must match. + if(BUILD_SYCL_MODULE) + set(ZEROMQ_USE_STATIC_RUNTIME OFF) + else() + set(ZEROMQ_USE_STATIC_RUNTIME ${STATIC_WINDOWS_RUNTIME}) + endif() + set(WIN_CMAKE_ARGS "-DCMAKE_CXX_FLAGS_DEBUG=$,/MTd,/MDd> ${CMAKE_CXX_FLAGS_DEBUG_INIT}" + "-DCMAKE_CXX_FLAGS_RELEASE=$,/MT,/MD> ${CMAKE_CXX_FLAGS_RELEASE_INIT}" + "-DCMAKE_CXX_FLAGS_RELWITHDEBINFO=$,/MT,/MD> ${CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT}" + "-DCMAKE_CXX_FLAGS_MINSIZEREL=$,/MT,/MD> ${CMAKE_CXX_FLAGS_MINSIZEREL_INIT}" + "-DCMAKE_C_FLAGS_DEBUG=$,/MTd,/MDd> ${CMAKE_C_FLAGS_DEBUG_INIT}" + "-DCMAKE_C_FLAGS_RELEASE=$,/MT,/MD> ${CMAKE_C_FLAGS_RELEASE_INIT}" + "-DCMAKE_C_FLAGS_RELWITHDEBINFO=$,/MT,/MD> ${CMAKE_C_FLAGS_RELWITHDEBINFO_INIT}" + "-DCMAKE_C_FLAGS_MINSIZEREL=$,/MT,/MD> ${CMAKE_C_FLAGS_MINSIZEREL_INIT}" ) set(lib_name libzmq) if(CMAKE_VS_PLATFORM_TOOLSET) diff --git a/CMakeLists.txt b/CMakeLists.txt index ba39ca4ef02..56ff8e0c227 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -297,8 +297,8 @@ if (BUILD_SYCL_MODULE AND NOT CMAKE_CXX_COMPILER_ID MATCHES "IntelLLVM") "but got CMAKE_CXX_COMPILER_ID: ${CMAKE_CXX_COMPILER_ID} " "and CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}.") endif() -if (BUILD_SYCL_MODULE AND (NOT UNIX OR APPLE)) - message(FATAL_ERROR "Open3D SYCL support is only available on Linux") +if (BUILD_SYCL_MODULE AND APPLE) + message(FATAL_ERROR "Open3D SYCL support is not available on Apple") endif() if(BUILD_SYCL_MODULE AND NOT GLIBCXX_USE_CXX11_ABI) message(FATAL_ERROR "BUILD_SYCL_MODULE=ON requires GLIBCXX_USE_CXX11_ABI=ON") @@ -517,9 +517,15 @@ if(WIN32) # objects exceeded"). /Zc:inline will remove unreferenced data and functions from object files. add_compile_options($<$:/Zc:inline>) endif() - if (STATIC_WINDOWS_RUNTIME) + if (STATIC_WINDOWS_RUNTIME AND NOT BUILD_SYCL_MODULE) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") else() + # The Intel oneAPI DPC++/C++ compiler (icx) hard-errors ("invalid + # argument 'MT' not allowed with '-fsycl'") when compiling any + # translation unit that has -fsycl enabled together with the static + # (/MT, /MTd) MSVC runtime. SYCL compilation therefore always + # requires the dynamic runtime on Windows, regardless of + # STATIC_WINDOWS_RUNTIME. set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") endif() endif() diff --git a/cmake/Open3DPackaging.cmake b/cmake/Open3DPackaging.cmake index e6ce4a3c15c..b3531a5fcd5 100644 --- a/cmake/Open3DPackaging.cmake +++ b/cmake/Open3DPackaging.cmake @@ -26,6 +26,9 @@ endif() if (BUILD_CUDA_MODULE) set(_sys ${_sys}-cuda) endif() +if (BUILD_SYCL_MODULE) + set(_sys ${_sys}-sycl) +endif() if (NOT MSVC) set(CPACK_STRIP_FILES ON) # Don't strip MSVC Debug build endif() diff --git a/cmake/Open3DSetGlobalProperties.cmake b/cmake/Open3DSetGlobalProperties.cmake index ab34eb8affc..8571fc87776 100644 --- a/cmake/Open3DSetGlobalProperties.cmake +++ b/cmake/Open3DSetGlobalProperties.cmake @@ -142,12 +142,41 @@ function(open3d_set_global_properties target) if(MSVC) target_compile_definitions(${target} PRIVATE NOMINMAX _USE_MATH_DEFINES _ENABLE_EXTENDED_ALIGNED_STORAGE) target_compile_options(${target} PRIVATE $<$:/EHsc>) + if(BUILD_SYCL_MODULE) + # The Intel oneAPI DPC++/C++ compiler (icx) fails to parse + # recent MSVC STL versions' header (pulled in + # transitively by oneDPL's , which is + # used by SYCL kernels for host-side algorithms), which + # implements a work-stealing deque annotated with the + # concurrency SAL macro `_Guarded_by_`. icx/clang-cl does not + # expand this macro the same way cl.exe does, causing + # "error: unknown type name '_Guarded_by_'". Since this macro + # is purely a static-analysis annotation (a no-op outside of + # /analyze builds), it is safe to force it to expand to + # nothing for SYCL translation units. + # Note: use target_compile_options (not + # target_compile_definitions) because CMake does not reliably + # escape parentheses in compile definitions across + # generators/shells, which can corrupt the flag. Also avoid + # wrapping this in a $ generator + # expression: CMake's generator-expression parser mishandles + # the literal parentheses in the flag text, splitting it into + # multiple separate command-line arguments. + target_compile_options(${target} PRIVATE "-D_Guarded_by_(x)=") + endif() # Multi-thread compile, two ways to enable # Option 1, at build time: cmake --build . --parallel %NUMBER_OF_PROCESSORS% # https://stackoverflow.com/questions/36633074/set-the-number-of-threads-in-a-cmake-build # Option 2, at configure time: add /MP flag, no need to use Option 1 # https://docs.microsoft.com/en-us/cpp/build/reference/mp-build-with-multiple-processes?view=vs-2019 - target_compile_options(${target} PRIVATE $<$:/MP>) + # Note: /MP is not compatible with the Intel oneAPI DPC++/C++ + # compiler (icx) when SYCL offloading (-fsycl) is enabled: icx + # errors with "'-MP' is not supported with offloading enabled". + # Use build-time parallelism (Option 1) instead when + # BUILD_SYCL_MODULE is ON. + if(NOT BUILD_SYCL_MODULE) + target_compile_options(${target} PRIVATE $<$:/MP>) + endif() if(BUILD_GUI) # GLEW and Open3D make direct OpenGL calls and link to opengl32.lib; # Filament needs to link through bluegl.lib. diff --git a/cpp/apps/CMakeLists.txt b/cpp/apps/CMakeLists.txt index de28eb9179f..ef905bafaee 100644 --- a/cpp/apps/CMakeLists.txt +++ b/cpp/apps/CMakeLists.txt @@ -87,10 +87,17 @@ macro(open3d_add_app_gui SRC_DIR APP_NAME TARGET_NAME) # MSVC puts the binary in bin/Open3D/Release/Open3D.exe # so we can't just install() the build results, and need to do them piecemeal. + get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if (IS_MULTI_CONFIG) + set(APP_BINARY_DIR "${APP_DIR}/$") + else() + set(APP_BINARY_DIR "${APP_DIR}") + endif() + install(DIRECTORY "${APP_DIR}/resources" DESTINATION "${CMAKE_INSTALL_PREFIX}/bin/${APP_NAME}" USE_SOURCE_PERMISSIONS) - install(FILES "${APP_DIR}/$/${TARGET_NAME}.exe" + install(FILES "${APP_BINARY_DIR}/${TARGET_NAME}.exe" DESTINATION "${CMAKE_INSTALL_PREFIX}/bin/${APP_NAME}" RENAME "${APP_NAME}.exe") else() diff --git a/cpp/pybind/CMakeLists.txt b/cpp/pybind/CMakeLists.txt index 5a3d8b8893e..d46b68206ae 100644 --- a/cpp/pybind/CMakeLists.txt +++ b/cpp/pybind/CMakeLists.txt @@ -75,9 +75,9 @@ endif() # At `make`: open3d.so (or the equivalents) will be created at # PYTHON_COMPILED_MODULE_DIR. The default location is -# `build/lib/${CMAKE_BUILD_TYPE}/Python/{cpu|cuda}` +# `build/lib/${CMAKE_BUILD_TYPE}/Python/{cpu|cuda|xpu}` set(PYTHON_COMPILED_MODULE_DIR - "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/Python/$,cuda,cpu>") + "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/Python/$,cuda,$,xpu,cpu>>") if (UNIX AND NOT APPLE) # Use RPATH instead of RUNPATH in pybind so that needed libc++.so can find child dependant libc++abi.so in RPATH diff --git a/cpp/pybind/make_python_package.cmake b/cpp/pybind/make_python_package.cmake index aa4171414b0..384e05f7f04 100644 --- a/cpp/pybind/make_python_package.cmake +++ b/cpp/pybind/make_python_package.cmake @@ -23,7 +23,7 @@ foreach(COMPILED_MODULE_PATH ${COMPILED_MODULE_PATH_LIST}) get_filename_component(COMPILED_MODULE_NAME ${COMPILED_MODULE_PATH} NAME) get_filename_component(COMPILED_MODULE_ARCH_DIR ${COMPILED_MODULE_PATH} DIRECTORY) get_filename_component(COMPILED_MODULE_BASE_DIR ${COMPILED_MODULE_ARCH_DIR} DIRECTORY) - foreach(ARCH cpu cuda) + foreach(ARCH cpu cuda xpu) if(IS_DIRECTORY "${COMPILED_MODULE_BASE_DIR}/${ARCH}") file(INSTALL "${COMPILED_MODULE_BASE_DIR}/${ARCH}/" DESTINATION "${PYTHON_PACKAGE_DST_DIR}/open3d/${ARCH}" diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index cb8c4f31d30..69b016855b9 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -52,11 +52,20 @@ endif() open3d_show_and_abort_on_warning(tests) open3d_set_global_properties(tests) # On Windows, running tests from the build folder needs tbb.dll to be in the same folder. +# Use the TBB::tbb namespaced target, since it exists both when TBB is built from +# source (bare "tbb" target, aliased to TBB::tbb) and when it's found via the oneAPI +# TBB package for SYCL builds (only TBB::tbb is defined, no bare "tbb" target). if (WIN32) + get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if (IS_MULTI_CONFIG) + set(TBB_COPY_DEST_DIR "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$/") + else() + set(TBB_COPY_DEST_DIR "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/") + endif() add_custom_command( TARGET tests POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$/" + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ "${TBB_COPY_DEST_DIR}" ) endif() diff --git a/docs/sycl.rst b/docs/sycl.rst index d7737a9b106..540772c521c 100644 --- a/docs/sycl.rst +++ b/docs/sycl.rst @@ -6,7 +6,8 @@ Cross-platform GPU support (SYCL) From v0.19, Open3D provides an experimental SYCL backend for cross-platform GPU support. This backend allows Open3D operations to run on many different GPUs, including integrated GPUs and discrete GPUs from Intel, Nvidia and AMD. We -provide pre-built C++ binaries and Python wheels for Linux (Ubuntu 22.04+). +provide pre-built C++ binaries and Python wheels for Linux (Ubuntu 22.04+) and +Windows 10+. Enabled features ----------------- @@ -15,7 +16,7 @@ Many Tensor API operations and Tensor Geometry operations without custom kernels can now be offloaded to SYCL devices. In addition, HW accelerated raycasting queries in :py:class:`open3d.t.geometry.RayCastingScene` are also supported. You will get an error if an operation is not supported. The implementation is tested -on Linux on Intel integrated and discrete GPUs. Currently, a single GPU +on Linux and Windows on Intel integrated and discrete GPUs. Currently, a single GPU (`SYCL:0`, if available) and the CPU (`SYCL:1` if a GPU is available, else `SYCL:0`) are supported. @@ -30,7 +31,9 @@ and (optionally) SYCL runtime for your `Nvidia `_ GPU. For Python, the wheels will automatically install the DPC++ runtime package -(`dpcpp-cpp-rt`). Make sure to have the `correct drivers installed +(`dpcpp-cpp-rt`) into the same environment. On Windows, Open3D registers those +pip-installed DLL directories at import time (system-wide oneAPI runtimes are +not used). Make sure to have the `correct drivers installed `_ for your GPU. For raycasting on Intel GPUs, you will also need the `intel-level-zero-gpu-raytracing` package. @@ -48,6 +51,13 @@ raycasting on Intel GPUs, you will also need the - `Python 3.14 `__ - `C++ x86_64 `__ + * - Windows SYCL + - `Python 3.10 `__ + - `Python 3.11 `__ + - `Python 3.12 `__ + - `Python 3.13 `__ + - `Python 3.14 `__ + Usage ------ diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt index a690bf2eda7..f4643548a27 100644 --- a/examples/cpp/CMakeLists.txt +++ b/examples/cpp/CMakeLists.txt @@ -121,10 +121,15 @@ include(ProcessorCount) ProcessorCount(NPROC) # build-examples-iteratively is used to conserve space on CI machine. +# NOTE: CMAKE_BINARY_DIR cannot be forwarded via -D here: CMake's script mode +# (cmake -P) always resets CMAKE_BINARY_DIR/CMAKE_SOURCE_DIR/CMAKE_CURRENT_BINARY_DIR +# to the script's invocation directory, silently ignoring any -D override. Use a +# differently-named variable (EXAMPLE_TOP_BUILD_DIR) instead so the script can +# reliably locate the top-level build tree regardless of its own working directory. add_custom_target(build-examples-iteratively COMMAND ${CMAKE_COMMAND} -DEXAMPLE_TARGETS="${EXAMPLE_TARGETS}" - -DCMAKE_BINARY_DIR="${CMAKE_BINARY_DIR}" + -DEXAMPLE_TOP_BUILD_DIR="${CMAKE_BINARY_DIR}" -DEXAMPLE_BIN_DIR="${EXAMPLE_BIN_DIR}" -DCMAKE_BUILD_TYPE="$" -DNPROC="${NPROC}" diff --git a/examples/cpp/iterative_build_examples.cmake b/examples/cpp/iterative_build_examples.cmake index 1414ee52c47..58d7d4e3b3c 100644 --- a/examples/cpp/iterative_build_examples.cmake +++ b/examples/cpp/iterative_build_examples.cmake @@ -1,17 +1,20 @@ +# NOTE: use EXAMPLE_TOP_BUILD_DIR (not CMAKE_BINARY_DIR) as the build tree root. +# CMake script mode (-P) always resets CMAKE_BINARY_DIR to this script's own +# invocation directory, ignoring any -D override, so it cannot be used here. string(REPLACE " " ";" EXAMPLE_TARGETS_LIST "${EXAMPLE_TARGETS}") foreach(EXAMPLE_TARGET ${EXAMPLE_TARGETS_LIST}) message(STATUS "[Iterative example build] building: ${EXAMPLE_TARGET}.") execute_process( COMMAND ${CMAKE_COMMAND} --build . --verbose --config ${CMAKE_BUILD_TYPE} --target ${EXAMPLE_TARGET} --parallel ${NPROC} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + WORKING_DIRECTORY ${EXAMPLE_TOP_BUILD_DIR} ) message(STATUS "[Iterative example build] deleting: ${EXAMPLE_TARGET}.") execute_process( COMMAND ${CMAKE_COMMAND} -E remove_directory ${EXAMPLE_BIN_DIR} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + WORKING_DIRECTORY ${EXAMPLE_TOP_BUILD_DIR} ) execute_process( COMMAND ${CMAKE_COMMAND} -E make_directory ${EXAMPLE_BIN_DIR} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + WORKING_DIRECTORY ${EXAMPLE_TOP_BUILD_DIR} ) endforeach() diff --git a/python/open3d/__init__.py b/python/open3d/__init__.py index 87608701d5c..d5e94f27119 100644 --- a/python/open3d/__init__.py +++ b/python/open3d/__init__.py @@ -16,6 +16,7 @@ import os import sys import re +import site os.environ["KMP_DUPLICATE_LIB_OK"] = "True" # Enable thread composability manager to coordinate Intel OpenMP and TBB threads. Only works with Intel OpenMP. @@ -27,8 +28,32 @@ import warnings from open3d._build_config import _build_config +_added_dll_dirs = [] if sys.platform == "win32": # Unix: Use rpath to find libraries _win32_dll_dir = os.add_dll_directory(str(Path(__file__).parent)) + # SYCL wheels depend on Intel DPC++ runtime packages (dpcpp-cpp-rt) installed + # in the same environment. Their DLLs live under site-packages/*.data/... + if _build_config["BUILD_SYCL_MODULE"]: + _intel_pip_dll_dirs = set() + _site_package_roots = [Path(_p) for _p in site.getsitepackages()] + _user_site = site.getusersitepackages() + if _user_site: + _site_package_roots.append(Path(_user_site)) + for _site_root in _site_package_roots: + if not _site_root.is_dir(): + continue + for _lib_bin in _site_root.glob("*.data/data/Library/bin"): + if not _lib_bin.is_dir(): + continue + _intel_pip_dll_dirs.add(_lib_bin) + for _child in _lib_bin.iterdir(): + if _child.is_dir(): + _intel_pip_dll_dirs.add(_child) + for _p in sorted(_intel_pip_dll_dirs): + try: + _added_dll_dirs.append(os.add_dll_directory(str(_p))) + except Exception: + pass __DEVICE_API__ = "cpu" if _build_config["BUILD_CUDA_MODULE"]: @@ -85,7 +110,7 @@ ) except OSError as os_error: warnings.warn( - f"Open3D was built with CUDA support, but an error ocurred while loading the Open3D CUDA Python bindings. This is usually because the CUDA libraries could not be found. Check your CUDA installation. Falling back to the CPU pybind library. Reported error: {os_error}.", + f"Open3D was built with CUDA support, but an error occurred while loading the Open3D CUDA Python bindings. This is usually because the CUDA libraries could not be found. Check your CUDA installation. Falling back to the CPU pybind library. Reported error: {os_error}.", ImportWarning, ) except StopIteration: @@ -96,6 +121,34 @@ ImportWarning, ) +if _build_config["BUILD_SYCL_MODULE"]: + try: + from open3d.xpu.pybind import ( + core, + camera, + data, + geometry, + io, + pipelines, + utility, + t, + ) + from open3d.xpu import pybind + + __DEVICE_API__ = "xpu" + except OSError as os_error: + warnings.warn( + f"Open3D was built with SYCL support, but an error occurred while loading the Open3D SYCL Python bindings. Ensure the DPC++ runtime (dpcpp-cpp-rt) is installed in this Python environment. Falling back to the CPU pybind library. Reported error: {os_error}.", + ImportWarning, + ) + except StopIteration: + warnings.warn( + "Open3D was built with SYCL support, but Open3D SYCL Python " + "binding library not found! Falling back to the CPU Python " + "binding library.", + ImportWarning, + ) + if __DEVICE_API__ == "cpu": from open3d.cpu.pybind import ( core, @@ -211,4 +264,6 @@ def _jupyter_nbextension_paths(): if sys.platform == "win32": _win32_dll_dir.close() + for _d in _added_dll_dirs: + _d.close() del os, sys, CDLL, find_library, Path, warnings, _insert_pybind_names diff --git a/python/open3d/ml/__init__.py b/python/open3d/ml/__init__.py index cf7342e0a27..66c0e11d713 100644 --- a/python/open3d/ml/__init__.py +++ b/python/open3d/ml/__init__.py @@ -9,6 +9,8 @@ import open3d as _open3d if _open3d.__DEVICE_API__ == 'cuda': from open3d.cuda.pybind.ml import * +elif _open3d.__DEVICE_API__ == 'xpu': + from open3d.xpu.pybind.ml import * else: from open3d.cpu.pybind.ml import * diff --git a/python/open3d/ml/contrib/__init__.py b/python/open3d/ml/contrib/__init__.py index b883e8024fd..3593e7d9a2a 100644 --- a/python/open3d/ml/contrib/__init__.py +++ b/python/open3d/ml/contrib/__init__.py @@ -8,5 +8,7 @@ import open3d as _open3d if _open3d.__DEVICE_API__ == 'cuda': from open3d.cuda.pybind.ml.contrib import * +elif _open3d.__DEVICE_API__ == 'xpu': + from open3d.xpu.pybind.ml.contrib import * else: from open3d.cpu.pybind.ml.contrib import * diff --git a/python/open3d/visualization/__init__.py b/python/open3d/visualization/__init__.py index cab0cad14ad..4edd59b1766 100644 --- a/python/open3d/visualization/__init__.py +++ b/python/open3d/visualization/__init__.py @@ -10,6 +10,10 @@ if open3d._build_config["BUILD_GUI"]: from open3d.cuda.pybind.visualization import gui from open3d.cuda.pybind.visualization import * +elif open3d.__DEVICE_API__ == "xpu": + if open3d._build_config["BUILD_GUI"]: + from open3d.xpu.pybind.visualization import gui + from open3d.xpu.pybind.visualization import * else: if open3d._build_config["BUILD_GUI"]: from open3d.cpu.pybind.visualization import gui diff --git a/util/install_oneapi_windows.ps1 b/util/install_oneapi_windows.ps1 new file mode 100644 index 00000000000..34da6fd7794 --- /dev/null +++ b/util/install_oneapi_windows.ps1 @@ -0,0 +1,94 @@ +#Requires -RunAsAdministrator +# Install Intel oneAPI C++ essentials for Windows SYCL (xpu) CI builds. +# Pattern from oneapi-src/oneapi-ci (2025.3.0 URLs @ 0804a4c): +# https://github.com/oneapi-src/oneapi-ci/tree/0804a4c9281440d8a91ac0680388b101e5f673ad +# +# Open3D uses the setvars.bat script to set up the oneAPI environment for icx (C +# and C++ compiler). VS 2022 integration is enabled for cmake -T Intel DPC++ toolset support. +param( + [switch]$Verbose +) + +$ErrorActionPreference = 'Stop' +if ($env:OPEN3D_ONEAPI_DEBUG -eq '1') { + $Verbose = $true +} + +# oneAPI 2025.3 offline webimages (oneapi-src/oneapi-ci @ 0804a4c9281440d8a91ac0680388b101e5f673ad) +$ONEAPI_BASEKIT_URL = "https://registrationcenter-download.intel.com/akdlm/IRC_NAS/1f18901e-877d-469d-a41a-a10f11b39336/intel-oneapi-base-toolkit-2025.3.0.372.exe" + +# Default components: +$ONEAPI_WIN_BASE_COMPONENTS = @( + "intel.oneapi.win.cpp-dpcpp-common", + "intel.oneapi.win.tbb.devel", + "intel.oneapi.win.dpl", + "intel.oneapi.win.ipp.devel", + "intel.oneapi.win.mkl.devel" +) -join ":" + +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$PrintPathsScript = Join-Path $ScriptDir 'print_oneapi_windows_paths.ps1' + +$TempRoot = if ($env:RUNNER_TEMP) { $env:RUNNER_TEMP } else { $env:TEMP } +$WorkDir = Join-Path $TempRoot "open3d_oneapi_$([guid]::NewGuid().ToString('N'))" +$InstallLogArchive = Join-Path $TempRoot 'open3d_oneapi_install_logs' +New-Item -ItemType Directory -Force -Path $WorkDir | Out-Null +$InstallExitCode = 0 +Push-Location $WorkDir +try { + Write-Host "Downloading OneAPI webimage..." + curl.exe --output webimage.exe --url $ONEAPI_BASEKIT_URL --retry 5 --retry-delay 5 --fail + Write-Host "Extracting OneAPI webimage..." + $ExtractProc = Start-Process -FilePath ".\webimage.exe" -ArgumentList @( + "-s", "-x", "-f", "webimage_extracted", "--log", "extract.log" + ) -Wait -PassThru -NoNewWindow + if ($ExtractProc.ExitCode -ne 0) { + throw "OneAPI webimage extract failed with exit code $($ExtractProc.ExitCode)" + } + Remove-Item webimage.exe -Force + $Bootstrapper = Join-Path $WorkDir "webimage_extracted\bootstrapper.exe" + if (-not (Test-Path $Bootstrapper)) { + throw "bootstrapper.exe not found after extracting OneAPI webimage" + } + Write-Host "Installing OneAPI components: $ONEAPI_WIN_BASE_COMPONENTS" + if ($Verbose) { + Write-Host "Install work dir: $WorkDir" + Write-Host "NEED_VS2022_INTEGRATION=1 (required for cmake -T Intel DPC++ toolset)" + } + $InstallArgs = @( + "-s", "--action", "install", + "--components=$ONEAPI_WIN_BASE_COMPONENTS", + "--eula=accept", + "-p=NEED_VS2017_INTEGRATION=0", + "-p=NEED_VS2019_INTEGRATION=0", + "-p=NEED_VS2022_INTEGRATION=1", + "--log-dir=$WorkDir" + ) + $InstallProc = Start-Process -FilePath $Bootstrapper -ArgumentList $InstallArgs -Wait -PassThru -NoNewWindow + $InstallExitCode = $InstallProc.ExitCode + if ($InstallExitCode -ne 0) { + throw "OneAPI bootstrapper install failed with exit code $InstallExitCode" + } +} finally { + if ($Verbose -or $InstallExitCode -ne 0) { + if (Test-Path -LiteralPath $WorkDir) { + Write-Host "Archiving installer logs to $InstallLogArchive" + New-Item -ItemType Directory -Force -Path $InstallLogArchive | Out-Null + Copy-Item -Path (Join-Path $WorkDir '*') -Destination $InstallLogArchive -Recurse -Force -ErrorAction SilentlyContinue + Write-Host "See extract.log and installer logs under: $InstallLogArchive" + } + } + Pop-Location + Remove-Item -Recurse -Force $WorkDir -ErrorAction SilentlyContinue +} + +Write-Host "OneAPI bootstrapper reported success (exit code 0)." +if (Test-Path -LiteralPath $PrintPathsScript) { + if ($Verbose) { + & $PrintPathsScript -Verbose + } else { + & $PrintPathsScript + } +} else { + Write-Warning "Missing $PrintPathsScript" +} diff --git a/util/print_oneapi_windows_paths.ps1 b/util/print_oneapi_windows_paths.ps1 new file mode 100644 index 00000000000..af269a57967 --- /dev/null +++ b/util/print_oneapi_windows_paths.ps1 @@ -0,0 +1,139 @@ +# Print Intel oneAPI layout and CMake-related paths on Windows (CI debugging). +# Usage: ./util/print_oneapi_windows_paths.ps1 [-Verbose] +# Env: OPEN3D_ONEAPI_DEBUG=1 enables extra detail (same as -Verbose). +param( + [switch]$Verbose +) + +$ErrorActionPreference = 'Continue' +if ($env:OPEN3D_ONEAPI_DEBUG -eq '1') { + $Verbose = $true +} + +function Write-Section($Title) { + Write-Host "" + Write-Host "========== $Title ==========" +} + +function Test-PathReport($Label, $Path) { + $exists = Test-Path -LiteralPath $Path + $mark = if ($exists) { '[OK]' } else { '[MISSING]' } + Write-Host "$mark $Label" + Write-Host " $Path" + return $exists +} + +function Find-FirstFile($Roots, $Pattern) { + foreach ($root in $Roots) { + if (-not (Test-Path -LiteralPath $root)) { continue } + $hit = Get-ChildItem -LiteralPath $root -Recurse -Filter $Pattern -ErrorAction SilentlyContinue | + Select-Object -First 1 + if ($hit) { return $hit } + } + return $null +} + +$OneApiRoot = 'C:\Program Files (x86)\Intel\oneAPI' +$MklCmakeDir = Join-Path $OneApiRoot 'mkl\latest\lib\cmake\mkl' +$TbbRoot = Join-Path $OneApiRoot 'tbb\latest' +$CompilerLatest = Join-Path $OneApiRoot 'compiler\latest' + +Write-Section 'oneAPI environment variables' +foreach ($name in @( + 'ONEAPI_ROOT', 'MKLROOT', 'TBBROOT', 'CMPLR_ROOT', 'DPL_ROOT', 'IPP_ROOT', + 'CMAKE_PREFIX_PATH', 'PATH' + )) { + $val = [Environment]::GetEnvironmentVariable($name, 'Process') + if (-not $val) { $val = [Environment]::GetEnvironmentVariable($name, 'Machine') } + if (-not $val) { $val = [Environment]::GetEnvironmentVariable($name, 'User') } + if ($name -eq 'PATH' -and $val) { + Write-Host "${name}: (length $($val.Length); use -Verbose for Intel entries)" + if ($Verbose) { + $val -split ';' | Where-Object { $_ -match 'Intel|oneAPI|icx' } | ForEach-Object { Write-Host " $_" } + } + } elseif ($val) { + Write-Host "${name}=$val" + } else { + Write-Host "${name}=" + } +} + +Write-Section 'oneAPI install tree (Open3D SYCL expectations)' +Test-PathReport 'oneAPI root' $OneApiRoot | Out-Null +Test-PathReport 'MKLConfig.cmake dir' $MklCmakeDir | Out-Null +Test-PathReport 'TBB package root (CMAKE_PREFIX_PATH)' $TbbRoot | Out-Null +Test-PathReport 'DPC++ compiler latest symlink' $CompilerLatest | Out-Null + +$mklConfig = Join-Path $MklCmakeDir 'MKLConfig.cmake' +Test-PathReport 'MKLConfig.cmake' $mklConfig | Out-Null +$tbbConfig = Join-Path $TbbRoot 'lib\cmake\tbb\TBBConfig.cmake' +Test-PathReport 'TBBConfig.cmake' $tbbConfig | Out-Null + +$icx = Join-Path $CompilerLatest 'bin\icx.exe' +Test-PathReport 'icx.exe' $icx | Out-Null + +Write-Section 'OpenCL (Windows SYCL / mkl_sycl link)' +$openClLib = Find-FirstFile @($CompilerLatest) 'OpenCL.lib' +if ($openClLib) { + Write-Host '[OK] OpenCL.lib' + Write-Host " $($openClLib.FullName)" + $incCandidate = Join-Path $openClLib.Directory.Parent.FullName 'include' + Test-PathReport 'OpenCL include (parent/include)' $incCandidate | Out-Null +} else { + Write-Host '[MISSING] OpenCL.lib under compiler\latest' + Write-Host " Search root: $CompilerLatest" +} + +Write-Section 'Visual Studio Intel DPC++ platform toolset (cmake -T)' +$vsRoots = @( + Join-Path $env:ProgramFiles 'Microsoft Visual Studio' + Join-Path ${env:ProgramFiles(x86)} 'Microsoft Visual Studio' +) +$toolsetProps = $null +foreach ($vsRoot in $vsRoots) { + if (-not (Test-Path -LiteralPath $vsRoot)) { continue } + $toolsetProps = Get-ChildItem -LiteralPath $vsRoot -Recurse -ErrorAction SilentlyContinue | + Where-Object { + $_.Name -eq 'Toolset.props' -and + $_.FullName -match '\\PlatformToolsets\\Intel\(R\) oneAPI DPC\+\+ Compiler\\' + } | + Select-Object -First 1 + if ($toolsetProps) { break } +} +if ($toolsetProps) { + Write-Host '[OK] Intel(R) oneAPI DPC++ Compiler Toolset.props' + Write-Host " $($toolsetProps.FullName)" +} else { + Write-Host '[MISSING] Platform toolset Toolset.props (CMake -T may fail at build with MSB8020)' + foreach ($vsRoot in $vsRoots) { + Write-Host " Searched under: $vsRoot" + } +} + +Write-Section 'Suggested CMake configure hints (windows.yml xpu legs)' +Write-Host '-T "Intel(R) oneAPI DPC++ Compiler"' +Write-Host "-DCMAKE_PREFIX_PATH=$MklCmakeDir;$TbbRoot" +if ($openClLib) { + $oclLib = $openClLib.FullName.Replace('\', '/') + $oclInc = (Join-Path $openClLib.Directory.Parent.FullName 'include').Replace('\', '/') + Write-Host "-DOpenCL_LIBRARY=$oclLib" + Write-Host "-DOpenCL_INCLUDE_DIR=$oclInc" +} else { + Write-Host '-DOpenCL_LIBRARY=' +} + +if ($Verbose) { + Write-Section 'Directory listing (verbose)' + foreach ($sub in @('compiler', 'mkl', 'tbb', 'dpl', 'ipp')) { + $p = Join-Path $OneApiRoot $sub + if (Test-Path -LiteralPath $p) { + Write-Host "--- $p ---" + Get-ChildItem -LiteralPath $p -ErrorAction SilentlyContinue | ForEach-Object { Write-Host " $($_.Name)" } + } + } +} + +Write-Section 'setvars (optional alternative to CMAKE_PREFIX_PATH)' +$setvars = Join-Path $OneApiRoot 'setvars-vcvarsall.bat' +Test-PathReport 'setvars-vcvarsall.bat' $setvars | Out-Null +Write-Host 'Local builds often run: cmd /c "setvars-vcvarsall.bat" vs2022 before cmake.'