Compare commits

..
62 Commits
Author SHA1 Message Date
Daniel 0fcb306c91 Do/release (#2554)
* fixed nightly windows STORAGE_PATH env variable
* fixed release.yml binary/antivirus scan artifact name
2023-05-11 09:26:18 +00:00
Daniel 67a6f40c6c rebase release branch into devel (#2553)
* changed mac release package compiler to clang
* fix mac release runs-on
* updated docs
2023-05-11 08:02:55 +00:00
Daniel aad183b993 Do/release (#2551)
* added dpcpp-sycl-release.env
* upgrade to icx2023.1.0 for windows
* updated compilation.md
* fix macos runner selection in release.yml
* fixed klocwork job
* fixed artifact names in release.yml
2023-05-10 11:17:49 +00:00
Tomasz Pyra 3759bb572d changed package filenames (#2550) 2023-05-09 21:17:34 +02:00
Sven Woop 28f5fa9d07 adding always_inline for Embree SYCL API functions 2023-05-09 11:18:47 +02:00
Florian Reibold dcb283e279 make EMBREE_NO_SPLASH a proper CMake option. 2023-05-03 16:39:17 +02:00
Sven Woop e087eefe5a making ze_rtas_builder_geometry_exp_flag_t opaque by default 2023-05-03 12:40:18 +02:00
Sven Woop 6ac6171b54 updated to latest L0 rtas build API spec 2023-05-03 12:40:18 +02:00
Sven Woop b37b536253 checking if rtas allocation is in 48 bit address range 2023-05-03 10:23:41 +02:00
Sven Woop 658f94ab6c using proper ZE_STRUCTURE_TYPE_RAYTRACING_MEM_ALLOC_EXT_DESC stype for rtas allocations 2023-05-03 10:23:41 +02:00
Sven Woop 8ddad2a3f5 - changed version to 4.1.0
- added support for Intel(R) Data Center GPU Max series to changelog
- removed limitation of support to specific Arc/Flex version, all products are supported now.
- updated DPC++, driver, and compute-runtime versions to use
2023-05-03 10:23:41 +02:00
Sven Woop 36d36e5b6e returning ZE_RESULT_ERROR_INVALID_ENUMERATION error when stype is not as expected 2023-04-28 18:31:10 +02:00
Sven Woop 02d0038a99 properly checking for stype of builder properties and descriptor 2023-04-28 10:11:48 +02:00
Sven Woop 113239e8aa adding Level Zero rtas header from spec 2023-04-28 10:11:48 +02:00
Sven Woop 53e8e0047d updates to compile Level Zero ray tracing builder API to match spec 2023-04-28 10:11:48 +02:00
Sven Woop 2080cc0543 using argument structure in bounds callback for Level Zero ray tracing build API 2023-04-28 10:11:48 +02:00
Sven Woop bdae2bdd04 using standard Level Zero results in Level Zero rtas build API 2023-04-28 10:11:48 +02:00
Sven Woop 8a72fb41fd removing ze_raytracing CI tests 2023-04-28 10:11:48 +02:00
Daniel 627ac7ba2c Do/remove macosx embree tag (#2543)
* fixed macosx embree label issue in CI
* updated base workflow files for macosx CI tests in release/nightly/continuous
2023-04-26 13:29:25 +00:00
Sven Woop 71a9563cd8 Merge pull request #2542 from intel-innersource/swoop/devel
Swoop/devel
2023-04-26 11:28:16 +02:00
Sven Woop f8bcaa2001 cleanups to cornell_box rtas build example 2023-04-26 10:32:28 +02:00
Sven Woop d439076261 only including rttrace.h 2023-04-26 10:24:03 +02:00
Sven Woop 5db1005e8d renamed rtbuild and rttrace API header files 2023-04-26 10:11:35 +02:00
Sven Woop 8c881fb01a returning proper error codes in rtas builder 2023-04-26 09:27:17 +02:00
Sven Woop eb5f9fc707 adding flags to rtas builder properties 2023-04-26 07:34:51 +02:00
Sven Woop 7c7e3eed8b adjusted Level Zero ray tracing Build API struct member names to match spec 2023-04-25 10:58:03 +02:00
Sven Woop 9e2ca6d4e4 adjusted Level Zero ray tracing Build API function names to match spec 2023-04-25 10:16:59 +02:00
Sven Woop d7eb0d2a44 implemented rtas device properties query for L0 ray tracing build API 2023-04-25 09:50:08 +02:00
Sven Woop 2f7f118105 adjusted property query for parallel operation object in L0 ray tracing build API 2023-04-25 07:35:35 +02:00
Sven Woop 90ae80b5fe removed not required update of build arguments 2023-04-25 07:04:26 +02:00
Sven Woop d8e955002f adopted build and size query functions of L0 ray tracing build API 2023-04-24 12:03:34 +02:00
Sven Woop d29232b282 introduced rtas builder concept to L0 ray tracing API 2023-04-24 10:57:45 +02:00
Sven Woop 272f5feb2a using L0 ray tracing API to build acceleration structure for cornell_box test 2023-04-24 09:18:17 +02:00
Werner, Stefan 7723b92932 * Added CMake options for sphere and curve backface culling
* Moved sphere backface culling documentation to the right place
2023-04-19 13:28:07 +02:00
Werner, Stefan 8251272aaf Added EMBREE_BACKFACE_CULLING_SPHERES option
This follows the same method that Cycles uses to ignore backfacing
sphere intersections.
2023-04-19 13:28:07 +02:00
Florian Reibold ee1c56c6bc do not use exception mechanism for BVH build retry due to TBB 2020.3 2023-04-18 13:37:41 +02:00
Florian Reibold c819f3bacd update dpcpp to 20230417 and fix deprecation warnings 2023-04-18 11:46:32 +02:00
Daniel 570d59289c fix config error in generated embree-addtest.cmake (#2536) 2023-04-14 10:37:11 +00:00
Daniel c9ee19a5d2 fix tarball package unpacks into single folder (#2535) 2023-04-05 15:48:31 +02:00
Sven Woop f59c6d3ef1 using proper RT allocation function to allocate RTDispatchGlobals 2023-03-31 09:35:02 +02:00
Sven Woop b2234567b7 fixed issue that caused allocation of RTDispatchGlobals by default 2023-03-30 17:43:46 +02:00
Daniel 619b0e5ea2 build a deliverable testing package (#2532)
- separate cpack test component
 - new ADD_EMBREE_TEST cmake macro
 - moved reference image directly beside test definition files
 - updated package scripts
2023-03-29 17:32:08 +02:00
Sven Woop 9ef2018879 fixed success job 2023-03-16 12:37:46 +01:00
Sven Woop 8de6a5fdf8 updates to compile ze_raytracing builder in isolation in separate repository 2023-03-16 12:37:46 +01:00
Sven Woop baa030dd36 properly destroying parallel build operations 2023-03-16 12:37:46 +01:00
Krzysztof Raszkowski 8b63714aca ci: update gfx-driver internal to ci-neo-025905 2023-03-15 11:24:52 +01:00
Sven Woop dac55b1974 all names of ze_raytracing build API implementation match spec 2023-03-15 10:20:17 +01:00
Sven Woop be3e00be56 fixed interface of some ze_raytracing API functions 2023-03-15 10:20:17 +01:00
Sven Woop 403818c7c0 implemented zeRaytracingAccelFormatCompatibilityExt in ze_raytracing build API 2023-03-15 10:20:17 +01:00
Sven Woop 1bc8b94bbd implemented build flag to skip duplicate any hit shader invokation 2023-03-15 10:20:17 +01:00
Sven Woop 8918ed32db added stype and pNext to ze_raytracing build API implementation descriptors 2023-03-15 10:20:17 +01:00
Sven Woop 6008fdf64e removed rthwifGetSupportedFeatures from ze_raytracing build API 2023-03-15 10:20:17 +01:00
Sven Woop cbf9a336f8 introduced triangle format, quad format, and vertex format in ze_raytracing build API 2023-03-15 10:20:17 +01:00
Daniel 0ee27e4af1 added arm support to changelog and doc (#2524) 2023-03-14 16:49:05 +01:00
Daniel 66e3f8af2b added EMBREE_ISA_NEON2X to embree-config.cmake (#2526) 2023-03-14 12:54:39 +01:00
Tomasz Pyra 957ae983df Minor fixes to performance CI (#2525)
* removed 'perf' tag from A770

* more precise wildcards
2023-03-13 18:27:03 +01:00
Tomasz Pyra df51d78be8 performance-CI update
- use Google Benchmark for testing
- find and use all models from embree-models repo
- use docker_gpu.yml for GPU testing
- schedule cron for daily performance testing
2023-03-10 17:19:02 +01:00
Tomasz Pyra e22d74ec07 Use all models from repo 2023-03-10 16:15:07 +01:00
Daniel b498e2b87e added arm emulation testing to nightly (#2520)
- Increase test timeout of bvh_builder test
- always disable SSE2 for imgui
2023-03-10 10:23:04 +01:00
Sven Woop 825c513d9c turning EMBREE_LEVEL_ZERO on in one CI test 2023-03-10 09:05:24 +01:00
Sven Woop f4a0f38636 fixed success CI task 2023-03-10 09:05:24 +01:00
Florian Reibold 02192dc3f9 update doc and fix intelstyle repo url 2023-03-09 16:17:59 +01:00
880 changed files with 7424 additions and 10125 deletions
+25 -115
View File
@@ -6,7 +6,6 @@ name: continuous
on: [push, workflow_dispatch]
jobs:
####################################################################
# Setup dpcpp and gfx if not already on NAS
####################################################################
@@ -63,62 +62,6 @@ jobs:
################################################################################
###############################################################################
########################################
# ze_raytracing
########################################
linux-ze_raytracing:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@devel
needs: [setup_gfx, setup_dpcpp]
with:
image: embree/ubuntu:22.04
runs-on: '[ "Linux", "docker", "build" ]'
project: embree
env-from-files: ./.github/workflows/dpcpp-sycl-nightly.env ./.github/workflows/gfx-ubuntu22-internal.env
artifact-out: linux-ze_raytracing
artifact-path: ./build
cmd: |
source $DPCPP_ROOT/startup.sh
mkdir build
cd build
cmake -G Ninja -D CMAKE_CXX_COMPILER=clang++ -D CMAKE_C_COMPILER=clang ../kernels/rthwif
cmake --build . --target package
linux-ze_raytracing-test-DG2:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@devel
needs: ["linux-ze_raytracing"]
with:
image: embree/ubuntu:22.04
options: --device=/dev/dri:/dev/dri
runs-on: '[ "Linux", "docker", "dg2" ]'
project: embree
env-from-files: ./.github/workflows/dpcpp-sycl-nightly.env ./.github/workflows/gfx-ubuntu22-internal.env
artifact-in: linux-ze_raytracing
cmd: |
cd build
ctest
windows-ze_raytracing:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows_gpu.yml@devel
needs: [setup_gfx, setup_dpcpp]
with:
runs-on: '[ "Windows", "NAS", "dg2" ]'
project: embree
env-from-files: ./.github/workflows/dpcpp-sycl-nightly.env ./.github/workflows/gfx-windows-internal.env
artifact-path: ./build
artifact-out: windows-ze_raytracing
shell: cmd
cmd: |
call %DPCPP_ROOT%\\startup.bat
mkdir build
cd build
cmake -G Ninja -D CMAKE_BUILD_TYPE=Release -D CMAKE_CXX_COMPILER=clang++ -D CMAKE_C_COMPILER=clang ../kernels/rthwif
cmake --build . --target package
ctest
########################################
# Linux DG2
########################################
@@ -135,7 +78,7 @@ jobs:
artifact-out: linux-DG2-JIT-INTERNAL
artifact-path: ./build .ctest_conf
cmd: |
scripts/test.py configure platform:x64 compiler:dpcpp ispc:ispc1.18.1 isa:SSE2 build:RelWithAssert EMBREE_SYCL_SUPPORT:ON sycl:none tasking:TBB2021.7.0 intensity:4
scripts/test.py configure platform:x64 compiler:dpcpp ispc:ispc1.18.1 isa:SSE2 build:RelWithAssert EMBREE_SYCL_SUPPORT:ON LEVEL_ZERO:ON sycl:none tasking:TBB2021.7.0 intensity:4
scripts/test.py build --debug
scripts/test.py build
@@ -201,54 +144,20 @@ jobs:
scripts/test.py build --debug
scripts/test.py build
linux-DG2-JIT-GPU-BVH-BUILDER:
linux-DG2-JIT-EMBARGO-test:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@devel
needs: [setup_gfx, setup_dpcpp]
needs: ["linux-DG2-JIT-EMBARGO"]
with:
image: embree/ubuntu:22.04
runs-on: '[ "Linux", "docker", "build" ]'
options: --device=/dev/dri:/dev/dri
runs-on: '[ "Linux", "docker", "dg2" ]'
project: embree
env-from-files: ./.github/workflows/dpcpp-sycl-nightly.env ./.github/workflows/gfx-ubuntu22-embargo.env
artifact-out: linux-DG2-JIT-GPU-BVH-BUILDER
artifact-path: ./build .ctest_conf
artifact-in: linux-DG2-JIT-EMBARGO
cmd: |
scripts/test.py configure platform:x64 compiler:dpcpp ispc:ispc1.18.1 isa:SSE2 build:RelWithAssert EMBREE_SYCL_SUPPORT:ON EMBREE_SYCL_GPU_BVH_BUILDER:ON USERGEOM:CONTEXT FILTER_FUNCTION:CONTEXT gfx:EMBARGO sycl:none tasking:TBB2021.7.0 intensity:4
scripts/test.py build --debug
scripts/test.py build
linux-DG2-JIT-PUBLIC-GPU-BVH-BUILDER:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@devel
needs: [setup_gfx, setup_dpcpp]
with:
image: embree/ubuntu:22.04
runs-on: '[ "Linux", "docker", "build" ]'
project: embree
env-from-files: ./.github/workflows/dpcpp-sycl-nightly.env ./.github/workflows/gfx-ubuntu22-public.env
install-gfx-driver: false
artifact-out: linux-DG2-JIT-PUBLIC-GPU-BVH-BUILDER
artifact-path: ./build .ctest_conf
cmd: |
scripts/test.py configure platform:x64 compiler:dpcpp ispc:ispc1.18.1 isa:AVX512 build:RelWithAssert EMBREE_SYCL_SUPPORT:ON EMBREE_SYCL_GPU_BVH_BUILDER:ON USERGEOM:CONTEXT FILTER_FUNCTION:CONTEXT gfx:PUBLIC sycl:none tasking:TBB2021.7.0 intensity:4
scripts/test.py build --debug
scripts/test.py build
# linux-DG2-AOT-INTERNAL-test:
# secrets: inherit
# uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@devel
# needs: ["linux-DG2-AOT-INTERNAL"]
# with:
# image: embree/ubuntu:22.04
# options: --device=/dev/dri:/dev/dri
# runs-on: '[ "Linux", "docker", "dg2" ]'
# project: embree
# env-from-files: ./.github/workflows/dpcpp-sycl-nightly.env ./.github/workflows/gfx-ubuntu22-internal.env
# artifact-in: linux-DG2-AOT-INTERNAL
# cmd: |
# scripts/test.py test --debug
# scripts/test.py test
scripts/test.py test --debug
scripts/test.py test
linux-DG2-JIT-PUBLIC-ICX:
secrets: inherit
@@ -542,7 +451,7 @@ jobs:
########################################
windows-V140:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_windows.yml@devel
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@devel
with:
runs-on: '[ "Windows", "NAS", "build" ]'
cmd: |
@@ -552,7 +461,7 @@ jobs:
windows-V141:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_windows.yml@devel
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@devel
with:
runs-on: '[ "Windows", "NAS", "build" ]'
cmd: |
@@ -562,7 +471,7 @@ jobs:
windows-V142:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_windows.yml@devel
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@devel
with:
runs-on: '[ "Windows", "NAS", "build" ]'
cmd: |
@@ -572,7 +481,7 @@ jobs:
windows-ICX:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_windows.yml@devel
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@devel
with:
runs-on: '[ "Windows", "NAS", "build", "avx512" ]'
cmd: |
@@ -586,15 +495,16 @@ jobs:
################################################################################
################################################################################
########################################
# MacOS
########################################
macosx-ARM-NEON-AVX2:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_macos.yml@devel
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@devel
with:
runs-on: '[ "macOS", "arm", "build" ]'
runs-on: '[ "macOS", "build", "arm" ]'
cmd: |
scripts/test.py configure platform:arm64 build:Debug compiler:CLANG ispc:ispc1.17.0 isa:NEON2X tasking:TBB_HOMEBREW intensity:2
scripts/test.py build
@@ -602,15 +512,14 @@ jobs:
macosx-x64-CLANG:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_macos.yml@devel
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main
with:
runs-on: '[ "macOS", "embree", "build" ]'
runs-on: '[ "macOS", "build", "x86_64" ]'
cmd: |
scripts/test.py configure platform:x64 build:Debug compiler:CLANG ispc:ispc1.18.1 isa:SSE2 tasking:TBB2021.1.1 intensity:2
scripts/test.py build
scripts/test.py test
########################################
# Klockwork
########################################
@@ -632,17 +541,11 @@ jobs:
success:
runs-on: ubuntu-latest
steps:
- name: Success
run: echo Success
needs:
- linux-ze_raytracing
- linux-ze_raytracing-test-DG2
- windows-ze_raytracing
- linux-DG2-JIT-INTERNAL-test
- linux-DG2-JIT-PUBLIC-test
- linux-ATSM-JIT-PUBLIC-test
- linux-DG2-JIT-EMBARGO
- linux-DG2-JIT-EMBARGO-test
- linux-DG2-JIT-PUBLIC-ICX-test
- linux-PVC-1T-JIT-INTERNAL-test
- linux-PVC-2T-JIT-INTERNAL-test
@@ -665,3 +568,10 @@ jobs:
- macosx-ARM-NEON-AVX2
- macosx-x64-CLANG
- linux-GCC-KLOCWORK
if: failure() || cancelled()
steps:
- name: Failure
run: |
echo "::notice title=Success::Workflow failed"
exit 1
+1 -1
View File
@@ -1 +1 @@
DPCPP_VERSION=sycl-nightly/20230304
DPCPP_VERSION=sycl-nightly/20230417
+1
View File
@@ -0,0 +1 @@
DPCPP_VERSION=intel-llvm/sycl-nightly/20230304
+1 -1
View File
@@ -1 +1 @@
GFX_DRIVER_VERSION=neo-builds/ci/master/ci-neo-master-025813/artifacts/linux/ubuntu/22.04
GFX_DRIVER_VERSION=neo-builds/ci/master/ci-neo-master-025905/artifacts/linux/ubuntu/22.04
+40 -25
View File
@@ -562,7 +562,7 @@ jobs:
nightly-windows-x64-RelWithDebInfo-V140-ISPC1_9_2-SSE2-INT:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_windows.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main
with:
cmd: |
python scripts/test.py configure platform:x64 build:RelWithDebInfo compiler:V140 ispc:ispc1.16.1 isa:SSE2 tasking:INT intensity:2
@@ -571,7 +571,7 @@ jobs:
nightly-windows-x64-RelWithDebInfo-V140-ISPC1_9_2-AVX-TBB2019_2:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_windows.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main
with:
cmd: |
python scripts/test.py configure platform:x64 build:RelWithDebInfo compiler:V140 ispc:ispc1.16.1 isa:AVX tasking:TBB2019.2 intensity:4
@@ -580,7 +580,7 @@ jobs:
nightly-windows-Win32-RelWithDebInfo-V140-ISPC1_12_0-SSE2-TBB2020_2:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_windows.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main
with:
cmd: |
python scripts/test.py configure platform:Win32 build:RelWithDebInfo compiler:V140 ispc:ispc1.12.0 isa:SSE2 tasking:TBB2020.2 intensity:2
@@ -589,7 +589,7 @@ jobs:
nightly-windows-x64-RelWithDebInfo-V140-ISPC1_12_0-AVX2-PPL:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_windows.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main
with:
cmd: |
python scripts/test.py configure platform:x64 build:RelWithDebInfo compiler:V140 ispc:ispc1.12.0 isa:AVX2 frequency_level:simd256 tasking:PPL intensity:2
@@ -598,7 +598,7 @@ jobs:
nightly-windows-x64-RelWithDebInfo-V141-ISPC1_13_0-AVX2-TBB2019_9-STATIC:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_windows.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main
with:
cmd: |
python scripts/test.py configure platform:x64 build:RelWithDebInfo compiler:V141 ispc:ispc1.13.0 isa:AVX2 frequency_level:simd128 tasking:TBB2019.9 intensity:2 STATIC_LIB:ON
@@ -607,7 +607,7 @@ jobs:
nightly-windows-x64-RelWithDebInfo-V142-ISPC1_13_0-AVX2-TBB2020_2-STATIC:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_windows.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main
with:
cmd: |
python scripts/test.py configure platform:x64 build:RelWithDebInfo compiler:V142 ispc:ispc1.13.0 isa:AVX2 tasking:TBB2020.2 intensity:2
@@ -616,7 +616,7 @@ jobs:
nightly-windows-x64-RelWithDebInfo-LLVM-CLANG-ISPC1_13_0-AVX2-TBB2019_9-NAMESPACE:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_windows.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main
with:
cmd: |
python scripts/test.py configure platform:x64 build:RelWithDebInfo compiler:LLVM_CLANG ispc:ispc1.13.0 isa:AVX2 tasking:TBB2019.9 intensity:4 api_namespace:myembree
@@ -625,7 +625,7 @@ jobs:
nightly-windows-x64-RelWithDebInfo-ICX2023_0_0-ISPC1_13_0-AVX2-TBB2021_5_0:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_windows.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main
with:
cmd: |
python scripts/test.py configure platform:x64 build:RelWithDebInfo compiler:ICX2023.0.0 ispc:ispc1.13.0 isa:AVX2 frequency_level:simd128 tasking:TBB2021.5.0 intensity:4
@@ -634,7 +634,7 @@ jobs:
nightly-windows-x64-RelWithDebInfo-ICX2023_0_0-ISPC1_13_0-AVX512-TBB2019_9:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_windows.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main
with:
runs-on: '[ "Windows", "NAS", "build", "avx512" ]'
cmd: |
@@ -644,7 +644,7 @@ jobs:
nightly-windows-x64-RelWithDebInfo-ICX2023_0_0-ISPC1_14_1-AVX2-TBB2021_2_0:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_windows.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main
with:
cmd: |
python scripts/test.py configure platform:x64 build:Release compiler:ICX2023.0.0 ispc:ispc1.14.1 isa:AVX2 tasking:TBB2021.2.0 intensity:2
@@ -658,7 +658,7 @@ jobs:
macosx-ARM-NEON:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_macos.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main
with:
runs-on: '[ "macOS", "arm", "build" ]'
cmd: |
@@ -668,9 +668,9 @@ jobs:
macosx-x64-ICX:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_macos.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main
with:
runs-on: '[ "macOS", "build", "embree" ]'
runs-on: '[ "macOS", "build", "x86_64" ]'
cmd: |
scripts/test.py configure platform:x64 build:Debug compiler:ICX2023.0.0 ispc:ispc1.17.0 isa:SSE2 tasking:TBB2021.7.0 intensity:2
scripts/test.py build
@@ -680,9 +680,9 @@ jobs:
nightly-macosx-x64-Debug-CLANG-ISPC1_12_0-SSE2-TBB2021_1_1-NAMESPACE:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_macos.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main
with:
runs-on: '[ "macOS", "embree", "build" ]'
runs-on: '[ "macOS", "build", "x86_64" ]'
cmd: |
scripts/test.py configure platform:x64 build:Debug compiler:CLANG ispc:ispc1.12.0 isa:SSE2 tasking:TBB2021.1.1 intensity:4 api_namespace:myembree maxinstancelevelcount:4
scripts/test.py build
@@ -690,9 +690,9 @@ jobs:
nightly-macosx-x64-Debug-CLANG-ISPC1_13_0-AVX-INT:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_macos.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main
with:
runs-on: '[ "macOS", "embree", "build" ]'
runs-on: '[ "macOS", "build", "x86_64" ]'
cmd: |
scripts/test.py configure platform:x64 build:Debug compiler:CLANG ispc:ispc1.13.0 isa:AVX tasking:INT intensity:4
scripts/test.py build
@@ -700,9 +700,9 @@ jobs:
nightly-macosx-x64-Debug-CLANG-ISPC1_13_0-SSE2-TBB2021_1_1-STATIC:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_macos.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main
with:
runs-on: '[ "macOS", "embree", "build" ]'
runs-on: '[ "macOS", "build", "x86_64" ]'
cmd: |
scripts/test.py configure platform:x64 build:Debug compiler:CLANG ispc:ispc1.13.0 isa:SSE2 tasking:TBB2021.1.1 intensity:4 STATIC_LIB:ON
scripts/test.py build
@@ -712,9 +712,9 @@ jobs:
nightly-macosx-x64-Debug-ICX2023_0_0-ISPC1_13_0-AVX-INT:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_macos.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main
with:
runs-on: '[ "macOS", "embree", "build" ]'
runs-on: '[ "macOS", "build", "x86_64" ]'
cmd: |
scripts/test.py configure platform:x64 build:Debug compiler:ICX2023.0.0 ispc:ispc1.13.0 isa:AVX tasking:INT intensity:4
scripts/test.py build
@@ -722,9 +722,9 @@ jobs:
nightly-macosx-x64-Debug-ICX2023_0_0-ISPC1_13_0-AVX2-TBB2021_1_1:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_macos.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main
with:
runs-on: '[ "macOS", "avx2", "embree", "build" ]'
runs-on: '[ "macOS", "avx2", "build", "x86_64" ]'
cmd: |
scripts/test.py configure platform:x64 build:Debug compiler:ICX2023.0.0 ispc:ispc1.13.0 isa:AVX2 frequency_level:simd256 tasking:TBB2021.1.1 intensity:4
scripts/test.py build
@@ -732,10 +732,25 @@ jobs:
nightly-macosx-x64-Debug-ICX2023_0_0-ISPC1_17_0-AVX2-TBB2021_1_1:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_macos.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main
with:
runs-on: '[ "macOS", "avx2", "embree", "build" ]'
runs-on: '[ "macOS", "avx2", "build", "x86_64" ]'
cmd: |
scripts/test.py configure platform:x64 build:Debug compiler:ICX2023.0.0 ispc:ispc1.17.0 isa:AVX2 frequency_level:simd128 tasking:TBB2021.1.1 intensity:4
scripts/test.py build
scripts/test.py test
########################################
# ARM EMULATION
########################################
linux-ubuntu22_04-arm64:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_docker.yml@main
with:
image: embree/arm64v8-ubuntu:22.04
runs-on: '[ "Linux", "docker-arm", "ARM64" ]'
cmd: |
python scripts/test.py configure platform:x64 build:Debug compiler:GCC isa:NONE tasking:INT intensity:2
python scripts/test.py build
python scripts/test.py test
+37 -35
View File
@@ -3,30 +3,33 @@
name: performance
on: [workflow_dispatch]
on:
schedule:
- cron: '00 01 * * *'
workflow_dispatch:
jobs:
########################################
# Linux build
########################################
linux-build-DG2-DPCPP:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_docker.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@devel
with:
image: embree/ubuntu:20.04
options: --device=/dev/dri:/dev/dri
runs-on: '[ "Linux", "docker", "dg2" ]'
project: embree
env-from-files: ./.github/workflows/dpcpp-none.env ./.github/workflows/gfx-ubuntu22-release.env
artifact-out: linux-DG2-DPCPP
artifact-path: ./build/*.tar.gz .ctest_conf
cmd: |
scripts/test.py configure platform:x64 build:Release compiler:ICX2023.0.0 EMBREE_SYCL_SUPPORT:ON sycl:none gfx:RELEASE ispc:ispc1.18.1 isas:SSE2-SSE42-AVX-AVX2-AVX512 tasking:TBB2021.7.0 intensity:4 package:ZIP
scripts/test.py configure platform:x64 build:Release compiler:ICX2023.0.0 EMBREE_SYCL_SUPPORT:ON sycl:none gfx:RELEASE ispc:ispc1.18.1 isas:SSE2-SSE42-AVX-AVX2-AVX512 tasking:TBB2021.7.0 intensity:4 package:ZIP EMBREE_USE_GOOGLE_BENCHMARK:ON EMBREE_BUILD_GOOGLE_BENCHMARK_FROM_SOURCE:ON EMBREE_NO_SPLASH:ON
scripts/test.py build
scripts/test.py test
linux-build-x86-ICX-ISPC:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_docker.yml@main
@@ -36,104 +39,103 @@ jobs:
artifact-out: linux-build-x86-ICX-ISPC
artifact-path: ./build/*.tar.gz .ctest_conf
cmd: |
scripts/test.py configure platform:x64 build:Release compiler:ICX2023.0.0 ispc:ispc1.18.1 isas:SSE2-SSE42-AVX-AVX2-AVX512 tasking:TBB2021.7.0 intensity:4 package:ZIP
scripts/test.py configure platform:x64 build:Release compiler:ICX2023.0.0 ispc:ispc1.18.1 isas:SSE2-SSE42-AVX-AVX2-AVX512 tasking:TBB2021.7.0 intensity:4 package:ZIP EMBREE_USE_GOOGLE_BENCHMARK:ON EMBREE_BUILD_GOOGLE_BENCHMARK_FROM_SOURCE:ON EMBREE_NO_SPLASH:ON
scripts/test.py build
scripts/test.py test
linux-test-DG2-A750-not_perf:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_docker.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main
needs: ["linux-build-DG2-DPCPP"]
with:
image: embree/ubuntu:22.04
options: --device=/dev/dri:/dev/dri
runs-on: '[ "Linux", "docker", "dg2" ]'
project: embree
env-from-files: ./.github/workflows/dpcpp-none.env ./.github/workflows/gfx-ubuntu22-release.env
artifact-in: linux-DG2-DPCPP
cmd: |
source <(scripts/test.py env --debug)
cd build
tar -xf embree-4.0.0.sycl.x86_64.linux.tar.gz
cd embree-4.0.0.sycl.x86_64.linux
chmod +x embree-vars.sh
./embree-vars.sh
tar -xf embree-?.?.?-beta.sycl.x86_64.linux.tar.gz
cd bin
chmod +x ../embree-vars.sh
../embree-vars.sh
$GITHUB_WORKSPACE/scripts/run-perf.sh gpu
linux-test-DG2-A770:
linux-test-DG2-A770-perf:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_docker.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main
needs: ["linux-build-DG2-DPCPP"]
with:
image: embree/ubuntu:22.04
options: --device=/dev/dri:/dev/dri
runs-on: '[ "Linux", "docker", "A770", "perf" ]'
project: embree
env-from-files: ./.github/workflows/dpcpp-none.env ./.github/workflows/gfx-ubuntu22-release.env
artifact-in: linux-DG2-DPCPP
cmd: |
source <(scripts/test.py env --debug)
cd build
tar -xf embree-4.0.0.sycl.x86_64.linux.tar.gz
cd embree-4.0.0.sycl.x86_64.linux
chmod +x embree-vars.sh
./embree-vars.sh
tar -xf embree-?.?.?-beta.sycl.x86_64.linux.tar.gz
cd bin
chmod +x ../embree-vars.sh
../embree-vars.sh
$GITHUB_WORKSPACE/scripts/run-perf.sh gpu
linux-test-i9-12900k:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/perf.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/perf.yml@devel
needs: ["linux-build-x86-ICX-ISPC"]
with:
runs-on: '[ "Linux", "perf", "vis-perf-i9-12900k-1" ]'
artifact-in: linux-build-x86-ICX-ISPC
cmd: |
cd build
tar -xf embree-4.0.0.x86_64.linux.tar.gz
cd embree-4.0.0.x86_64.linux
cd bin
tar -xf embree-?.?.?.x86_64.linux.tar.gz
cd embree-*.linux/bin
$GITHUB_WORKSPACE/scripts/run-perf.sh cpu
linux-test-x8380-1:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/perf.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/perf.yml@devel
needs: ["linux-build-x86-ICX-ISPC"]
with:
runs-on: '[ "Linux", "perf", "vis-perf-x8380-1" ]'
artifact-in: linux-build-x86-ICX-ISPC
cmd: |
cd build
tar -xf embree-4.0.0.x86_64.linux.tar.gz
cd embree-4.0.0.x86_64.linux
cd bin
tar -xf embree-?.?.?.x86_64.linux.tar.gz
cd embree-*.linux/bin
$GITHUB_WORKSPACE/scripts/run-perf.sh cpu
linux-test-x8280-1:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/perf.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/perf.yml@devel
needs: ["linux-build-x86-ICX-ISPC"]
with:
runs-on: '[ "Linux", "perf", "vis-perf-x8280-1" ]'
artifact-in: linux-build-x86-ICX-ISPC
cmd: |
cd build
tar -xf embree-4.0.0.x86_64.linux.tar.gz
cd embree-4.0.0.x86_64.linux
cd bin
tar -xf embree-?.?.?.x86_64.linux.tar.gz
cd embree-*.linux/bin
$GITHUB_WORKSPACE/scripts/run-perf.sh cpu
linux-test-a3970x-1:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/perf.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/perf.yml@devel
needs: ["linux-build-x86-ICX-ISPC"]
with:
runs-on: '[ "Linux", "perf", "vis-perf-a3970x-1" ]'
artifact-in: linux-build-x86-ICX-ISPC
cmd: |
cd build
tar -xf embree-4.0.0.x86_64.linux.tar.gz
cd embree-4.0.0.x86_64.linux
cd bin
tar -xf embree-?.?.?.x86_64.linux.tar.gz
cd embree-*.linux/bin
$GITHUB_WORKSPACE/scripts/run-perf.sh cpu
+39 -39
View File
@@ -14,40 +14,40 @@ jobs:
# Release Builds
####################################################################
release-windows-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP:
release-windows-x64-Release-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_windows.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main
with:
runs-on: '[ "Windows", "NAS", "build", "avx512" ]'
artifact-out: release-windows-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
artifact-out: release-windows-x64-Release-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
artifact-path: ./build/*.zip
cmd: |
python scripts/test.py configure platform:x64 build:Release compiler:ICX2023.0.0 ispc:ispc1.18.1 isas:SSE2-SSE42-AVX-AVX2-AVX512 tasking:TBB2021.7.0 intensity:4 package:ZIP
python scripts/test.py configure platform:x64 build:Release compiler:ICX2023.1.0 ispc:ispc1.19.0 isas:SSE2-SSE42-AVX-AVX2-AVX512 tasking:TBB2021.9.0 intensity:4 package:ZIP
python scripts/test.py build
python scripts/test.py test
release-macosx-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP:
release-macosx-x64-Release-CLANG-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_macos.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main
with:
runs-on: '[ "macOS", "embree", "sign", "avx2" ]'
artifact-out: release-macosx-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
runs-on: '[ "macOS", "sign", "avx2", "x86_64" ]'
artifact-out: release-macosx-x64-Release-CLANG-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
artifact-path: ./build/*.zip
cmd: |
scripts/test.py configure platform:x64 build:Release compiler:ICX2023.0.0 ispc:ispc1.18.1 isas:SSE2-SSE42-AVX-AVX2 tasking:TBB2021.7.0 intensity:4 package:ZIP
scripts/test.py configure platform:x64 build:Release compiler:CLANG ispc:ispc1.19.0 isas:SSE2-SSE42-AVX-AVX2 tasking:TBB2021.9.0 intensity:4 package:ZIP
scripts/test.py build
scripts/test.py test
release-linux-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP:
release-linux-x64-Release-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/embree_docker.yml@main
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main
with:
image: embree/rockylinux:8.7
runs-on: '[ "Linux", "docker", "avx512" ]'
artifact-out: release-linux-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
artifact-out: release-linux-x64-Release-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
artifact-path: ./build/*.tar.gz
cmd: |
scripts/test.py configure platform:x64 build:Release compiler:ICX2023.0.0 ispc:ispc1.18.1 isas:SSE2-SSE42-AVX-AVX2-AVX512 tasking:TBB2021.7.0 intensity:4 package:ZIP
scripts/test.py configure platform:x64 build:Release compiler:ICX2023.1.0 ispc:ispc1.19.0 isas:SSE2-SSE42-AVX-AVX2-AVX512 tasking:TBB2021.9.0 intensity:4 package:ZIP
scripts/test.py build
scripts/test.py test
@@ -56,17 +56,17 @@ jobs:
# DPC++ Release Builds
####################################################################
release-windows-x64-Release-SYCL-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP:
release-windows-x64-Release-SYCL-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows_gpu.yml@devel
with:
runs-on: '[ "Windows", "NAS", "dg2" ]'
project: embree
env-from-files: ./.github/workflows/dpcpp-none.env ./.github/workflows/gfx-windows-internal.env
artifact-out: release-windows-x64-Release-SYCL-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
artifact-out: release-windows-x64-Release-SYCL-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
artifact-path: ./build/*.zip
cmd: |
python scripts/test.py configure platform:x64 build:Release compiler:ICX2023.0.0 EMBREE_SYCL_SUPPORT:ON sycl:none gfx:RELEASE ispc:ispc1.18.1 isas:SSE2-SSE42-AVX-AVX2-AVX512 tasking:TBB2021.7.0 intensity:4 package:ZIP
python scripts/test.py configure platform:x64 build:Release compiler:ICX2023.1.0 EMBREE_SYCL_SUPPORT:ON sycl:none gfx:RELEASE ispc:ispc1.19.0 isas:SSE2-SSE42-AVX-AVX2-AVX512 tasking:TBB2021.9.0 intensity:4 package:ZIP
python scripts/test.py build
python scripts/test.py test
@@ -83,7 +83,7 @@ jobs:
# python scripts/test.py build
# python scripts/test.py test
release-linux-x64-Release-SYCL-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP:
release-linux-x64-Release-SYCL-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP:
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@devel
with:
@@ -92,10 +92,10 @@ jobs:
runs-on: '[ "Linux", "docker", "dg2" ]'
project: embree
env-from-files: ./.github/workflows/dpcpp-none.env ./.github/workflows/gfx-ubuntu22-release.env
artifact-out: release-linux-x64-Release-SYCL-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
artifact-out: release-linux-x64-Release-SYCL-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
artifact-path: ./build/*.tar.gz
cmd: |
scripts/test.py configure platform:x64 build:Release compiler:ICX2023.0.0 EMBREE_SYCL_SUPPORT:ON sycl:none gfx:RELEASE ispc:ispc1.18.1 isas:SSE2-SSE42-AVX-AVX2-AVX512 tasking:TBB2021.7.0 intensity:4 package:ZIP
scripts/test.py configure platform:x64 build:Release compiler:ICX2023.1.0 EMBREE_SYCL_SUPPORT:ON sycl:none gfx:RELEASE ispc:ispc1.19.0 isas:SSE2-SSE42-AVX-AVX2-AVX512 tasking:TBB2021.9.0 intensity:4 package:ZIP
scripts/test.py build
scripts/test.py test
@@ -105,54 +105,54 @@ jobs:
#####################################################################
binary-analysis:
needs:
- release-windows-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
- release-macosx-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
- release-linux-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
- release-windows-x64-Release-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
- release-macosx-x64-Release-CLANG-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
- release-linux-x64-Release-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/binary_analysis.yml@main
with:
project: embree
artifact-in-windows: release-windows-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
artifact-in-macos: release-macosx-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
artifact-in-linux: release-linux-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
artifact-in-windows: release-windows-x64-Release-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
artifact-in-macos: release-macosx-x64-Release-CLANG-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
artifact-in-linux: release-linux-x64-Release-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
path: "build/*.zip build/*.gz"
antivirus-scan:
needs:
- release-windows-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
- release-macosx-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
- release-linux-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
- release-windows-x64-Release-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
- release-macosx-x64-Release-CLANG-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
- release-linux-x64-Release-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/antivirus_scan.yml@main
with:
project: embree
artifact-in-windows: release-windows-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
artifact-in-macos: release-macosx-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
artifact-in-linux: release-linux-x64-Release-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
artifact-in-windows: release-windows-x64-Release-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
artifact-in-macos: release-macosx-x64-Release-CLANG-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
artifact-in-linux: release-linux-x64-Release-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
path: "build/*.zip build/*.gz"
binary-analysis-dpcpp:
needs:
- release-windows-x64-Release-SYCL-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
- release-linux-x64-Release-SYCL-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
- release-windows-x64-Release-SYCL-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
- release-linux-x64-Release-SYCL-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/binary_analysis.yml@main
with:
project: embree
artifact-in-windows: release-windows-x64-Release-SYCL-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
artifact-in-linux: release-linux-x64-Release-SYCL-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
artifact-in-windows: release-windows-x64-Release-SYCL-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
artifact-in-linux: release-linux-x64-Release-SYCL-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
path: "build/*.zip build/*.gz"
artifact-out-name: "binary-analysis-dpcpp"
antivirus-scan-dpcpp:
needs:
- release-windows-x64-Release-SYCL-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
- release-linux-x64-Release-SYCL-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
- release-windows-x64-Release-SYCL-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
- release-linux-x64-Release-SYCL-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
secrets: inherit
uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/antivirus_scan.yml@main
with:
project: embree
artifact-in-windows: release-windows-x64-Release-SYCL-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
artifact-in-linux: release-linux-x64-Release-SYCL-ICX2023_0_0-ISPC1_18_1-TBB2021_7_0-PACKAGE-ZIP
artifact-in-windows: release-windows-x64-Release-SYCL-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
artifact-in-linux: release-linux-x64-Release-SYCL-ICX2023_1_0-ISPC1_19_0-TBB2021_9_0-PACKAGE-ZIP
path: "build/*.zip build/*.gz"
artifact-out-name: "antivirus-scan-dpcpp"
+13
View File
@@ -1,6 +1,19 @@
Version History
---------------
### Embree 4.1.0
- Added support for Intel® Data Center GPU Max Series.
- Added ARM64 Linux support.
- Added EMBREE_BACKFACE_CULLING_SPHERES cmake option. The new cmake option defaults to OFF.
### Embree 4.0.1
- Improved performance for Tiger Lake, Comet Lake, Cannon Lake, Kaby Lake,
and Skylake client CPUs by using 256 bit SIMD instructions by default.
- Fixed broken motion blur of RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE geometry type.
- Fixed bvh build retry issue for TBB 2020.3
- Added support for Intel® Data Center GPU Flex Series
- Fixed issue on systems without a SYCL platform.
### Embree 4.0.0
- This Embree release adds support for Intel® Arc™ GPUs through SYCL.
- The SYCL support of Embree is in beta phase. Current functionality, quality,
+13 -14
View File
@@ -4,8 +4,8 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.1.0)
SET(EMBREE_VERSION_MAJOR 4)
SET(EMBREE_VERSION_MINOR 0)
SET(EMBREE_VERSION_PATCH 1)
SET(EMBREE_VERSION_MINOR 1)
SET(EMBREE_VERSION_PATCH 0)
IF (EMBREE_SYCL_SUPPORT)
SET(EMBREE_VERSION_NOTE "-beta") # Embree SYCL version is in beta phase
ELSE()
@@ -89,9 +89,7 @@ MARK_AS_ADVANCED(CLEAR CMAKE_CXX_COMPILER)
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/common/cmake" ${CMAKE_MODULE_PATH})
IF (BUILD_TESTING)
INCLUDE(test)
ENDIF()
INCLUDE(test)
set(BUILD_DOC OFF CACHE INTERNAL "build documentation (internal only)")
IF (BUILD_DOC)
@@ -145,7 +143,8 @@ OPTION(EMBREE_STACK_PROTECTOR "When enabled Embree compiles with stack protectio
IF (NOT APPLE)
OPTION(EMBREE_SYCL_SUPPORT "Enables SYCL GPU support." OFF)
IF (EMBREE_SYCL_SUPPORT)
OPTION(EMBREE_NO_SPLASH "Enables/Disables the Embree splash." OFF)
IF (EMBREE_SYCL_SUPPORT AND NOT EMBREE_NO_SPLASH)
MESSAGE(WARNING
"==================================================================================\n"
" The SYCL support of Embree is in beta phase. Current functionality, quality, \n"
@@ -169,11 +168,8 @@ ENDIF()
IF (EMBREE_SYCL_SUPPORT)
ADD_DEFINITIONS("-DEMBREE_SYCL_SUPPORT") # FIXME: only use define from rtcore_config.h
ENDIF()
OPTION(EMBREE_SYCL_GPU_BVH_BUILDER "Using fast GPU-based BVH builder" OFF)
IF (EMBREE_SYCL_GPU_BVH_BUILDER)
SET(EMBREE_STATIC_LIB ON)
ADD_DEFINITIONS("-DEMBREE_SYCL_GPU_BVH_BUILDER")
IF (EMBREE_NO_SPLASH)
ADD_DEFINITIONS("-DEMBREE_NO_SPLASH") # FIXME: only use define from rtcore_config.h
ENDIF()
CMAKE_DEPENDENT_OPTION(EMBREE_SYCL_RT_SIMULATION "Using hardware simulation" OFF "EMBREE_SYCL_SUPPORT" OFF)
@@ -186,13 +182,12 @@ IF (EMBREE_SYCL_RT_SIMULATION)
ENDIF()
CMAKE_DEPENDENT_OPTION(EMBREE_SYCL_RT_VALIDATION_API "Use rt_validation API instead of IGC provided rt_production API" OFF "EMBREE_SYCL_SUPPORT" OFF)
IF (EMBREE_SYCL_RT_VALIDATION_API)
ADD_DEFINITIONS("-DEMBREE_SYCL_RT_VALIDATION_API")
ENDIF()
CMAKE_DEPENDENT_OPTION(EMBREE_SYCL_IMPLICIT_DISPATCH_GLOBALS "Using L0 allocated Dispatch Globals" ON "EMBREE_SYCL_RT_VALIDATION_API" OFF)
IF (NOT EMBREE_SYCL_IMPLICIT_DISPATCH_GLOBALS)
IF (EMBREE_SYCL_RT_VALIDATION_API AND NOT EMBREE_SYCL_IMPLICIT_DISPATCH_GLOBALS)
ADD_DEFINITIONS("-DEMBREE_SYCL_ALLOC_DISPATCH_GLOBALS")
ENDIF()
@@ -211,6 +206,8 @@ ENDIF()
OPTION(EMBREE_RAY_MASK "Enables ray mask support." ON)
OPTION(EMBREE_BACKFACE_CULLING "Enables backface culling.")
OPTION(EMBREE_BACKFACE_CULLING_CURVES "Enables backface culling for curve primitives." OFF)
OPTION(EMBREE_BACKFACE_CULLING_SPHERES "Enables backface culling for sphere primitives." OFF)
OPTION(EMBREE_FILTER_FUNCTION "Enables filter functions." ON)
OPTION(EMBREE_IGNORE_INVALID_RAYS "Ignores invalid rays." OFF) # FIXME: enable by default?
@@ -418,6 +415,9 @@ IF (EMBREE_MAX_ISA STREQUAL "NONE")
ELSE()
OPTION(EMBREE_ISA_AVX512 "Enables AVX512 ISA." ${COMPILER_SUPPORTS_AVX512})
ENDIF()
# Don't use OPTION, but still set them to OFF, so that embree-config.cmake is consisten with its definitions
SET(EMBREE_ISA_NEON OFF)
SET(EMBREE_ISA_NEON2X OFF)
ENDIF()
ELSEIF (EMBREE_MAX_ISA STREQUAL "DEFAULT")
@@ -715,4 +715,3 @@ ENDIF()
##############################################################
INCLUDE(CPack)
+290 -170
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -109,7 +109,7 @@ ELSE()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions") # enable exceptions
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") # enable threads
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msimd128") # enable SIMD intrinsics
ENDIF()
ENDIF()
SET(CMAKE_CXX_FLAGS_DEBUG "")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g") # generate debug information
+6 -2
View File
@@ -22,6 +22,7 @@ SET(EMBREE_ISA_AVX2 @EMBREE_ISA_AVX2@)
SET(EMBREE_ISA_AVX512 @EMBREE_ISA_AVX512@)
SET(EMBREE_ISA_AVX512SKX @EMBREE_ISA_AVX512@) # just for compatibility
SET(EMBREE_ISA_NEON @EMBREE_ISA_NEON@)
SET(EMBREE_ISA_NEON2X @EMBREE_ISA_NEON2X@)
SET(EMBREE_BUILD_TYPE @CMAKE_BUILD_TYPE@)
SET(EMBREE_ISPC_SUPPORT @EMBREE_ISPC_SUPPORT@)
@@ -52,8 +53,6 @@ SET(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR @EMBREE_CURVE_SELF_INTERSECT
SET(EMBREE_DISC_POINT_SELF_INTERSECTION_AVOIDANCE @EMBREE_DISC_POINT_SELF_INTERSECTION_AVOIDANCE@)
SET(EMBREE_MIN_WIDTH @EMBREE_MIN_WIDTH@)
SET(EMBREE_SYCL_GPU_BVH_BUILDER @EMBREE_SYCL_GPU_BVH_BUILDER@)
IF (EMBREE_STATIC_LIB AND (EMBREE_TASKING_SYSTEM STREQUAL "TBB"))
INCLUDE(CMakeFindDependencyMacro)
FIND_DEPENDENCY(TBB)
@@ -101,3 +100,8 @@ IF (EMBREE_SYCL_SUPPORT)
ENDIF()
INCLUDE("${EMBREE_ROOT_DIR}/@EMBREE_CMAKEEXPORT_DIR@/embree-targets.cmake")
SET(EMBREE_TESTING_INTENSITY @EMBREE_TESTING_INTENSITY@)
SET(EMBREE_TESTING_MEMCHECK @EMBREE_TESTING_MEMCHECK@)
SET(EMBREE_TESTING_BENCHMARK @EMBREE_TESTING_BENCHMARK@)
+18 -5
View File
@@ -245,14 +245,25 @@ SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Intel(R) Embree implements high performan
SET(CPACK_PACKAGE_VENDOR "Intel Corporation")
SET(CPACK_PACKAGE_CONTACT embree_support@intel.com)
SET(CPACK_ARCHIVE_COMPONENT_INSTALL ON)
SET(CPACK_COMPONENTS_GROUPING ONE_PER_GROUP)
SET(CPACK_COMPONENT_LIB_DISPLAY_NAME "Library")
SET(CPACK_COMPONENT_LIB_DESCRIPTION "The Embree library including documentation.")
SET(CPACK_COMPONENT_LIB_GROUP "embree")
SET(CPACK_COMPONENT_DEVEL_DISPLAY_NAME "Development")
SET(CPACK_COMPONENT_DEVEL_DESCRIPTION "Header Files for C and ISPC required to develop applications with Embree.")
SET(CPACK_COMPONENT_DEVEL_GROUP "embree")
SET(CPACK_COMPONENT_EXAMPLES_DISPLAY_NAME "Examples")
SET(CPACK_COMPONENT_EXAMPLES_DESCRIPTION "Tutorials demonstrating how to use Embree.")
SET(CPACK_COMPONENT_EXAMPLES_GROUP "embree")
SET(CPACK_COMPONENT_TESTING_DISPLAY_NAME "Testing")
SET(CPACK_COMPONENT_TESTING_DESCRIPTION "Models and reference images for tests")
SET(CPACK_COMPONENT_TESTING_GROUP "embree-testing")
# dependencies between components
#SET(CPACK_COMPONENT_DEVEL_DEPENDS lib)
@@ -275,11 +286,12 @@ IF(WIN32)
ENDIF()
SET(CPACK_GENERATOR ZIP)
SET(PACKAGE_BASE_NAME "${CPACK_PACKAGE_FILE_NAME}")
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.${ARCH}.windows")
SET(CPACK_MONOLITHIC_INSTALL 1)
#SET(CPACK_MONOLITHIC_INSTALL 1)
IF (EMBREE_TESTING_PACKAGE)
SET(PACKAGE_SCRIPT "${PROJECT_SOURCE_DIR}/scripts/package_win.bat")
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND ${PACKAGE_SCRIPT} ${CMAKE_BUILD_TYPE} "${CPACK_PACKAGE_FILE_NAME}.zip")
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND ${PACKAGE_SCRIPT} ${CMAKE_BUILD_TYPE} "${PACKAGE_BASE_NAME}" "${ARCH}")
ENDIF()
# MacOSX specific settings
@@ -289,10 +301,11 @@ ELSEIF(APPLE)
SET(CPACK_RESOURCE_FILE_README "${PROJECT_BINARY_DIR}/README.txt")
SET(CPACK_GENERATOR ZIP)
SET(PACKAGE_BASE_NAME "${CPACK_PACKAGE_FILE_NAME}")
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.x86_64.macosx")
SET(CPACK_MONOLITHIC_INSTALL 1)
#SET(CPACK_MONOLITHIC_INSTALL 1)
IF (EMBREE_TESTING_PACKAGE)
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND "${PROJECT_SOURCE_DIR}/scripts/package_macosx.sh" ${CMAKE_BUILD_TYPE} "${CPACK_PACKAGE_FILE_NAME}.zip" "${EMBREE_SIGN_FILE}")
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND "${PROJECT_SOURCE_DIR}/scripts/package_macosx.sh" ${CMAKE_BUILD_TYPE} "${PACKAGE_BASE_NAME}" "${EMBREE_SIGN_FILE}")
ENDIF()
# Linux specific settings
@@ -300,7 +313,7 @@ ELSE()
SET(CPACK_GENERATOR TGZ)
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.x86_64.linux")
SET(CPACK_MONOLITHIC_INSTALL 1)
#SET(CPACK_MONOLITHIC_INSTALL 1)
IF (EMBREE_TESTING_PACKAGE)
IF (EMBREE_SYCL_SUPPORT)
SET(PACKAGE_SCRIPT "${PROJECT_SOURCE_DIR}/scripts/package_linux_dpcpp.sh")
+510 -246
View File
@@ -1,267 +1,531 @@
## Copyright 2009-2021 Intel Corporation
## SPDX-License-Identifier: Apache-2.0
if (BUILD_TESTING OR EMBREE_TESTING_INSTALL_TESTS)
INCLUDE(CTest)
INCLUDE(CTest)
IF (WIN32)
IF("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC")
SET(MY_PROJECT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}")
if (EMBREE_TESTING_INSTALL_TESTS)
SET(EMBREE_INSTALL_CTESTTESTFILE "${CMAKE_CURRENT_BINARY_DIR}/embree-addtests.cmake")
file(WRITE "${EMBREE_INSTALL_CTESTTESTFILE}" "")
endif()
if (NOT EMBREE_TESTING_PACKAGE_TEST_PROJECT)
IF (WIN32)
IF("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC")
SET(MY_PROJECT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}")
ELSE()
SET(MY_PROJECT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
ENDIF()
ELSE()
SET(MY_PROJECT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
SET(MY_PROJECT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
ENDIF()
ELSE()
SET(MY_PROJECT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
ENDIF()
else()
SET(MY_PROJECT_BINARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../${EMBREE_INSTALL_BINDIR}")
endif()
FIND_PATH(EMBREE_TESTING_MODEL_DIR
NAMES test-models-intensity2.txt
PATHS "${PROJECT_SOURCE_DIR}/models"
DOC "Path to the folder containing the Embree models for regression testing."
NO_DEFAULT_PATHS)
if (NOT EMBREE_TESTING_PACKAGE_TEST_PROJECT)
SET(EMBREE_TESTING_INTENSITY 1 CACHE STRING "Intensity of testing (0 = no testing, 1 = verify and tutorials, 2 = light testing, 3 = intensive testing, 4 = very intensive testing.")
SET_PROPERTY(CACHE EMBREE_TESTING_INTENSITY PROPERTY STRINGS 0 1 2 3 4)
SET(EMBREE_TESTING_ONLY_SYCL_TESTS OFF CACHE BOOL "Run only tests with the sycl support.")
SET(EMBREE_TESTING_MEMCHECK OFF CACHE BOOL "Turns on memory checking for some tests.")
SET(EMBREE_TESTING_BENCHMARK OFF CACHE BOOL "Turns benchmarking on.")
SET(EMBREE_TESTING_BENCHMARK_DATABASE "${PROJECT_BINARY_DIR}" CACHE PATH "Path to database for benchmarking.")
SET(EMBREE_TESTING_PACKAGE OFF CACHE BOOL "Packages release as test.")
SET(EMBREE_TESTING_KLOCWORK OFF CACHE BOOL "Runs Kocwork as test.")
SET(EMBREE_TESTING_SDE OFF CACHE STRING "Uses SDE to run tests for specified CPU.")
SET_PROPERTY(CACHE EMBREE_TESTING_SDE PROPERTY STRINGS OFF pnr nhm wsm snb ivb hsw bdw knl skl skx cnl)
endif()
SET(EMBREE_TESTING_INTENSITY 1 CACHE STRING "Intensity of testing (0 = no testing, 1 = verify and tutorials, 2 = light testing, 3 = intensive testing, 4 = very intensive testing.")
SET_PROPERTY(CACHE EMBREE_TESTING_INTENSITY PROPERTY STRINGS 0 1 2 3 4)
SET(EMBREE_TESTING_ONLY_SYCL_TESTS OFF CACHE BOOL "Run only tests with the sycl support.")
SET(EMBREE_TESTING_MEMCHECK OFF CACHE BOOL "Turns on memory checking for some tests.")
SET(EMBREE_TESTING_BENCHMARK OFF CACHE BOOL "Turns benchmarking on.")
SET(EMBREE_TESTING_BENCHMARK_DATABASE "${PROJECT_BINARY_DIR}" CACHE PATH "Path to database for benchmarking.")
SET(EMBREE_TESTING_PACKAGE OFF CACHE BOOL "Packages release as test.")
SET(EMBREE_TESTING_KLOCWORK OFF CACHE BOOL "Runs Kocwork as test.")
SET(EMBREE_TESTING_SDE OFF CACHE STRING "Uses SDE to run tests for specified CPU.")
SET_PROPERTY(CACHE EMBREE_TESTING_SDE PROPERTY STRINGS OFF pnr nhm wsm snb ivb hsw bdw knl skl skx cnl)
FUNCTION (SET_EMBREE_TEST_PROPERTIES testname)
SET(variants "_cpp;_ispc;_sycl")
foreach(v ${variants})
if (v STREQUAL "_cpp")
SET(v "")
endif()
set(testnamedef "EMBREE_TEST_${testname}${v}_DEFINED")
if(${testnamedef})
SET_TESTS_PROPERTIES(${testname}${v} ${ARGN})
endif()
endforeach()
# checks if the current cmake configuration is compatible with the requirements declared in the optionsfile
MACRO (EMBREE_TEST_CHECK_OPTIONS optionsfile out)
if (EMBREE_TESTING_INSTALL_TESTS)
file(APPEND "${EMBREE_INSTALL_CTESTTESTFILE}" "SET_EMBREE_TEST_PROPERTIES(${testname} ${ARGN}) \n")
endif()
ENDFUNCTION()
# if no optionsfile is found return true (no requirements defined)
SET(${out} 1)
MACRO (ADD_EMBREE_GENERIC_CPP_TEST testname executable)
if((NOT ${EMBREE_SYCL_SUPPORT}) OR (NOT ${EMBREE_TESTING_ONLY_SYCL_TESTS}))
ADD_TEST(NAME ${testname}
WORKING_DIRECTORY "${MY_PROJECT_BINARY_DIR}"
COMMAND ${executable} ${ARGN})
SET(testnamedef EMBREE_TEST_${testname}_DEFINED)
SET(${testnamedef} "1" CACHE INTERNAL "")
endif()
ENDMACRO()
IF(EXISTS "${optionsfile}")
FILE(READ "${optionsfile}" lines)
STRING(REGEX REPLACE "\n" ";" lines "${lines}")
MACRO (ADD_EMBREE_GENERIC_ISPC_TEST testname executable)
if((NOT ${EMBREE_SYCL_SUPPORT}) OR (NOT ${EMBREE_TESTING_ONLY_SYCL_TESTS}))
IF (EMBREE_ISPC_SUPPORT AND EMBREE_RAY_PACKETS)
ADD_TEST(NAME ${testname}_ispc
WORKING_DIRECTORY "${MY_PROJECT_BINARY_DIR}"
COMMAND ${executable}_ispc ${ARGN})
SET(testnamedef EMBREE_TEST_${testname}_ispc_DEFINED)
SET(${testnamedef} "1" CACHE INTERNAL "")
ENDIF()
endif()
ENDMACRO()
FOREACH (line ${lines})
MACRO (ADD_EMBREE_GENERIC_SYCL_TEST testname executable)
IF (EMBREE_SYCL_SUPPORT)
ADD_TEST(NAME ${testname}_sycl
WORKING_DIRECTORY ${MY_PROJECT_BINARY_DIR}
COMMAND ${executable}_sycl ${ARGN})
SET(testnamedef EMBREE_TEST_${testname}_sycl_DEFINED)
SET(${testnamedef} 1 CACHE INTERNAL "")
SET_TESTS_PROPERTIES(${testname}_sycl PROPERTIES TIMEOUT 50)
ENDIF()
ENDMACRO()
# parse line into list
string(REGEX MATCHALL "([^\ ]+\ |[^\ ]+$)" tokens "${line}")
LIST(LENGTH tokens token_count)
IF (NOT ${token_count} EQUAL 3)
message(FATAL_ERROR "illegal .embree_opitons in ${optionsfile} at line ${line}")
ENDIF()
# we require every line to follow the scheme "option [==/!=] value"
LIST(GET tokens 0 option)
LIST(GET tokens 1 comp)
LIST(GET tokens 2 value)
STRING(STRIP ${option} option)
STRING(STRIP ${comp} comp)
STRING(STRIP ${value} value)
IF ("${comp}" STREQUAL "==")
IF (NOT "${${option}}" STREQUAL "${value}")
SET(${out} 0)
ENDIF()
ELSE()
IF ("${${option}}" STREQUAL "${value}")
SET(${out} 0)
ENDIF()
ENDIF()
IF (${out} EQUAL 0)
# Checks if the current cmake configuration is compatible with <condition>
# condition may be a triple of CMAKE_VARIABLE_NAME op VALUE
# supported operators for op are: ==, !=, <, <=, >, >=
FUNCTION (EMBREE_TESTING_CHECK_OPTION out condition)
# parse condition into list
string(REGEX MATCHALL "([^\ ]+\ |[^\ ]+$)" tokens "${condition}")
LIST(LENGTH tokens token_count)
IF (NOT ${token_count} EQUAL 3)
message(FATAL_ERROR "illegal embree_opitons condition: ${condition}")
ENDIF()
# we require every condition to follow the scheme "variable_name op value"
LIST(GET tokens 0 option)
LIST(GET tokens 1 comp)
LIST(GET tokens 2 value)
STRING(STRIP ${option} option)
STRING(STRIP ${comp} comp)
STRING(STRIP ${value} value)
SET(${out} 0 PARENT_SCOPE)
if ("${comp}" STREQUAL "==")
if ("${${option}}" STREQUAL "${value}")
SET(${out} 1 PARENT_SCOPE)
endif()
elseif ("${comp}" STREQUAL "!=")
if (NOT ("${${option}}" STREQUAL "${value}"))
SET(${out} 1 PARENT_SCOPE)
endif()
elseif ("${comp}" STREQUAL ">")
if ("${${option}}" GREATER "${value}")
SET(${out} 1 PARENT_SCOPE)
endif()
elseif ("${comp}" STREQUAL ">=")
if ("${${option}}" GREATER_EQUAL "${value}")
SET(${out} 1 PARENT_SCOPE)
endif()
elseif ("${comp}" STREQUAL "<")
if ("${${option}}" LESS "${value}")
SET(${out} 1 PARENT_SCOPE)
endif()
elseif ("${comp}" STREQUAL "<=")
if ("${${option}}" LESS_EQUAL "${value}")
SET(${out} 1 PARENT_SCOPE)
endif()
else()
message(FATAL_ERROR "Could not parse embree_option condition: ${condition}")
endif()
ENDFUNCTION()
# Checks multiple options from a list with EMBREE_TESTING_CHECK_OPTION
FUNCTION (EMBREE_TESTING_CHECK_OPTIONS_LIST out conditions)
SET(${out} 1 PARENT_SCOPE)
FOREACH (c ${conditions})
EMBREE_TESTING_CHECK_OPTION(myout ${c})
IF (myout EQUAL 0)
SET(${out} 0 PARENT_SCOPE)
BREAK()
ENDIF()
ENDFOREACH()
ENDIF()
ENDMACRO()
MACRO (ADD_EMBREE_GENERIC_CPP_TEST testname executable args)
IF (BUILD_TESTING)
ADD_TEST(NAME ${testname}
WORKING_DIRECTORY "${MY_PROJECT_BINARY_DIR}"
COMMAND ${executable} ${args})
ENDIF()
ENDMACRO()
MACRO (ADD_EMBREE_GENERIC_ISPC_TEST testname executable args)
IF (BUILD_TESTING AND EMBREE_ISPC_SUPPORT AND EMBREE_RAY_PACKETS)
ADD_TEST(NAME ${testname}_ispc
WORKING_DIRECTORY "${MY_PROJECT_BINARY_DIR}"
COMMAND ${executable}_ispc ${args})
ENDIF()
ENDMACRO()
MACRO (ADD_EMBREE_GENERIC_SYCL_TEST testname executable args)
IF (BUILD_TESTING AND EMBREE_SYCL_SUPPORT)
ADD_TEST(NAME ${testname}_sycl
WORKING_DIRECTORY ${MY_PROJECT_BINARY_DIR}
COMMAND ${executable}_sycl ${args})
SET_TESTS_PROPERTIES(${testname}_sycl PROPERTIES TIMEOUT 50)
ENDIF()
ENDMACRO()
MACRO (ADD_EMBREE_TEST testname executable args)
# Check if we should dump the output of this tests
LIST(FIND EMBREE_TESTING_DUMPTESTS ${testname} dumptest)
if (NOT(EMBREE_TESTING_DUMPFORMAT))
SET(EMBREE_TESTING_DUMPFORMAT "tga")
endif()
set(DUMP_ARG "")
IF(NOT(${dumptest} EQUAL -1))
file(MAKE_DIRECTORY "${PROJECT_SOURCE_DIR}/tests/dump")
set(argsx "${args} -o ${PROJECT_SOURCE_DIR}/tests/dump/${testname}.${EMBREE_TESTING_DUMPFORMAT}")
ELSE()
set(argsx ${args})
ENDIF()
# By default add tests for all executables
SET (extra_args ${ARGN})
LIST(APPEND extra_args cpp)
LIST(APPEND extra_args ispc)
LIST(APPEND extra_args sycl)
LIST(REMOVE_DUPLICATES extra_args)
# Exclude exe with '!'
LIST(FIND extra_args "!cpp" p)
if (NOT (${p} EQUAL -1))
LIST(REMOVE_ITEM extra_args "!cpp")
LIST(REMOVE_ITEM extra_args "cpp")
endif()
LIST(FIND extra_args "!ispc" p)
if (NOT (${p} EQUAL -1))
LIST(REMOVE_ITEM extra_args "!ispc")
LIST(REMOVE_ITEM extra_args "ispc")
endif()
LIST(FIND extra_args "!sycl" p)
if (NOT (${p} EQUAL -1))
LIST(REMOVE_ITEM extra_args "!sycl")
LIST(REMOVE_ITEM extra_args "sycl")
endif()
# Add the tests
FOREACH(loopvar ${extra_args})
if((NOT ${EMBREE_SYCL_SUPPORT}) OR (NOT ${EMBREE_TESTING_ONLY_SYCL_TESTS}))
if(${loopvar} STREQUAL "cpp")
ADD_EMBREE_GENERIC_CPP_TEST(${testname} ${executable} ${argsx})
ENDIF()
if(${loopvar} STREQUAL "ispc")
ADD_EMBREE_GENERIC_ISPC_TEST(${testname} ${executable} ${argsx})
ENDIF()
endif()
if(${loopvar} STREQUAL "sycl")
ADD_EMBREE_GENERIC_SYCL_TEST(${testname} ${executable} ${argsx})
ENDIF()
ENDFOREACH()
ENDMACRO()
MACRO (ADD_EMBREE_TUTORIAL_TEST name args)
ADD_EMBREE_TEST(${name} embree_${name} "--compare ${PROJECT_SOURCE_DIR}/tests/models/reference/${name}.exr ${args}" ${ARGN})
ENDMACRO()
MACRO (ADD_EMBREE_PRIMITIVE_TEST xml shader)
EMBREE_TEST_CHECK_OPTIONS("${xml}.embree_options" out)
IF (${out} EQUAL 1)
GET_FILENAME_COMPONENT(FN ${xml} NAME_WE)
SET(testname "prim_${FN}_${shader}")
SET(compare_threshold "55")
# TODO: APPLE with AVX2 enabled have a sphere cap intersection problem with linear curves
IF ((testname MATCHES "prim_curves_linear_flat.*") AND ((testname MATCHES ".*uv") OR testname MATCHES ".*Ng"))
IF (APPLE AND (EMBREE_ISA_AVX2 OR EMBREE_ISA_AVX512))
SET(compare_threshold "200")
ENDIF()
ENDIF()
SET(args "-i ${xml} --shader ${shader} --time 0.5 --compare ${PROJECT_SOURCE_DIR}/tests/primitives/reference/${testname}.exr --compare-threshold ${compare_threshold}")
ADD_EMBREE_TEST(${testname} embree_viewer ${args})
ENDIF()
ENDMACRO()
MACRO (ADD_EMBREE_MODEL_TEST testname executable model reference args)
EMBREE_TEST_CHECK_OPTIONS("${PROJECT_SOURCE_DIR}/tests/models/${model}.embree_options" out)
IF (${out} EQUAL 1)
SET(extra_args ${ARGN})
IF ("${testname}" MATCHES ".*subdiv.*") # skip subdiv models for SYCL mode
LIST(APPEND extra_args !sycl)
ENDIF()
SET(argsx "-c ${PROJECT_SOURCE_DIR}/tests/models/${model} --compare ${PROJECT_SOURCE_DIR}/tests/models/reference/${reference}.exr ${args}")
ADD_EMBREE_TEST(${testname} ${executable} ${argsx} ${extra_args})
ENDIF()
ENDMACRO()
MACRO (ADD_EMBREE_MODELS_TEST model_list_file testname executable reference args)
IF (BUILD_TESTING)
SET(full_model_list_file "${PROJECT_SOURCE_DIR}/tests/models/${model_list_file}")
IF(NOT EXISTS "${full_model_list_file}")
MESSAGE(FATAL_ERROR "File ${PROJECT_SOURCE_DIR}/tests/models/${model_list_file} does not exist!")
ENDIF()
FILE(READ "${full_model_list_file}" models)
STRING(REGEX REPLACE "\n" ";" models "${models}")
FOREACH (model ${models})
IF (model MATCHES "^#")
CONTINUE()
ENDIF()
IF (model MATCHES ".*mblur.*" OR model MATCHES ".*motion_blur.*") # skip mblur models if motion blur is not enabled
IF (NOT EMBREE_SYCL_MBLUR)
CONTINUE()
ENDIF()
ENDIF()
STRING(REGEX REPLACE " .*" "" modelname "${model}")
STRING(REGEX REPLACE "/" "_" modelname "${modelname}")
STRING(REGEX REPLACE ".ecs" "" modelname "${modelname}")
ADD_EMBREE_MODEL_TEST(${testname}_${modelname} ${executable} ${model} ${reference}_${modelname} "${args}")
ENDFOREACH()
ENDIF()
ENDMACRO()
# add klocwork test
IF (EMBREE_TESTING_KLOCWORK)
ADD_TEST(NAME Klocwork-Build WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND "${PROJECT_SOURCE_DIR}/scripts/klocwork_build.sh")
ADD_TEST(NAME Klocwork-Check WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND "${PROJECT_SOURCE_DIR}/scripts/klocwork_check.sh")
SET_TESTS_PROPERTIES(Klocwork-Build PROPERTIES TIMEOUT 2400)
SET_TESTS_PROPERTIES(Klocwork-Check PROPERTIES TIMEOUT 300)
ENDIF()
# add valgrind test
IF (EMBREE_TESTING_MEMCHECK)
find_program( EMBREE_MEMORYCHECK_COMMAND valgrind )
set( EMBREE_MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full --show-leak-kinds=definite --errors-for-leak-kinds=definite --error-exitcode=1" )
IF (NOT EMBREE_MEMORYCHECK_COMMAND)
MESSAGE(FATAL_ERROR "valgrind not found")
ENDIF()
FUNCTION(ADD_MEMCHECK_TEST name binary)
set(memcheck_command "${EMBREE_MEMORYCHECK_COMMAND} ${EMBREE_MEMORYCHECK_COMMAND_OPTIONS}")
separate_arguments(memcheck_command)
add_test(NAME ${name} COMMAND ${memcheck_command} "${MY_PROJECT_BINARY_DIR}/${binary}" ${ARGN})
ENDFUNCTION()
ENDIF()
# looks for ifile in multiple possible locations and outputs a file with absolute path in ofile
FUNCTION (EMBREE_FIND_TEST_FILE ifile ofile errmsgflavor)
if (EXISTS "${ifile}") # abs path, use get_filename_component because it could also be relative to cwd
get_filename_component(absifile "${ifile}" ABSOLUTE)
SET(${ofile} ${absifile} PARENT_SCOPE)
elseif(EXISTS "${PROJECT_SOURCE_DIR}/tests/${ifile}") # testing dir
set(${ofile} "${PROJECT_SOURCE_DIR}/tests/${ifile}" PARENT_SCOPE)
elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${ifile}") # relative to source folder
set(${ofile} "${CMAKE_CURRENT_SOURCE_DIR}/${ifile}" PARENT_SCOPE)
else()
set(${ofile} "" PARENT_SCOPE)
if (errmsgflavor)
message(FATAL_ERROR
"Could not find ${errmsgflavor} \"${ifile}\"\n"
"looked for:\n"
" ${inputfile}\n"
" ${PROJECT_SOURCE_DIR}/tests/${ifile}\n"
" ${CMAKE_CURRENT_SOURCE_DIR}/${ifile}\n"
)
endif()
endif()
ENDFUNCTION()
FUNCTION (EMBREE_ADD_TEST_PARSE_SUBLIST args keyword sublist)
SET(myargs ${args})
SET(mysublist "")
SET(keywords "ECS;XML;NO_REFERENCE;REFERENCE;REFERENCE_SUFFIX;INTENSITY;CONDITION_FILE;CONDITION;ARGS;NO_CPP;NO_ISPC;NO_SYCL;GEN_REFERENCE;")
list(FIND nargs ${keyword} istart)
if (NOT(istart EQUAL -1))
list(LENGTH myargs iend)
foreach(k ${keywords})
list(FIND myargs ${k} i)
if (NOT(i EQUAL -1) AND (i GREATER istart) AND (i LESS iend))
SET(iend ${i})
endif()
endforeach()
MATH(EXPR i "${istart}+1")
while (i LESS iend)
list(GET myargs ${i} elem)
list(APPEND mysublist ${elem})
MATH(EXPR i "${i}+1")
endwhile()
endif()
SET(${sublist} ${mysublist} PARENT_SCOPE)
ENDFUNCTION()
FUNCTION (EMBREE_ADD_TEST_PARSE_FLAG args keyword value)
SET(myargs ${args})
SET(${value} OFF PARENT_SCOPE)
list(FIND nargs ${keyword} i)
if (NOT(i EQUAL -1))
SET(${value} ON PARENT_SCOPE)
endif()
ENDFUNCTION()
# ADD_EMBREE_TEST_ECS(testname exename [ECS <file> | XML <file>] [NO_REFERENCE | REFERENCE <path> | REFERENCE_SUFFIX <suffix>] [INTENSITY <i>] [CONDITION <conds>] [ARGS <args>] [GEN_REFERENCE])
# [ECS <file> | XML <inputfile> | OPTIONS <inputfile>]
# - looks for file and calls the test command with either "-c <inputfile>.ecs" or "-i <inputfile>.xml"
#
# [NO_REFERENCE | REFERENCE <path> | REFERENCE_SUFFIX <suffix>]
# - if not found a reference is will be expected in the same folder as *.ecs with name *.ecs.exename.exr
# - NO_REFERENCE: don't look for a reference (no --compare in test command)
# - REFERENCE <path>: use the reference located in <path>. Same rules aplly as for finding ecs files: absolute or relative to CMAKE_CURRENT_SOURCE_DIR path, must not be located outside the embree root dir.
# - REFERENCE_SUFFIX <suffix>: use the default reference location and name with a suffix before the last file extension, e.g. *.ecs.exename<suffix>.exr
# - if this argument is not specified, looks for
# 1. <inputfile>.exename.exr, or
# 2. <testname>.exr, if no <inputfile> was given
#
# [INTENSITY <i>]
# - default i = 1
# - sets the intensity level for the test, test is only run if ${EMBREE_TESTING_INTENSITY} GREATER_EQUAL i
# - could be done with an *.embree_options file, but this is more flexible, e.g. you can easier share reference images without specifying an absolute path
# - DOES NOT overrite EMBREE_TESTING_INTENSITY, if specified in *.embree_options
#
# [CONDITION_FILE <file>]
# - file containing additional conditions
# - conditions are specified linewise in form of: EMBREE_OPTION op VALUE, where EMBREE_OPTION is a cmake variable used during embree configuration and op is one of ==, !=, <, <=, >, >=
# - if this argument is not specified, looks for
# 1. <inputfile>.embree_options, or
# 2. <testname>.embree_options, if no <inputfile> was given
#
# [CONDITION <conds>]
# - cmake list of additional conditions, specified the same way as in an embree_options file
#
# [ARGS <args>]
# - additional arguments for the test command
#
# [GEN_REFERENCE]
# - writes the reference to the expected location
# - could also be done with the ARGS parameter, but this way we don't have to deal with paths
#
# EXAMPLES
#
# all optional arguments default,
# - looks for points.ecs.embree_options to filter out test by configured options, if not found no restrictions
# - runs for EMBREE_TESTING_INTENSITY >= 1
# - reference will be expected in the same folder as points.ecs with name points.ecs.embree_viewer.exr
#ADD_EMBREE_TEST_ECS(viewer_points embree_viewer "models/xxx/points.ecs") # 1)
#ADD_EMBREE_TEST_ECS(viewer_points embree_viewer "${PROJECT_SOURCE_DIR}/models/xxx/points.ecs") # 2) same as 1) but with absolute path to ecs
#ADD_EMBREE_TEST_ECS(viewer_points embree_viewer "points.ecs") # 3) same as 1) but looks for points.ecs in the ${CMAKE_CURRENT_SOURCE_DIR} i.e. <embree_root>/tutorials/viewer/points.ecs
#ADD_EMBREE_TEST_ECS(viewer_points embree_viewer "models/xxx/points.ecs" ARGS --coherent INTENSITY 2) # 4) same as 1) but runs only at EMBREE_TESTING_INTENSITY >= 2
#ADD_EMBREE_TEST_ECS(viewer_points embree_viewer "models/xxx/points.ecs" REFERENCE_SUFFIX "_quads" ARGS
# --coherent
# --convert-triangles-to-quads INTENSITY 2) # 5) same as 4) but expects reference name points.ecr.embree_viewer_quads.ecs
#ADD_EMBREE_TEST_ECS(viewer_points embree_viewer "models/xxx/points.ecs" REFERENCE "special.exr" ARGS
# --coherent
# --convert-triangles-to-quads INTENSITY 2) # 5) same as 4) but expects reference <embree-root>/tutorials/viewer/special.exr
## 1) - 5) all share the same base input arguments defined in points.ecs as well as the points.ecs.embree_options
#ADD_EMBREE_TEST_ECS(point_geometry embree_point_geometry) # 6) no ecs file, uses point_geometry.embree_options if exists, expects reference ${CMAKE_CURRENT_SOURCE_DIR}/point_geometry.exr
#ADD_EMBREE_TEST_ECS(verify verify NO_REFERENCE) # 7) no ecs file, uses verify.embree_options if exists, no reference
#ADD_EMBREE_TEST_ECS(verify_memcheck verify NO_REFERENCE CONDITIONS "EMBREE_TESTING_MEMCHECK == ON") # 8) same as 7) but with extra condition
FUNCTION (ADD_EMBREE_TEST_ECS testname executable)
SET(nargs ${ARGN})
# disable everything
SET(testnamedef EMBREE_TEST_${testname}_DEFINED)
SET(${testnamedef} "0" CACHE INTERNAL "")
SET(testnamedef EMBREE_TEST_${testname}_ispc_DEFINED)
SET(${testnamedef} "0" CACHE INTERNAL "")
SET(testnamedef EMBREE_TEST_${testname}_sycl_DEFINED)
SET(${testnamedef} "0" CACHE INTERNAL "")
# parsing input file
# ECS mode -> single parameter with filename after ECS keyword
list(FIND nargs "ECS" i)
if (NOT(i EQUAL -1))
SET(inputtype "-c")
MATH(EXPR i "${i}+1")
list(GET nargs ${i} out)
EMBREE_FIND_TEST_FILE("${out}" inputfile "test file")
endif()
# XML mode -> single parameter with filename after XML keyword
list(FIND nargs "XML" i)
if (NOT(i EQUAL -1))
SET(inputtype "-i")
MATH(EXPR i "${i}+1")
list(GET nargs ${i} out)
EMBREE_FIND_TEST_FILE("${out}" inputfile "test file")
endif()
# no filetype keyword -> look for <testname>.ecs/xml
# does not need to be specified
if (NOT inputtype)
EMBREE_FIND_TEST_FILE("${testname}.ecs" inputfile "")
if(inputfile)
SET(inputtype "-c")
endif()
EMBREE_FIND_TEST_FILE("${testname}.ecs" inputfile "")
if(inputfile)
SET(inputtype "-i")
endif()
endif()
# parsing refernce image
# no reference image mode -> no additional parameter to parse
list(FIND nargs "NO_REFERENCE" i)
if (NOT(i EQUAL -1))
SET(no_reference ON)
endif()
# reference suffix mode -> singe parameter with suffix to default reference file name
list(FIND nargs "REFERENCE_SUFFIX" i)
if (NOT(i EQUAL -1))
MATH(EXPR i "${i}+1")
list(GET nargs ${i} out)
EMBREE_FIND_TEST_FILE("${inputfile}.${executable}${out}.exr" referencefile "reference image")
endif()
# reference mode -> singe parameter with absolute path to reference image
list(FIND nargs "REFERENCE" i)
if (NOT(i EQUAL -1))
MATH(EXPR i "${i}+1")
list(GET nargs ${i} out)
EMBREE_FIND_TEST_FILE("${out}" referencefile "reference image")
endif()
# no reference keyword -> look for <testname>.exr and <inputfile>.<executable>.exr respectively
if ((NOT no_reference) AND (NOT referencefile))
if (NOT inputfile)
EMBREE_FIND_TEST_FILE("${testname}.exr" referencefile "reference image")
else()
EMBREE_FIND_TEST_FILE("${inputfile}.${executable}.exr" referencefile "reference image")
endif()
endif()
# parsing intensity
# single integer parameter
SET(intensity 1)
list(FIND nargs "INTENSITY" i)
if (NOT(i EQUAL -1))
MATH(EXPR i "${i}+1")
list(GET nargs ${i} intensity)
endif()
# parsing condition
SET(conditions "")
SET(conditionsfile)
list(FIND nargs "CONDITION_FILE" i)
# condition file -> single parameter to absolute path of conditions file
if (NOT(i EQUAL -1))
list(GET nargs ${i} conditionsfile)
EMBREE_FIND_TEST_FILE("${conditionsfile}" conditionsfile "")
# no <inputfile> specified -> look for <testname>.embree_options
elseif (NOT inputtype)
EMBREE_FIND_TEST_FILE("${testname}.embree_options" conditionsfile "")
# <inputfile> specified -> look for <inputfile>.embree_options
else()
EMBREE_FIND_TEST_FILE("${inputfile}.embree_options" conditionsfile "")
endif()
if (conditionsfile)
file(READ "${conditionsfile}" lines)
string(REGEX REPLACE "\n" ";" conditions "${lines}")
endif()
# parsing additional conditions
EMBREE_ADD_TEST_PARSE_SUBLIST("${nargs}" "CONDITION" extra_conditions)
list(APPEND conditions ${extra_conditions})
# parsing extra args
EMBREE_ADD_TEST_PARSE_SUBLIST("${nargs}" "ARGS" extraargs)
EMBREE_ADD_TEST_PARSE_FLAG("${nargs}" "MEMCHECK" memcheck)
EMBREE_ADD_TEST_PARSE_FLAG("${nargs}" "NO_CPP" no_cpp)
EMBREE_ADD_TEST_PARSE_FLAG("${nargs}" "NO_ISPC" no_ispc)
EMBREE_ADD_TEST_PARSE_FLAG("${nargs}" "NO_SYCL" no_sycl)
EMBREE_ADD_TEST_PARSE_FLAG("${nargs}" "GEN_REFERENCE" gen_reference)
# add the test, if the conditions are met
SET(matchconditions ON)
if (conditions)
EMBREE_TESTING_CHECK_OPTIONS_LIST(out "${conditions}")
if (out EQUAL 0)
SET(matchconditions OFF)
endif()
endif()
# LESS_EQUAL not supported on all CI runners
if (matchconditions AND ((intensity LESS EMBREE_TESTING_INTENSITY) OR (intensity EQUAL EMBREE_TESTING_INTENSITY)))
SET(args "")
if (inputfile)
list(APPEND args "${inputtype} ${inputfile}")
endif()
if (NOT no_reference)
list(APPEND args "--compare ${referencefile}")
endif()
if (gen_reference)
list(APPEND args "-o ${referencefile}")
endif()
foreach(a ${extraargs})
list(APPEND args "${a}")
endforeach()
if (memcheck)
list(PREPEND args "${MY_PROJECT_BINARY_DIR}/${executable}")
list(PREPEND args "${EMBREE_MEMORYCHECK_COMMAND_OPTIONS}")
if((NOT ${EMBREE_SYCL_SUPPORT}) OR (NOT ${EMBREE_TESTING_ONLY_SYCL_TESTS}))
if (NOT(no_cpp))
ADD_EMBREE_GENERIC_CPP_TEST(${testname} ${EMBREE_MEMORYCHECK_COMMAND} ${args})
endif()
if (NOT(no_ispc))
ADD_EMBREE_GENERIC_ISPC_TEST(${testname} ${EMBREE_MEMORYCHECK_COMMAND} ${args})
endif()
endif()
if (NOT(no_sycl))
ADD_EMBREE_GENERIC_SYCL_TEST(${testname} ${EMBREE_MEMORYCHECK_COMMAND} ${args})
endif()
else()
if((NOT ${EMBREE_SYCL_SUPPORT}) OR (NOT ${EMBREE_TESTING_ONLY_SYCL_TESTS}))
if (NOT(no_cpp))
ADD_EMBREE_GENERIC_CPP_TEST(${testname} ${executable} ${args})
endif()
if (NOT(no_ispc))
ADD_EMBREE_GENERIC_ISPC_TEST(${testname} ${executable} ${args})
endif()
endif()
if (NOT(no_sycl))
ADD_EMBREE_GENERIC_SYCL_TEST(${testname} ${executable} ${args})
endif()
endif()
endif()
if (EMBREE_TESTING_INSTALL_TESTS)
if (inputfile)
get_filename_component(inputpath ${inputfile} DIRECTORY)
STRING(REPLACE "${PROJECT_SOURCE_DIR}/" "" inputpath "${inputpath}")
INSTALL(FILES "${inputfile}"
DESTINATION "${CMAKE_INSTALL_TESTDIR}/${inputpath}"
COMPONENT testing)
endif()
if (conditionsfile)
get_filename_component(conditionspath ${conditionsfile} DIRECTORY)
STRING(REPLACE "${PROJECT_SOURCE_DIR}/" "" conditionspath "${conditionspath}")
INSTALL(FILES "${conditionsfile}"
DESTINATION "${CMAKE_INSTALL_TESTDIR}/${conditionspath}"
COMPONENT testing)
endif()
if (referencefile)
get_filename_component(referencepath ${referencefile} DIRECTORY)
STRING(REPLACE "${PROJECT_SOURCE_DIR}/" "" referencepath "${referencepath}")
INSTALL(FILES "${referencefile}"
DESTINATION "${CMAKE_INSTALL_TESTDIR}/${referencepath}"
COMPONENT testing)
endif()
SET(testcall "ADD_EMBREE_TEST_ECS(${testname} ${executable}")
if (inputfile)
STRING(REPLACE "${PROJECT_SOURCE_DIR}/" "" inputfile "${inputfile}")
if (inputtype STREQUAL "-c")
SET(testcall "${testcall} \n ECS ${inputfile}")
elseif (inputtype STREQUAL "-i")
SET(testcall "${testcall} \n XML ${inputfile}")
endif()
endif()
if (no_reference)
SET(testcall "${testcall} \n NO_REFERENCE")
else()
STRING(REPLACE "${PROJECT_SOURCE_DIR}/" "" referencefile "${referencefile}")
SET(testcall "${testcall} \n REFERENCE ${referencefile}")
endif()
SET(testcall "${testcall} \n INTENSITY ${intensity}")
STRING(REPLACE "${PROJECT_SOURCE_DIR}/" "" conditionsfile "${conditionsfile}")
SET(testcall "${testcall} \n CONDITION_FILE ${conditionsfile}")
SET(testcall "${testcall} \n CONDITION ")
foreach(c ${conditions})
SET(testcall "${testcall} \"${c}\"")
endforeach()
SET(testcall "${testcall} \n ARGS ")
foreach(a ${extraargs})
SET(testcall "${testcall} ${a}")
endforeach()
SET(testcall "${testcall})\n\n")
file(APPEND "${EMBREE_INSTALL_CTESTTESTFILE}" "${testcall}")
endif()
ENDFUNCTION()
# add klocwork test
IF (EMBREE_TESTING_KLOCWORK)
ADD_TEST(NAME Klocwork-Build WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND "${PROJECT_SOURCE_DIR}/scripts/klocwork_build.sh")
ADD_TEST(NAME Klocwork-Check WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" COMMAND "${PROJECT_SOURCE_DIR}/scripts/klocwork_check.sh")
SET_TESTS_PROPERTIES(Klocwork-Build PROPERTIES TIMEOUT 2400)
SET_TESTS_PROPERTIES(Klocwork-Check PROPERTIES TIMEOUT 300)
ENDIF()
else()
FUNCTION(ADD_EMBREE_TEST_ECS testname executable)
ENDFUNCTION()
FUNCTION(SET_EMBREE_TEST_PROPERTIES testname)
ENDFUNCTION()
endif()
+2 -25
View File
@@ -212,15 +212,11 @@
#define PRINT2(x,y) embree_cout << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << embree_endl
#define PRINT3(x,y,z) embree_cout << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << ", " << STRING(z) << " = " << (z) << embree_endl
#define PRINT4(x,y,z,w) embree_cout << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << ", " << STRING(z) << " = " << (z) << ", " << STRING(w) << " = " << (w) << embree_endl
#define PRINT5(x,y,z,w,a) embree_cout << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << ", " << STRING(z) << " = " << (z) << ", " << STRING(w) << " = " << (w) << ", " << STRING(a) << " = " << (a) << embree_endl
#define PRINT6(x,y,z,w,a,b) embree_cout << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << ", " << STRING(z) << " = " << (z) << ", " << STRING(w) << " = " << (w) << ", " << STRING(a) << " = " << (a) << ", " << STRING(b) << " = " << (b) << embree_endl
#define UPRINT(x) embree_cout_uniform << STRING(x) << " = " << (x) << embree_endl
#define UPRINT2(x,y) embree_cout_uniform << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << embree_endl
#define UPRINT3(x,y,z) embree_cout_uniform << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << ", " << STRING(z) << " = " << (z) << embree_endl
#define UPRINT4(x,y,z,w) embree_cout_uniform << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << ", " << STRING(z) << " = " << (z) << ", " << STRING(w) << " = " << (w) << embree_endl
#define UPRINT5(x,y,z,w,a) embree_cout_uniform << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << ", " << STRING(z) << " = " << (z) << ", " << STRING(w) << " = " << (w) << ", " << STRING(a) << " = " << (a) << embree_endl
#define UPRINT6(x,y,z,w,a,b) embree_cout_uniform << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << ", " << STRING(z) << " = " << (z) << ", " << STRING(w) << " = " << (w) << ", " << STRING(a) << " = " << (a) << ", " << STRING(b) << " = " << (b) << embree_endl
#if defined(DEBUG) // only report file and line in debug mode
#define THROW_RUNTIME_ERROR(str) \
@@ -365,15 +361,9 @@ __forceinline std::string toString(long long value) {
/// SYCL specific
////////////////////////////////////////////////////////////////////////////////
#if defined(__SYCL_DEVICE_ONLY__)
# define EMBREE_SYCL_SIMD(N) [[intel::reqd_sub_group_size(N)]]
#else
# define EMBREE_SYCL_SIMD(N)
#endif
#if defined(EMBREE_SYCL_SUPPORT) && defined(__SYCL_DEVICE_ONLY__)
#define sycl_printf0(format, ...) { \
static const CONSTANT char fmt[] = format; \
if (get_sub_group_local_id() == SYCL_CTZ::ctz(intel_sub_group_ballot(true))) \
@@ -447,20 +437,7 @@ namespace embree
return cout;
}
#if defined(__WIN32__) and defined(__INTEL_LLVM_COMPILER)
inline sycl_ostream_ operator <<(sycl_ostream_ cout, size_t i)
{
if (cout.uniform) {
if (get_sub_group_local_id() == SYCL_CTZ::ctz(intel_sub_group_ballot(true)))
sycl_printf("%i",i);
} else {
sycl_printf("%i ",i);
}
return cout;
}
#endif
inline sycl_ostream_ operator <<(sycl_ostream_ cout, float f)
{
if (cout.uniform) {
@@ -483,7 +460,7 @@ namespace embree
return cout;
}
inline sycl_ostream_ operator <<(sycl_ostream_ cout, ulong l)
inline sycl_ostream_ operator <<(sycl_ostream_ cout, uint64_t l)
{
if (cout.uniform) {
if (get_sub_group_local_id() == SYCL_CTZ::ctz(intel_sub_group_ballot(true)))
+40 -44
View File
@@ -20,20 +20,16 @@ using sycl::uint8;
using sycl::uint4;
using sycl::uint3;
using sycl::uint2;
using sycl::uint;
using sycl::ulong;
using sycl::uchar16;
using sycl::uchar8;
using sycl::uchar4;
using sycl::uchar3;
using sycl::uchar2;
using sycl::uchar;
using sycl::ushort16;
using sycl::ushort8;
using sycl::ushort4;
using sycl::ushort3;
using sycl::ushort2;
using sycl::ushort;
using sycl::fmax;
using sycl::fmin;
@@ -51,7 +47,7 @@ SYCL_EXTERNAL extern float atomic_min(volatile LOCAL float *p, float val);
SYCL_EXTERNAL extern float atomic_max(volatile GLOBAL float *p, float val);
SYCL_EXTERNAL extern float atomic_max(volatile LOCAL float *p, float val);
SYCL_EXTERNAL extern "C" uint intel_sub_group_ballot(bool valid);
SYCL_EXTERNAL extern "C" unsigned int intel_sub_group_ballot(bool valid);
SYCL_EXTERNAL extern "C" void __builtin_IB_assume_uniform(void *p);
@@ -91,32 +87,32 @@ SYCL_EXTERNAL extern "C" void __builtin_IB_assume_uniform(void *p);
///////////////////////////////////////////////////////////////////////
SYCL_EXTERNAL /* extern "C" */ uint __builtin_IB_lsc_load_global_uchar_to_uint (const GLOBAL sycl::uchar *base, int elemOff, enum LSC_LDCC cacheOpt); //D8U32
SYCL_EXTERNAL /* extern "C" */ uint __builtin_IB_lsc_load_global_ushort_to_uint(const GLOBAL sycl::ushort *base, int elemOff, enum LSC_LDCC cacheOpt); //D16U32
SYCL_EXTERNAL /* extern "C" */ uint __builtin_IB_lsc_load_global_uint (const GLOBAL sycl::uint *base, int elemOff, enum LSC_LDCC cacheOpt); //D32V1
SYCL_EXTERNAL /* extern "C" */ sycl::uint2 __builtin_IB_lsc_load_global_uint2 (const GLOBAL sycl::uint2 *base, int elemOff, enum LSC_LDCC cacheOpt); //D32V2
SYCL_EXTERNAL /* extern "C" */ sycl::uint3 __builtin_IB_lsc_load_global_uint3 (const GLOBAL sycl::uint3 *base, int elemOff, enum LSC_LDCC cacheOpt); //D32V3
SYCL_EXTERNAL /* extern "C" */ sycl::uint4 __builtin_IB_lsc_load_global_uint4 (const GLOBAL sycl::uint4 *base, int elemOff, enum LSC_LDCC cacheOpt); //D32V4
SYCL_EXTERNAL /* extern "C" */ sycl::uint8 __builtin_IB_lsc_load_global_uint8 (const GLOBAL sycl::uint8 *base, int elemOff, enum LSC_LDCC cacheOpt); //D32V8
SYCL_EXTERNAL /* extern "C" */ sycl::ulong __builtin_IB_lsc_load_global_ulong (const GLOBAL sycl::ulong *base, int elemOff, enum LSC_LDCC cacheOpt); //D64V1
SYCL_EXTERNAL /* extern "C" */ sycl::ulong2 __builtin_IB_lsc_load_global_ulong2(const GLOBAL sycl::ulong2 *base, int elemOff, enum LSC_LDCC cacheOpt); //D64V2
SYCL_EXTERNAL /* extern "C" */ sycl::ulong3 __builtin_IB_lsc_load_global_ulong3(const GLOBAL sycl::ulong3 *base, int elemOff, enum LSC_LDCC cacheOpt); //D64V3
SYCL_EXTERNAL /* extern "C" */ sycl::ulong4 __builtin_IB_lsc_load_global_ulong4(const GLOBAL sycl::ulong4 *base, int elemOff, enum LSC_LDCC cacheOpt); //D64V4
SYCL_EXTERNAL /* extern "C" */ sycl::ulong8 __builtin_IB_lsc_load_global_ulong8(const GLOBAL sycl::ulong8 *base, int elemOff, enum LSC_LDCC cacheOpt); //D64V8
SYCL_EXTERNAL /* extern "C" */ uint32_t __builtin_IB_lsc_load_global_uchar_to_uint (const GLOBAL uint8_t *base, int elemOff, enum LSC_LDCC cacheOpt); //D8U32
SYCL_EXTERNAL /* extern "C" */ uint32_t __builtin_IB_lsc_load_global_ushort_to_uint(const GLOBAL uint16_t *base, int elemOff, enum LSC_LDCC cacheOpt); //D16U32
SYCL_EXTERNAL /* extern "C" */ uint32_t __builtin_IB_lsc_load_global_uint (const GLOBAL uint32_t *base, int elemOff, enum LSC_LDCC cacheOpt); //D32V1
SYCL_EXTERNAL /* extern "C" */ sycl::uint2 __builtin_IB_lsc_load_global_uint2 (const GLOBAL sycl::uint2 *base, int elemOff, enum LSC_LDCC cacheOpt); //D32V2
SYCL_EXTERNAL /* extern "C" */ sycl::uint3 __builtin_IB_lsc_load_global_uint3 (const GLOBAL sycl::uint3 *base, int elemOff, enum LSC_LDCC cacheOpt); //D32V3
SYCL_EXTERNAL /* extern "C" */ sycl::uint4 __builtin_IB_lsc_load_global_uint4 (const GLOBAL sycl::uint4 *base, int elemOff, enum LSC_LDCC cacheOpt); //D32V4
SYCL_EXTERNAL /* extern "C" */ sycl::uint8 __builtin_IB_lsc_load_global_uint8 (const GLOBAL sycl::uint8 *base, int elemOff, enum LSC_LDCC cacheOpt); //D32V8
SYCL_EXTERNAL /* extern "C" */ uint64_t __builtin_IB_lsc_load_global_ulong (const GLOBAL uint64_t *base, int elemOff, enum LSC_LDCC cacheOpt); //D64V1
SYCL_EXTERNAL /* extern "C" */ sycl::ulong2 __builtin_IB_lsc_load_global_ulong2 (const GLOBAL sycl::ulong2 *base, int elemOff, enum LSC_LDCC cacheOpt); //D64V2
SYCL_EXTERNAL /* extern "C" */ sycl::ulong3 __builtin_IB_lsc_load_global_ulong3 (const GLOBAL sycl::ulong3 *base, int elemOff, enum LSC_LDCC cacheOpt); //D64V3
SYCL_EXTERNAL /* extern "C" */ sycl::ulong4 __builtin_IB_lsc_load_global_ulong4 (const GLOBAL sycl::ulong4 *base, int elemOff, enum LSC_LDCC cacheOpt); //D64V4
SYCL_EXTERNAL /* extern "C" */ sycl::ulong8 __builtin_IB_lsc_load_global_ulong8 (const GLOBAL sycl::ulong8 *base, int elemOff, enum LSC_LDCC cacheOpt); //D64V8
// global address space
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_uchar_from_uint (GLOBAL sycl::uchar *base, int immElemOff, uint val, enum LSC_STCC cacheOpt); //D8U32
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_ushort_from_uint(GLOBAL sycl::ushort *base, int immElemOff, uint val, enum LSC_STCC cacheOpt); //D16U32
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_uint (GLOBAL sycl::uint *base, int immElemOff, uint val, enum LSC_STCC cacheOpt); //D32V1
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_uint2 (GLOBAL sycl::uint2 *base, int immElemOff, sycl::uint2 val, enum LSC_STCC cacheOpt); //D32V2
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_uint3 (GLOBAL sycl::uint3 *base, int immElemOff, sycl::uint3 val, enum LSC_STCC cacheOpt); //D32V3
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_uint4 (GLOBAL sycl::uint4 *base, int immElemOff, sycl::uint4 val, enum LSC_STCC cacheOpt); //D32V4
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_uint8 (GLOBAL sycl::uint8 *base, int immElemOff, sycl::uint8 val, enum LSC_STCC cacheOpt); //D32V8
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_ulong (GLOBAL sycl::ulong *base, int immElemOff, sycl::ulong val, enum LSC_STCC cacheOpt); //D64V1
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_ulong2(GLOBAL sycl::ulong2 *base, int immElemOff, sycl::ulong2 val, enum LSC_STCC cacheOpt); //D64V2
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_ulong3(GLOBAL sycl::ulong3 *base, int immElemOff, sycl::ulong3 val, enum LSC_STCC cacheOpt); //D64V3
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_ulong4(GLOBAL sycl::ulong4 *base, int immElemOff, sycl::ulong4 val, enum LSC_STCC cacheOpt); //D64V4
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_ulong8(GLOBAL sycl::ulong8 *base, int immElemOff, sycl::ulong8 val, enum LSC_STCC cacheOpt); //D64V8
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_uchar_from_uint (GLOBAL uint8_t *base, int immElemOff, uint32_t val, enum LSC_STCC cacheOpt); //D8U32
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_ushort_from_uint(GLOBAL uint16_t *base, int immElemOff, uint32_t val, enum LSC_STCC cacheOpt); //D16U32
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_uint (GLOBAL uint32_t *base, int immElemOff, uint32_t val, enum LSC_STCC cacheOpt); //D32V1
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_uint2 (GLOBAL sycl::uint2 *base, int immElemOff, sycl::uint2 val, enum LSC_STCC cacheOpt); //D32V2
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_uint3 (GLOBAL sycl::uint3 *base, int immElemOff, sycl::uint3 val, enum LSC_STCC cacheOpt); //D32V3
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_uint4 (GLOBAL sycl::uint4 *base, int immElemOff, sycl::uint4 val, enum LSC_STCC cacheOpt); //D32V4
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_uint8 (GLOBAL sycl::uint8 *base, int immElemOff, sycl::uint8 val, enum LSC_STCC cacheOpt); //D32V8
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_ulong (GLOBAL uint64_t *base, int immElemOff, uint64_t val, enum LSC_STCC cacheOpt); //D64V1
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_ulong2 (GLOBAL sycl::ulong2 *base, int immElemOff, sycl::ulong2 val, enum LSC_STCC cacheOpt); //D64V2
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_ulong3 (GLOBAL sycl::ulong3 *base, int immElemOff, sycl::ulong3 val, enum LSC_STCC cacheOpt); //D64V3
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_ulong4 (GLOBAL sycl::ulong4 *base, int immElemOff, sycl::ulong4 val, enum LSC_STCC cacheOpt); //D64V4
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_ulong8 (GLOBAL sycl::ulong8 *base, int immElemOff, sycl::ulong8 val, enum LSC_STCC cacheOpt); //D64V8
///////////////////////////////////////////////////////////////////////
// prefetching
@@ -124,14 +120,14 @@ SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_store_global_ulong8(GLOBAL sycl
//
// LSC Pre-Fetch Load functions with CacheControls
// global address space
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_uchar (const GLOBAL sycl::uchar *base, int immElemOff, enum LSC_LDCC cacheOpt); //D8U32
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_ushort(const GLOBAL sycl::ushort *base, int immElemOff, enum LSC_LDCC cacheOpt); //D16U32
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_uint (const GLOBAL sycl::uint *base, int immElemOff, enum LSC_LDCC cacheOpt); //D32V1
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_uint2 (const GLOBAL sycl::uint2 *base, int immElemOff, enum LSC_LDCC cacheOpt); //D32V2
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_uint3 (const GLOBAL sycl::uint3 *base, int immElemOff, enum LSC_LDCC cacheOpt); //D32V3
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_uint4 (const GLOBAL sycl::uint4 *base, int immElemOff, enum LSC_LDCC cacheOpt); //D32V4
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_uint8 (const GLOBAL sycl::uint8 *base, int immElemOff, enum LSC_LDCC cacheOpt); //D32V8
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_ulong (const GLOBAL sycl::ulong *base, int immElemOff, enum LSC_LDCC cacheOpt); //D64V1
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_uchar (const GLOBAL uint8_t *base, int immElemOff, enum LSC_LDCC cacheOpt); //D8U32
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_ushort(const GLOBAL uint16_t *base, int immElemOff, enum LSC_LDCC cacheOpt); //D16U32
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_uint (const GLOBAL uint32_t *base, int immElemOff, enum LSC_LDCC cacheOpt); //D32V1
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_uint2 (const GLOBAL sycl::uint2 *base, int immElemOff, enum LSC_LDCC cacheOpt); //D32V2
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_uint3 (const GLOBAL sycl::uint3 *base, int immElemOff, enum LSC_LDCC cacheOpt); //D32V3
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_uint4 (const GLOBAL sycl::uint4 *base, int immElemOff, enum LSC_LDCC cacheOpt); //D32V4
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_uint8 (const GLOBAL sycl::uint8 *base, int immElemOff, enum LSC_LDCC cacheOpt); //D32V8
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_ulong (const GLOBAL uint64_t *base, int immElemOff, enum LSC_LDCC cacheOpt); //D64V1
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_ulong2(const GLOBAL sycl::ulong2 *base, int immElemOff, enum LSC_LDCC cacheOpt); //D64V2
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_ulong3(const GLOBAL sycl::ulong3 *base, int immElemOff, enum LSC_LDCC cacheOpt); //D64V3
SYCL_EXTERNAL extern "C" void __builtin_IB_lsc_prefetch_global_ulong4(const GLOBAL sycl::ulong4 *base, int immElemOff, enum LSC_LDCC cacheOpt); //D64V4
@@ -150,14 +146,14 @@ inline float work_group_reduce_max(float x) { return x; }
inline float atomic_min(volatile float *p, float val) { return val; };
inline float atomic_max(volatile float *p, float val) { return val; };
inline uint intel_sub_group_ballot(bool valid) { return 0; }
inline uint32_t intel_sub_group_ballot(bool valid) { return 0; }
#endif
/* creates a temporary that is enforced to be uniform */
#define SYCL_UNIFORM_VAR(Ty,tmp,k) \
Ty tmp##_data; \
Ty* p##tmp##_data = (Ty*) sub_group_broadcast((ulong)&tmp##_data,k); \
Ty* p##tmp##_data = (Ty*) sub_group_broadcast((uint64_t)&tmp##_data,k); \
Ty& tmp = *p##tmp##_data;
#if !defined(__forceinline)
@@ -192,23 +188,23 @@ namespace embree
return SYCL_EXPERIMENTAL::this_sub_group();
}
__forceinline const uint get_sub_group_local_id() {
__forceinline const uint32_t get_sub_group_local_id() {
return this_sub_group().get_local_id()[0];
}
__forceinline const uint get_sub_group_size() {
__forceinline const uint32_t get_sub_group_size() {
return this_sub_group().get_max_local_range().size();
}
__forceinline const uint get_sub_group_id() {
__forceinline const uint32_t get_sub_group_id() {
return this_sub_group().get_group_id()[0];
}
__forceinline const uint get_num_sub_groups() {
__forceinline const uint32_t get_num_sub_groups() {
return this_sub_group().get_group_range().size();
}
__forceinline uint sub_group_ballot(bool pred) {
__forceinline uint32_t sub_group_ballot(bool pred) {
return intel_sub_group_ballot(pred);
}
+1
View File
@@ -12,6 +12,7 @@ endif()
string(REGEX REPLACE "\n$" "" intelstyle_url "${intelstyle_url}")
string(REPLACE "embree" "intelstyle" intelstyle_url "${intelstyle_url}")
string(REPLACE "libraries" "documentation" intelstyle_url "${intelstyle_url}")
message(STATUS "Fetch intelstyle repository ${intelstyle_url}")
include(FetchContent)
-15
View File
@@ -224,21 +224,6 @@ Embree SYCL Known Issues
quality, and GPU performance may not reflect that of the final
product.
- Currently only the following Intel® Arc™ GPUs are support:
- Intel® Arc™ A770 Graphics
- Intel® Arc™ A750 Graphics
- Intel® Arc™ A770M Graphics
- Intel® Arc™ A730M Graphics
- Intel® Arc™ A550M Graphics
- Intel® Data Center GPU Max Series is currently not supported.
- Ahead of time compilation is currently not working properly and you
will get this error during compilation:
llvm-foreach: Floating point exception (core dumped)
- Compilation with build configuration "debug" is currently not working on
Windows.
+8
View File
@@ -63,6 +63,14 @@ Possible properties to query are:
back face culling is enabled. This is only the case if Embree is
compiled with `EMBREE_BACKFACE_CULLING` enabled.
+ `RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED`: Queries whether
back face culling for curves is enabled. This is only the case if Embree is
compiled with `EMBREE_BACKFACE_CULLING_CURVES` enabled.
+ `RTC_DEVICE_PROPERTY_BACKFACE_CULLING_SPHERES_ENABLED`: Queries whether
back face culling for spheres is enabled. This is only the case if Embree is
compiled with `EMBREE_BACKFACE_CULLING_SPHERES` enabled.
+ `RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED`: Queries whether
compact polys is enabled. This is only the case if Embree is
compiled with `EMBREE_COMPACT_POLYS` enabled.
+5
View File
@@ -1,6 +1,11 @@
Version History
---------------
### Embree 4.1.0
- Added support for Intel® Data Center GPU Max Series.
- Added ARM64 Linux support.
- Added EMBREE_BACKFACE_CULLING_SPHERES cmake option. The new cmake option defaults to OFF.
### Embree 4.0.1
- Improved performance for Tiger Lake, Comet Lake, Cannon Lake, Kaby Lake,
and Skylake client CPUs by using 256 bit SIMD instructions by default.
+23 -10
View File
@@ -17,8 +17,9 @@ C++11. Embree is tested with the following compilers:
Linux
- Intel® oneAPI DPC++/C++ Compiler 2023.1.0
- Intel® oneAPI DPC++/C++ Compiler 2023.0.0
- oneAPI DPC++/C++ Compiler 2022-12-14
- oneAPI DPC++/C++ Compiler 2023-04-17
- Clang 5.0.0
- Clang 4.0.0
- GCC 10.0.1 (Fedora 32) AVX512 support
@@ -26,6 +27,7 @@ Linux
- GCC 7.3.1 (Fedora 27) AVX2 support
- GCC 7.3.1 (Fedora 26) AVX2 support
- GCC 6.4.1 (Fedora 25) AVX2 support
- Intel® Implicit SPMD Program Compiler 1.19.0
- Intel® Implicit SPMD Program Compiler 1.18.1
- Intel® Implicit SPMD Program Compiler 1.17.0
- Intel® Implicit SPMD Program Compiler 1.16.1
@@ -36,6 +38,7 @@ Linux
macOS x86
- Intel® C++ Classic Compiler 2023.1.0
- Intel® C++ Classic Compiler 2023.0.0
- Apple Clang 12.0.5 (macOS 11.7.1)
@@ -141,13 +144,13 @@ The "oneAPI DPC++ Compiler" is more up-to-date than the "Intel(R) oneAPI
DPC++/C++ Compiler" but less stable. The current tested version of the "oneAPI
DPC++ compiler is
- [oneAPI DPC++ Compiler 2022-12-14](https://github.com/intel/llvm/releases/download/sycl-nightly%2F20221214/dpcpp-compiler.tar.gz)
- [oneAPI DPC++ Compiler 2023-04-17](https://github.com/intel/llvm/releases/download/sycl-nightly%2F20230417/dpcpp-compiler.tar.gz)
The compiler can be downloaded and simply extracted. The oneAPI DPC++ compiler
2022-12-14 can be set up executing the following command in a Linux (bash)
shell:
wget https://github.com/intel/llvm/releases/download/sycl-nightly%2F20221214/dpcpp-compiler.tar.gz
wget https://github.com/intel/llvm/releases/download/sycl-nightly%2F20230417/dpcpp-compiler.tar.gz
tar xzf dpcpp-compiler.tar.gz
source ./dpcpp_compiler/startup.sh
@@ -171,7 +174,7 @@ through `EMBREE_SYCL_SUPPORT=ON`.
Alternatively, you can download and run the installer of the
- [Intel(R) oneAPI DPC++/C++ Compiler 2023.0.0](https://www.intel.com/content/www/us/en/developer/articles/tool/oneapi-standalone-components.html#dpcpp-cpp).
- [Intel(R) oneAPI DPC++/C++ Compiler 2023.1.0](https://www.intel.com/content/www/us/en/developer/articles/tool/oneapi-standalone-components.html#dpcpp-cpp).
After installation, you can set up the compiler by sourcing the
`vars.sh` script in the `env` directory of the compiler install directory, for example,
@@ -215,7 +218,7 @@ We tested Embree with the latest GPGPU driver Devel Release from
and OpenCL(TM) Driver from that release is too old for Embree to work
properly. Thus if no newer version of the GPGPU driver is available,
you need to additionally install the latest compute runtime from here
[22.43.24595](https://github.com/intel/compute-runtime/releases/tag/22.43.24595.30).
[23.09.25812.14](https://github.com/intel/compute-runtime/releases/tag/23.09.25812.14).
Unfortunately, these compute runtime packages are only available for
Ubuntu 22.04. You can also install a newer version of the compute
@@ -227,11 +230,13 @@ Windows
Embree is tested using the following compilers under Windows:
- Intel® oneAPI DPC++/C++ Compiler 2023.1.0
- Intel® oneAPI DPC++/C++ Compiler 2023.0.0
- oneAPI DPC++/C++ Compiler 2022-12-14
- oneAPI DPC++/C++ Compiler 2023-04-17
- Visual Studio 2019
- Visual Studio 2017
- Visual Studio 2015 (Update\ 1)
- Intel® Implicit SPMD Program Compiler 1.19.0
- Intel® Implicit SPMD Program Compiler 1.18.1
- Intel® Implicit SPMD Program Compiler 1.17.0
- Intel® Implicit SPMD Program Compiler 1.16.1
@@ -356,7 +361,7 @@ The "oneAPI DPC++ Compiler" is more up-to-date than the "Intel(R) oneAPI
DPC++/C++ Compiler" but less stable. The current tested version of the oneAPI
DPC++ compiler is
- [oneAPI DPC++ Compiler 2022-12-14](https://github.com/intel/llvm/releases/download/sycl-nightly%2F20221214/dpcpp-compiler-win.tar.gz)
- [oneAPI DPC++ Compiler 2023-04-17](https://github.com/intel/llvm/releases/download/sycl-nightly%2F20230417/dpcpp-compiler-win.tar.gz)
Download and unpack the archive and open the "x64 Native Tools Command Prompt"
of Visual Studio and execute the following lines to properly configure the
@@ -442,9 +447,9 @@ your application with such an Embree package.
### Windows Graphics Driver Installation
In order to run the SYCL tutorials on HPG hardware, you first need to
install the proper graphics drivers for your graphics card from
[https://www.intel.com](https://www.intel.com). Embree will work with
graphics driver version 101.4027 or later.
install the graphics drivers for your graphics card from
[https://www.intel.com](https://www.intel.com). Please make sure to
have installed version 31.0.101.4314 or newer.
CMake Configuration
@@ -513,6 +518,14 @@ parameters that can be configured in CMake:
surfaces facing a ray can be hit. This option is turned OFF by
default.
+ `EMBREE_BACKFACE_CULLING_CURVES`: Enables backface culling for curves,
i.e. only surfaces facing a ray can be hit. This option is turned OFF
by default.
+ `EMBREE_BACKFACE_CULLING_SPHERES`: Enables backface culling for spheres,
i.e. only surfaces facing a ray can be hit. This option is turned OFF
by default.
+ `EMBREE_COMPACT_POLYS`: Enables compact tris/quads, i.e. only
geomIDs and primIDs are stored inside the leaf nodes.
+2 -2
View File
@@ -4,8 +4,8 @@ Intel® Embree Overview
Intel® Embree is a high-performance ray tracing library developed at
Intel, which is released as open source under the [Apache 2.0
license](http://www.apache.org/licenses/LICENSE-2.0). Intel® Embree
supports x86 CPUs under Linux, macOS, and Windows; ARM CPUs on macOS;
as well as Intel® GPUs under Linux and Windows.
supports x86 CPUs under Linux, macOS, and Windows; ARM CPUs on Linux
and macOS; as well as Intel® GPUs under Linux and Windows.
Intel® Embree targets graphics application developers to improve the
performance of photo-realistic rendering applications. Embree is
+2 -12
View File
@@ -3,24 +3,14 @@ Supported Platforms
Embree supports Windows (32-bit and 64-bit), Linux (64-bit), and macOS
(64-bit). Under Windows, Linux and macOS x86 based CPUs are supported,
while ARM CPUs are currently only supported under macOS (e.g. Apple
M1). ARM support for Windows and Linux is experimental.
while ARM CPUs are currently only supported under Linux and macOS (e.g.
Apple M1). ARM support for Windows experimental.
Embree supports Intel GPUs based on the Xe HPG microarchitecture
(Intel® Arc™ GPU) under Linux and Windows and Xe HPC microarchitecture
(Intel® Data Center GPU Flex Series and Intel® Data Center GPU Max
Series) under Linux.
Currently the following products are supported and further products
will get enabled soon:
- Intel® Arc™ A770 Graphics
- Intel® Arc™ A750 Graphics
- Intel® Arc™ A770M Graphics
- Intel® Arc™ A730M Graphics
- Intel® Arc™ A550M Graphics
- Intel® Data Center GPU Flex 170
The code compiles with the Intel® Compiler, Intel® oneAPI DPC++
Compiler, GCC, Clang, and the Microsoft Compiler. To use Embree on the
GPU the Intel® oneAPI DPC++ Compiler must be used. Please see section
+1
View File
@@ -49,6 +49,7 @@ enum RTCDeviceProperty
RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED = 33,
RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED = 34,
RTC_DEVICE_PROPERTY_BACKFACE_CULLING_SPHERES_ENABLED = 62,
RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED = 63,
RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED = 64,
RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED = 65,
+2 -5
View File
@@ -38,7 +38,6 @@ namespace embree
__forceinline bool split_pos(const PrimRef& prim, unsigned int& dim_o, float& fsplit_o) const
{
#if !defined(__SYCL_DEVICE_ONLY__)
/* compute morton code */
const Vec3fa lower = prim.lower;
const Vec3fa upper = prim.upper;
@@ -73,7 +72,6 @@ namespace embree
dim_o = dim;
fsplit_o = fsplit;
#endif
return true;
}
@@ -85,11 +83,10 @@ namespace embree
const Vec3fa gupper = (upper-base)*Vec3fa(scale)-Vec3fa(0.2f);
Vec3ia ilower(floor(glower));
Vec3ia iupper(floor(gupper));
#if !defined(__SYCL_DEVICE_ONLY__)
/* this ignores dimensions that are empty */
iupper = (Vec3ia)select(vint4(glower) >= vint4(gupper),vint4(ilower),vint4(iupper));
#endif
/* compute a morton code for the lower and upper grid coordinates. */
const unsigned int lower_code = bitInterleave(ilower.x,ilower.y,ilower.z);
const unsigned int upper_code = bitInterleave(iupper.x,iupper.y,iupper.z);
+10 -1
View File
@@ -170,6 +170,9 @@ namespace embree
#if defined (EMBREE_BACKFACE_CULLING_CURVES)
v += "backfacecullingcurves ";
#endif
#if defined (EMBREE_BACKFACE_CULLING_SPHERES)
v += "backfacecullingspheres ";
#endif
#if defined(EMBREE_FILTER_FUNCTION)
v += "intersection_filter ";
#endif
@@ -477,6 +480,12 @@ namespace embree
case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED: return 0;
#endif
#if defined(EMBREE_BACKFACE_CULLING_SPHERES)
case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_SPHERES_ENABLED: return 1;
#else
case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_SPHERES_ENABLED: return 0;
#endif
#if defined(EMBREE_COMPACT_POLYS)
case RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED: return 1;
#else
@@ -594,7 +603,7 @@ namespace embree
std::cout << std::endl;
}
dispatchGlobalsPtr = rthwifInit(gpu_device, gpu_context);
dispatchGlobalsPtr = zeRTASInitExp(gpu_device, gpu_context);
}
DeviceGPU::~DeviceGPU()
+10 -11
View File
@@ -38,17 +38,16 @@ RTC_NAMESPACE_BEGIN;
RTC_TRACE(rtcNewSYCLDevice);
Lock<MutexSys> lock(g_mutex);
if (!getenv("EMBREE_NO_SPLASH"))
{
std::cout << std::endl;
std::cout << "==================================================================================" << std::endl;
std::cout << " The SYCL support of Embree is in beta phase. Current functionality, quality, " << std::endl;
std::cout << " and GPU performance may not reflect that of the final product. Please read the " << std::endl;
std::cout << " documentation section \"Embree SYCL Known Issues\" for known limitations. " << std::endl;
std::cout << "==================================================================================" << std::endl;
std::cout << std::endl;
}
#if !defined(EMBREE_NO_SPLASH)
std::cout << std::endl;
std::cout << "==================================================================================" << std::endl;
std::cout << " The SYCL support of Embree is in beta phase. Current functionality, quality, " << std::endl;
std::cout << " and GPU performance may not reflect that of the final product. Please read the " << std::endl;
std::cout << " documentation section \"Embree SYCL Known Issues\" for known limitations. " << std::endl;
std::cout << "==================================================================================" << std::endl;
std::cout << std::endl;
#endif
DeviceGPU* device = new DeviceGPU(sycl_context,config);
return (RTCDevice) device->refInc();
RTC_CATCH_END(nullptr);
+1 -16
View File
@@ -685,10 +685,7 @@ namespace embree
{
/* select acceleration structures to build */
unsigned int new_enabled_geometry_types = world.enabledGeometryTypesMask();
// #if defined(EMBREE_SYCL_SUPPORT)
// if (!dynamic_cast<DeviceGPU*>(device)) // do not build software accel for GPU if not required
// #endif
if (flags_modified || new_enabled_geometry_types != enabled_geometry_types)
{
accels_init();
@@ -726,18 +723,6 @@ namespace embree
/* build all hierarchies of this scene */
accels_build();
/* build acceleration structure for rthw */
// #if defined(EMBREE_SYCL_SUPPORT)
// if (DeviceGPU* gpu_device = dynamic_cast<DeviceGPU*>(device))
// //if (gpu_device->rthw_support())
// // bounds = LBBox<embree::Vec3fa>(rthwifBuild(this,quality_flags,hwaccel,device->gpu_build));
// if (gpu_device->rthw_support()) {
// const BBox3f aabb = rthwifBuild(this,quality_flags,hwaccel,device->gpu_build);
// bounds = LBBox<embree::Vec3fa>(aabb);
// hwaccel_bounds = aabb;
// }
// #endif
/* make static geometry immutable */
if (!isDynamicAccel()) {
accels_immutable();
+1 -1
View File
@@ -154,7 +154,7 @@ namespace embree
const Grid& g = grid(primID);
for (ssize_t y=0; y<ssize_t(g.resY)-1; y++)
for (ssize_t x=0; x<ssize_t(g.resX)-1; x++)
quadID_to_primID_xy[quadID++] = { primID, (ushort) x, (ushort) y };
quadID_to_primID_xy[quadID++] = { primID, (uint16_t) x, (uint16_t) y };
}
}
+1 -1
View File
@@ -362,7 +362,7 @@ namespace embree
#if defined(EMBREE_SYCL_SUPPORT)
public:
struct PrimID_XY { uint32_t primID; ushort x,y; };
struct PrimID_XY { uint32_t primID; uint16_t x,y; };
Device::vector<PrimID_XY> quadID_to_primID_xy = device; //!< maps a quad to the primitive ID and grid coordinates
#endif
};
+43 -44
View File
@@ -3,7 +3,6 @@
#include "stat.h"
namespace embree
{
Stat Stat::instance;
@@ -25,16 +24,16 @@ namespace embree
//Counters::Data& data = instance.cntrs.active;
/* print absolute numbers */
cout << "--------- ABSOLUTE ---------" << embree_endl;
cout << " #normal_travs = " << float(data.normal.travs )*1E-6f << "M" << embree_endl;
cout << " #nodes = " << float(data.normal.trav_nodes )*1E-6f << "M" << embree_endl;
cout << " #nodes_xfm = " << float(data.normal.trav_xfm_nodes )*1E-6f << "M" << embree_endl;
cout << " #leaves = " << float(data.normal.trav_leaves )*1E-6f << "M" << embree_endl;
cout << " #prims = " << float(data.normal.trav_prims )*1E-6f << "M" << embree_endl;
cout << " #prim_hits = " << float(data.normal.trav_prim_hits )*1E-6f << "M" << embree_endl;
cout << "--------- ABSOLUTE ---------" << std::endl;
cout << " #normal_travs = " << float(data.normal.travs )*1E-6 << "M" << std::endl;
cout << " #nodes = " << float(data.normal.trav_nodes )*1E-6 << "M" << std::endl;
cout << " #nodes_xfm = " << float(data.normal.trav_xfm_nodes )*1E-6 << "M" << std::endl;
cout << " #leaves = " << float(data.normal.trav_leaves )*1E-6 << "M" << std::endl;
cout << " #prims = " << float(data.normal.trav_prims )*1E-6 << "M" << std::endl;
cout << " #prim_hits = " << float(data.normal.trav_prim_hits )*1E-6 << "M" << std::endl;
cout << " #stack nodes = " << float(data.normal.trav_stack_nodes )*1E-6f << "M" << embree_endl;
cout << " #stack pop = " << float(data.normal.trav_stack_pop )*1E-6f << "M" << embree_endl;
cout << " #stack nodes = " << float(data.normal.trav_stack_nodes )*1E-6 << "M" << std::endl;
cout << " #stack pop = " << float(data.normal.trav_stack_pop )*1E-6 << "M" << std::endl;
size_t normal_box_hits = 0;
size_t weighted_box_hits = 0;
@@ -50,20 +49,20 @@ namespace embree
cout << "[" << i << "] " << value << " ";
average += (float)i*data.normal.trav_hit_boxes[i] / normal_box_hits;
}
cout << " average = " << average << embree_endl;
cout << " average = " << average << std::endl;
for (size_t i=0;i<SIZE_HISTOGRAM;i++) cout << "[" << i << "] " << 100.0f * data.normal.trav_hit_boxes[i]*i / weighted_box_hits << " ";
cout << embree_endl;
cout << std::endl;
if (data.shadow.travs) {
cout << " #shadow_travs = " << float(data.shadow.travs )*1E-6f << "M" << embree_endl;
cout << " #nodes = " << float(data.shadow.trav_nodes )*1E-6f << "M" << embree_endl;
cout << " #nodes_xfm = " << float(data.shadow.trav_xfm_nodes)*1E-6f << "M" << embree_endl;
cout << " #leaves = " << float(data.shadow.trav_leaves )*1E-6f << "M" << embree_endl;
cout << " #prims = " << float(data.shadow.trav_prims )*1E-6f << "M" << embree_endl;
cout << " #prim_hits = " << float(data.shadow.trav_prim_hits)*1E-6f << "M" << embree_endl;
cout << " #shadow_travs = " << float(data.shadow.travs )*1E-6 << "M" << std::endl;
cout << " #nodes = " << float(data.shadow.trav_nodes )*1E-6 << "M" << std::endl;
cout << " #nodes_xfm = " << float(data.shadow.trav_xfm_nodes)*1E-6 << "M" << std::endl;
cout << " #leaves = " << float(data.shadow.trav_leaves )*1E-6 << "M" << std::endl;
cout << " #prims = " << float(data.shadow.trav_prims )*1E-6 << "M" << std::endl;
cout << " #prim_hits = " << float(data.shadow.trav_prim_hits)*1E-6 << "M" << std::endl;
cout << " #stack nodes = " << float(data.shadow.trav_stack_nodes )*1E-6f << "M" << embree_endl;
cout << " #stack pop = " << float(data.shadow.trav_stack_pop )*1E-6f << "M" << embree_endl;
cout << " #stack nodes = " << float(data.shadow.trav_stack_nodes )*1E-6 << "M" << std::endl;
cout << " #stack pop = " << float(data.shadow.trav_stack_pop )*1E-6 << "M" << std::endl;
size_t shadow_box_hits = 0;
size_t weighted_shadow_box_hits = 0;
@@ -74,14 +73,14 @@ namespace embree
}
cout << " #hit_boxes = ";
for (size_t i=0;i<SIZE_HISTOGRAM;i++) cout << "[" << i << "] " << 100.0f * data.shadow.trav_hit_boxes[i] / shadow_box_hits << " ";
cout << embree_endl;
cout << std::endl;
for (size_t i=0;i<SIZE_HISTOGRAM;i++) cout << "[" << i << "] " << 100.0f * data.shadow.trav_hit_boxes[i]*i / weighted_shadow_box_hits << " ";
cout << embree_endl;
cout << std::endl;
}
cout << embree_endl;
cout << std::endl;
/* print per traversal numbers */
cout << "--------- PER TRAVERSAL ---------" << embree_endl;
cout << "--------- PER TRAVERSAL ---------" << std::endl;
float active_normal_travs = float(cntrs.active.normal.travs )/float(cntrs.all.normal.travs );
float active_normal_trav_nodes = float(cntrs.active.normal.trav_nodes )/float(cntrs.all.normal.trav_nodes );
float active_normal_trav_xfm_nodes = float(cntrs.active.normal.trav_xfm_nodes )/float(cntrs.all.normal.trav_xfm_nodes );
@@ -90,13 +89,13 @@ namespace embree
float active_normal_trav_prim_hits = float(cntrs.active.normal.trav_prim_hits )/float(cntrs.all.normal.trav_prim_hits );
float active_normal_trav_stack_pop = float(cntrs.active.normal.trav_stack_pop )/float(cntrs.all.normal.trav_stack_pop );
cout << " #normal_travs = " << float(cntrs.code.normal.travs )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_travs << "% active" << embree_endl;
cout << " #nodes = " << float(cntrs.code.normal.trav_nodes )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_nodes << "% active" << embree_endl;
cout << " #node_xfm = " << float(cntrs.code.normal.trav_xfm_nodes )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_xfm_nodes << "% active" << embree_endl;
cout << " #leaves = " << float(cntrs.code.normal.trav_leaves)/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_leaves << "% active" << embree_endl;
cout << " #prims = " << float(cntrs.code.normal.trav_prims )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_prims << "% active" << embree_endl;
cout << " #prim_hits = " << float(cntrs.code.normal.trav_prim_hits )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_prim_hits << "% active" << embree_endl;
cout << " #stack_pop = " << float(cntrs.code.normal.trav_stack_pop )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_stack_pop << "% active" << embree_endl;
cout << " #normal_travs = " << float(cntrs.code.normal.travs )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_travs << "% active" << std::endl;
cout << " #nodes = " << float(cntrs.code.normal.trav_nodes )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_nodes << "% active" << std::endl;
cout << " #node_xfm = " << float(cntrs.code.normal.trav_xfm_nodes )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_xfm_nodes << "% active" << std::endl;
cout << " #leaves = " << float(cntrs.code.normal.trav_leaves)/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_leaves << "% active" << std::endl;
cout << " #prims = " << float(cntrs.code.normal.trav_prims )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_prims << "% active" << std::endl;
cout << " #prim_hits = " << float(cntrs.code.normal.trav_prim_hits )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_prim_hits << "% active" << std::endl;
cout << " #stack_pop = " << float(cntrs.code.normal.trav_stack_pop )/float(cntrs.code.normal.travs) << ", " << 100.0f*active_normal_trav_stack_pop << "% active" << std::endl;
if (cntrs.all.shadow.travs) {
float active_shadow_travs = float(cntrs.active.shadow.travs )/float(cntrs.all.shadow.travs );
@@ -106,24 +105,24 @@ namespace embree
float active_shadow_trav_prims = float(cntrs.active.shadow.trav_prims )/float(cntrs.all.shadow.trav_prims );
float active_shadow_trav_prim_hits = float(cntrs.active.shadow.trav_prim_hits )/float(cntrs.all.shadow.trav_prim_hits );
cout << " #shadow_travs = " << float(cntrs.code.shadow.travs )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_travs << "% active" << embree_endl;
cout << " #nodes = " << float(cntrs.code.shadow.trav_nodes )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_nodes << "% active" << embree_endl;
cout << " #nodes_xfm = " << float(cntrs.code.shadow.trav_xfm_nodes )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_xfm_nodes << "% active" << embree_endl;
cout << " #leaves = " << float(cntrs.code.shadow.trav_leaves)/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_leaves << "% active" << embree_endl;
cout << " #prims = " << float(cntrs.code.shadow.trav_prims )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_prims << "% active" << embree_endl;
cout << " #prim_hits = " << float(cntrs.code.shadow.trav_prim_hits )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_prim_hits << "% active" << embree_endl;
cout << " #shadow_travs = " << float(cntrs.code.shadow.travs )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_travs << "% active" << std::endl;
cout << " #nodes = " << float(cntrs.code.shadow.trav_nodes )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_nodes << "% active" << std::endl;
cout << " #nodes_xfm = " << float(cntrs.code.shadow.trav_xfm_nodes )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_xfm_nodes << "% active" << std::endl;
cout << " #leaves = " << float(cntrs.code.shadow.trav_leaves)/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_leaves << "% active" << std::endl;
cout << " #prims = " << float(cntrs.code.shadow.trav_prims )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_prims << "% active" << std::endl;
cout << " #prim_hits = " << float(cntrs.code.shadow.trav_prim_hits )/float(cntrs.code.shadow.travs) << ", " << 100.0f*active_shadow_trav_prim_hits << "% active" << std::endl;
}
cout << embree_endl;
cout << std::endl;
/* print user counters for performance tuning */
cout << "--------- USER ---------" << embree_endl;
cout << "--------- USER ---------" << std::endl;
for (size_t i=0; i<10; i++)
cout << "#user" << i << " = " << float(cntrs.user[i])/float(cntrs.all.normal.travs+cntrs.all.shadow.travs) << " per traversal" << embree_endl;
cout << "#user" << i << " = " << float(cntrs.user[i])/float(cntrs.all.normal.travs+cntrs.all.shadow.travs) << " per traversal" << std::endl;
cout << "#user5/user3 " << 100.0f*float(cntrs.user[5])/float(cntrs.user[3]) << "%" << embree_endl;
cout << "#user6/user3 " << 100.0f*float(cntrs.user[6])/float(cntrs.user[3]) << "%" << embree_endl;
cout << "#user7/user3 " << 100.0f*float(cntrs.user[7])/float(cntrs.user[3]) << "%" << embree_endl;
cout << embree_endl;
cout << "#user5/user3 " << 100.0f*float(cntrs.user[5])/float(cntrs.user[3]) << "%" << std::endl;
cout << "#user6/user3 " << 100.0f*float(cntrs.user[6])/float(cntrs.user[3]) << "%" << std::endl;
cout << "#user7/user3 " << 100.0f*float(cntrs.user[7])/float(cntrs.user[3]) << "%" << std::endl;
cout << std::endl;
}
}
-10
View File
@@ -81,7 +81,6 @@ namespace embree
object_accel_mb_min_leaf_size = 1;
object_accel_mb_max_leaf_size = 1;
gpu_build = 0;
max_spatial_split_replications = 1.2f;
useSpatialPreSplits = false;
@@ -421,15 +420,6 @@ namespace embree
}
}
else if (tok == Token::Id("gpu_build"))
{
if (cin->trySymbol("=")) {
Token flag = cin->get();
if (flag == Token::Id("ploc")) gpu_build = 1;
else if (flag == Token::Id("ploc_twolevel")) gpu_build = 2;
}
}
else if (tok == Token::Id("max_spatial_split_replications") && cin->trySymbol("="))
max_spatial_split_replications = cin->get().Float();
-5
View File
@@ -105,12 +105,7 @@ namespace embree
std::string grid_accel_mb; //!< acceleration structure to use for motion blur grids
std::string grid_builder_mb; //!< builder for motion blur grids
//public:
//std::string rthw_builder = "internal"; //!< ray tracing hardware builder to use
public:
int gpu_build; //!< enabled if BVH build should happen on GPU
float max_spatial_split_replications; //!< maximally replications*N many primitives in accel for spatial splits
bool useSpatialPreSplits; //!< use spatial pre-splits instead of the full spatial split builder
size_t tessellation_cache_size; //!< size of the shared tessellation cache
+1
View File
@@ -5,6 +5,7 @@
#cmakedefine EMBREE_STAT_COUNTERS
#cmakedefine EMBREE_BACKFACE_CULLING
#cmakedefine EMBREE_BACKFACE_CULLING_CURVES
#cmakedefine EMBREE_BACKFACE_CULLING_SPHERES
#cmakedefine EMBREE_FILTER_FUNCTION
#cmakedefine EMBREE_IGNORE_INVALID_RAYS
#cmakedefine EMBREE_GEOMETRY_TRIANGLE
+20
View File
@@ -0,0 +1,20 @@
{
global:
rtc*;
_ZN?rtc*;
_ZN??rtc*;
_ZN???rtc*;
_ZN????rtc*;
_ZN??rtc*;
_ZN???rtc*;
_ZN????rtc*;
_ZN?????rtc*;
_ZN???rtc*;
_ZN????rtc*;
_ZN?????rtc*;
_ZN??????rtc*;
_ZN6embree13TaskScheduler*;
_ZN6embree?13TaskScheduler*;
local:
*;
};
+15
View File
@@ -0,0 +1,15 @@
_rtc*
__ZN?rtc*
__ZN??rtc*
__ZN???rtc*
__ZN????rtc*
__ZN??rtc*
__ZN???rtc*
__ZN????rtc*
__ZN?????rtc*
__ZN???rtc*
__ZN????rtc*
__ZN?????rtc*
__ZN??????rtc*
__ZN6embree13TaskScheduler*
__ZN6embree?13TaskScheduler*
+21 -5
View File
@@ -104,10 +104,15 @@ namespace embree
const vfloat<M> t_back = projC0 + td;
const vbool<M> valid_front = valid & (ray.tnear() <= t_front) & (t_front <= ray.tfar);
const vbool<M> valid_back = valid & (ray.tnear() <= t_back ) & (t_back <= ray.tfar);
/* check if there is a first hit */
#if defined (EMBREE_BACKFACE_CULLING_SPHERES)
/* check if there is a first hit */
const vbool<M> valid_first = valid_front;
#else
const vbool<M> valid_back = valid & (ray.tnear() <= t_back ) & (t_back <= ray.tfar);
const vbool<M> valid_first = valid_front | valid_back;
#endif
if (unlikely(none(valid_first)))
return false;
@@ -120,7 +125,10 @@ namespace embree
/* invoke intersection filter for first hit */
const bool is_hit_first = epilog(valid_first, hit);
#if defined (EMBREE_BACKFACE_CULLING_SPHERES)
return is_hit_first;
#else
/* check for possible second hits before potentially accepted hit */
const vfloat<M> t_second = t_back;
const vbool<M> valid_second = valid_front & valid_back & (t_second <= ray.tfar);
@@ -131,8 +139,8 @@ namespace embree
const Vec3vf<M> Ng_second = td_back * ray_dir - perp;
hit = SphereIntersectorHitM<M> (t_second, Ng_second);
const bool is_hit_second = epilog(valid_second, hit);
return is_hit_first | is_hit_second;
#endif
}
template<typename Epilog>
@@ -184,10 +192,14 @@ namespace embree
const vfloat<M> t_back = projC0 + td;
const vbool<M> valid_front = valid & (ray.tnear()[k] <= t_front) & (t_front <= ray.tfar[k]);
const vbool<M> valid_back = valid & (ray.tnear()[k] <= t_back ) & (t_back <= ray.tfar[k]);
/* check if there is a first hit */
#if defined (EMBREE_BACKFACE_CULLING_SPHERES)
const vbool<M> valid_first = valid_front;
#else
const vbool<M> valid_back = valid & (ray.tnear()[k] <= t_back ) & (t_back <= ray.tfar[k]);
const vbool<M> valid_first = valid_front | valid_back;
#endif
if (unlikely(none(valid_first)))
return false;
@@ -200,7 +212,10 @@ namespace embree
/* invoke intersection filter for first hit */
const bool is_hit_first = epilog(valid_first, hit);
#if defined (EMBREE_BACKFACE_CULLING_SPHERES)
return is_hit_first;
#else
/* check for possible second hits before potentially accepted hit */
const vfloat<M> t_second = t_back;
const vbool<M> valid_second = valid_front & valid_back & (t_second <= ray.tfar[k]);
@@ -213,6 +228,7 @@ namespace embree
const bool is_hit_second = epilog(valid_second, hit);
return is_hit_first | is_hit_second;
#endif
}
};
} // namespace isa
+6 -27
View File
@@ -68,8 +68,8 @@ ELSE()
option(EMBREE_BUILDER_TBB_STATIC "Use a staticaly compiled TBB version for the Embree builder for GPU." OFF)
ENDIF()
IF (NOT EMBREE_SYCL_IMPLICIT_DISPATCH_GLOBALS)
ADD_DEFINITIONS("-DEMBREE_SYCL_ALLOC_DISPATCH_GLOBALS")
IF (EMBREE_SYCL_RT_VALIDATION_API AND NOT EMBREE_SYCL_IMPLICIT_DISPATCH_GLOBALS)
ADD_DEFINITIONS("-DEMBREE_SYCL_ALLOC_DISPATCH_GLOBALS")
ENDIF()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-bitwise-instead-of-logical") # disables "use of bitwise '&' with boolean operands" warning
@@ -154,45 +154,29 @@ IF (RTHWIF_STANDALONE)
ENDIF()
IF (EMBREE_SYCL_RT_VALIDATION_API)
ADD_LIBRARY(embree_rthwif_sycl STATIC rttrace/rthwif_production.cpp)
ADD_LIBRARY(embree_rthwif_sycl STATIC rttrace/rttrace_validation.cpp)
SET_PROPERTY(TARGET embree_rthwif_sycl APPEND PROPERTY COMPILE_FLAGS "-DEMBREE_SYCL_SUPPORT")
SET_TARGET_PROPERTIES(embree_rthwif_sycl PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS_SYCL})
INSTALL(TARGETS embree_rthwif_sycl EXPORT embree_rthwif_sycl-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib)
INSTALL(EXPORT embree_rthwif_sycl-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel)
SET(EMBREE_RTHWIF_SYCL embree_rthwif_sycl)
ENDIF()
ADD_LIBRARY(embree_rthwif ${RTHWIF_LIB_TYPE} rtbuild/rthwif_builder.cpp rtbuild/qbvh6.cpp rtbuild/statistics.cpp)
ADD_LIBRARY(embree_rthwif ${RTHWIF_LIB_TYPE} rtbuild/rtbuild.cpp rtbuild/qbvh6.cpp rtbuild/statistics.cpp)
TARGET_LINK_LIBRARIES(embree_rthwif PUBLIC ${EMBREE_RTHWIF_SYCL} PRIVATE ${TBB_TARGET} simd sys)
SET_TARGET_PROPERTIES(embree_rthwif PROPERTIES OUTPUT_NAME ${RTHWIF_NAME})
IF (EMBREE_RTHWIF_STATIC_LIB)
TARGET_COMPILE_DEFINITIONS(embree_rthwif PUBLIC EMBREE_RTHWIF_STATIC_LIB)
TARGET_COMPILE_DEFINITIONS(embree_rthwif PUBLIC EMBREE_RTHWIF_STATIC_LIB)
ENDIF()
IF (EMBREE_SYCL_GPU_BVH_BUILDER)
ADD_LIBRARY(embree_rthwif_gpu STATIC rtbuild/rthwif_embree_builder_ploc.cpp rtbuild/qbvh6.cpp rtbuild/statistics.cpp)
TARGET_LINK_LIBRARIES(embree_rthwif_gpu PUBLIC tbb simd sys -lze_loader)
SET_TARGET_PROPERTIES(embree_rthwif_gpu PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS_SYCL})
ENDIF()
TARGET_LINK_LIBRARIES(embree_rthwif PUBLIC ${EMBREE_RTHWIF_SYCL} PRIVATE ${TBB_TARGET} simd sys)
if (EMBREE_LEVEL_ZERO)
TARGET_LINK_LIBRARIES(embree_rthwif PUBLIC -lze_loader)
TARGET_COMPILE_DEFINITIONS(embree_rthwif PUBLIC EMBREE_LEVEL_ZERO)
TARGET_COMPILE_DEFINITIONS(embree_rthwif PUBLIC EMBREE_SYCL_SUPPORT)
endif()
IF (EMBREE_SYCL_GPU_BVH_BUILDER)
TARGET_LINK_LIBRARIES(embree_rthwif PUBLIC embree_rthwif_gpu)
ENDIF()
SET_PROPERTY(TARGET embree_rthwif APPEND PROPERTY COMPILE_FLAGS "-DEMBREE_SYCL_SUPPORT")
IF (EMBREE_STATIC_LIB OR NOT EMBREE_RTHWIF_STATIC_LIB)
INSTALL(TARGETS embree_rthwif EXPORT ${RTHWIF_NAME}-targets
LIBRARY NAMELINK_SKIP DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib
@@ -201,11 +185,6 @@ IF (EMBREE_STATIC_LIB OR NOT EMBREE_RTHWIF_STATIC_LIB)
INSTALL(EXPORT ${RTHWIF_NAME}-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel)
ENDIF()
IF (EMBREE_SYCL_GPU_BVH_BUILDER)
INSTALL(TARGETS embree_rthwif_gpu EXPORT embree_rthwif_gpu-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib)
INSTALL(EXPORT embree_rthwif_gpu-targets DESTINATION "${EMBREE_CMAKEEXPORT_DIR}" COMPONENT devel)
ENDIF()
IF (EMBREE_LEVEL_ZERO OR RTHWIF_STANDALONE)
ADD_SUBDIRECTORY(testing)
ENDIF()
-507
View File
@@ -1,507 +0,0 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#if defined(EMBREE_SYCL_SUPPORT)
#include "common.h"
namespace embree
{
namespace gpu
{
class AABB3f {
public:
float lower_x,lower_y,lower_z;
float upper_x,upper_y,upper_z;
__forceinline AABB3f() = default;
__forceinline AABB3f(const AABB3f &aabb) : lower_x(aabb.lower_x),
lower_y(aabb.lower_y),
lower_z(aabb.lower_z),
upper_x(aabb.upper_x),
upper_y(aabb.upper_y),
upper_z(aabb.upper_z)
{}
__forceinline AABB3f(const float3 &v) : lower_x(v.x()),
lower_y(v.y()),
lower_z(v.z()),
upper_x(v.x()),
upper_y(v.y()),
upper_z(v.z())
{}
__forceinline AABB3f(const float3 &lower, const float3 &upper) : lower_x(lower.x()),
lower_y(lower.y()),
lower_z(lower.z()),
upper_x(upper.x()),
upper_y(upper.y()),
upper_z(upper.z())
{}
__forceinline AABB3f(const BBox3fa &aabb) : lower_x(aabb.lower.x),
lower_y(aabb.lower.y),
lower_z(aabb.lower.z),
upper_x(aabb.upper.x),
upper_y(aabb.upper.y),
upper_z(aabb.upper.z)
{}
__forceinline AABB3f(const float lower_x, const float lower_y, const float lower_z, const float upper_x, const float upper_y, const float upper_z) : lower_x(lower_x),
lower_y(lower_y),
lower_z(lower_z),
upper_x(upper_x),
upper_y(upper_y),
upper_z(upper_z)
{}
__forceinline bool empty()
{
if (lower_x > upper_x ||
lower_y > upper_y ||
lower_z > upper_z) return true;
return false;
}
__forceinline void init()
{
const float _pos_inf = INFINITY;
const float _neg_inf = -INFINITY;
lower_x = _pos_inf;
lower_y = _pos_inf;
lower_z = _pos_inf;
upper_x = _neg_inf;
upper_y = _neg_inf;
upper_z = _neg_inf;
}
__forceinline void setZero()
{
lower_x = 0.0f;
lower_y = 0.0f;
lower_z = 0.0f;
upper_x = 0.0f;
upper_y = 0.0f;
upper_z = 0.0f;
}
__forceinline bool encloses(const AABB3f &other)
{
if ( other.lower_x < lower_x ||
other.lower_y < lower_y ||
other.lower_z < lower_z )
return false;
if ( other.upper_x > upper_x ||
other.upper_y > upper_y ||
other.upper_z > upper_z )
return false;
return true;
}
__forceinline void extend(const class AABB3f &aabb)
{
lower_x = min(lower_x,aabb.lower_x);
lower_y = min(lower_y,aabb.lower_y);
lower_z = min(lower_z,aabb.lower_z);
upper_x = max(upper_x,aabb.upper_x);
upper_y = max(upper_y,aabb.upper_y);
upper_z = max(upper_z,aabb.upper_z);
}
__forceinline void extend(const class AABB3f &aabb, const uint slot)
{
const uint subgroupLocalID = get_sub_group_local_id();
const bool cmp = subgroupLocalID == slot;
lower_x = cselect(cmp,min(lower_x,aabb.lower_x),lower_x);
lower_y = cselect(cmp,min(lower_y,aabb.lower_y),lower_y);
lower_z = cselect(cmp,min(lower_z,aabb.lower_z),lower_z);
upper_x = cselect(cmp,max(upper_x,aabb.upper_x),upper_x);
upper_y = cselect(cmp,max(upper_y,aabb.upper_y),upper_y);
upper_z = cselect(cmp,max(upper_z,aabb.upper_z),upper_z);
}
__forceinline void extend(const float3 &v)
{
lower_x = min(lower_x,v.x());
lower_y = min(lower_y,v.y());
lower_z = min(lower_z,v.z());
upper_x = max(upper_x,v.x());
upper_y = max(upper_y,v.y());
upper_z = max(upper_z,v.z());
}
__forceinline void extend(const float4 &v)
{
lower_x = min(lower_x,v.x());
lower_y = min(lower_y,v.y());
lower_z = min(lower_z,v.z());
upper_x = max(upper_x,v.x());
upper_y = max(upper_y,v.y());
upper_z = max(upper_z,v.z());
}
__forceinline void extend(const BBox3fa &aabb)
{
lower_x = min(lower_x,aabb.lower.x);
lower_y = min(lower_y,aabb.lower.y);
lower_z = min(lower_z,aabb.lower.z);
upper_x = max(upper_x,aabb.upper.x);
upper_y = max(upper_y,aabb.upper.y);
upper_z = max(upper_z,aabb.upper.z);
}
__forceinline void enlarge(const float &v)
{
lower_x -= v;
lower_y -= v;
lower_z -= v;
upper_x += v;
upper_y += v;
upper_z += v;
}
__forceinline void add(const class AABB3f &aabb)
{
lower_x += aabb.lower_x;
lower_y += aabb.lower_y;
lower_z += aabb.lower_z;
upper_x += aabb.upper_x;
upper_y += aabb.upper_y;
upper_z += aabb.upper_z;
}
__forceinline void mul(const float f)
{
lower_x *= f;
lower_y *= f;
lower_z *= f;
upper_x *= f;
upper_y *= f;
upper_z *= f;
}
__forceinline float3 lower() const { return float3(lower_x,lower_y,lower_z); }
__forceinline float3 upper() const { return float3(upper_x,upper_y,upper_z); }
__forceinline float3 size() const
{
return upper() - lower();
}
__forceinline float3 diag() const
{
return upper() - lower();
}
__forceinline float3 centroid2() const
{
return upper() + lower();
}
__forceinline float3 centroid() const
{
return (upper() + lower())*0.5f;
}
__forceinline float length2() const
{
const float3 diag = size();
return sycl::fma(diag.x(),diag.x(),
sycl::fma(diag.y(),diag.y(),
diag.z() * diag.z()));
}
__forceinline float maxDiagDim() const
{
const float3 d = diag();
return max(max(d.x(),d.y()),d.z());
}
__forceinline void atomic_merge_global(AABB3f &dest) const
{
sycl::atomic_ref<float, sycl::memory_order::relaxed, sycl::memory_scope::device,sycl::access::address_space::global_space> _lower_x(dest.lower_x);
sycl::atomic_ref<float, sycl::memory_order::relaxed, sycl::memory_scope::device,sycl::access::address_space::global_space> _lower_y(dest.lower_y);
sycl::atomic_ref<float, sycl::memory_order::relaxed, sycl::memory_scope::device,sycl::access::address_space::global_space> _lower_z(dest.lower_z);
sycl::atomic_ref<float, sycl::memory_order::relaxed, sycl::memory_scope::device,sycl::access::address_space::global_space> _upper_x(dest.upper_x);
sycl::atomic_ref<float, sycl::memory_order::relaxed, sycl::memory_scope::device,sycl::access::address_space::global_space> _upper_y(dest.upper_y);
sycl::atomic_ref<float, sycl::memory_order::relaxed, sycl::memory_scope::device,sycl::access::address_space::global_space> _upper_z(dest.upper_z);
_lower_x.fetch_min(lower_x);
_lower_y.fetch_min(lower_y);
_lower_z.fetch_min(lower_z);
_upper_x.fetch_max(upper_x);
_upper_y.fetch_max(upper_y);
_upper_z.fetch_max(upper_z);
}
__forceinline void atomic_merge_local(AABB3f &dest) const
{
sycl::atomic_ref<float, sycl::memory_order::relaxed, sycl::memory_scope::work_group,sycl::access::address_space::local_space> _lower_x(dest.lower_x);
sycl::atomic_ref<float, sycl::memory_order::relaxed, sycl::memory_scope::work_group,sycl::access::address_space::local_space> _lower_y(dest.lower_y);
sycl::atomic_ref<float, sycl::memory_order::relaxed, sycl::memory_scope::work_group,sycl::access::address_space::local_space> _lower_z(dest.lower_z);
sycl::atomic_ref<float, sycl::memory_order::relaxed, sycl::memory_scope::work_group,sycl::access::address_space::local_space> _upper_x(dest.upper_x);
sycl::atomic_ref<float, sycl::memory_order::relaxed, sycl::memory_scope::work_group,sycl::access::address_space::local_space> _upper_y(dest.upper_y);
sycl::atomic_ref<float, sycl::memory_order::relaxed, sycl::memory_scope::work_group,sycl::access::address_space::local_space> _upper_z(dest.upper_z);
_lower_x.fetch_min(lower_x);
_lower_y.fetch_min(lower_y);
_lower_z.fetch_min(lower_z);
_upper_x.fetch_max(upper_x);
_upper_y.fetch_max(upper_y);
_upper_z.fetch_max(upper_z);
}
__forceinline AABB3f sub_group_reduce() const
{
AABB3f result;
result.lower_x = embree::sub_group_reduce(lower_x, SYCL_EXT_ONEAPI::minimum<float>());
result.lower_y = embree::sub_group_reduce(lower_y, SYCL_EXT_ONEAPI::minimum<float>());
result.lower_z = embree::sub_group_reduce(lower_z, SYCL_EXT_ONEAPI::minimum<float>());
result.upper_x = embree::sub_group_reduce(upper_x, SYCL_EXT_ONEAPI::maximum<float>());
result.upper_y = embree::sub_group_reduce(upper_y, SYCL_EXT_ONEAPI::maximum<float>());
result.upper_z = embree::sub_group_reduce(upper_z, SYCL_EXT_ONEAPI::maximum<float>());
return result;
}
__forceinline AABB3f sub_group_broadcast(const sycl::id<1> &localID) const
{
AABB3f result;
result.lower_x = embree::sub_group_broadcast<float>(lower_x,localID);
result.lower_y = embree::sub_group_broadcast<float>(lower_y,localID);
result.lower_z = embree::sub_group_broadcast<float>(lower_z,localID);
result.upper_x = embree::sub_group_broadcast<float>(upper_x,localID);
result.upper_y = embree::sub_group_broadcast<float>(upper_y,localID);
result.upper_z = embree::sub_group_broadcast<float>(upper_z,localID);
return result;
}
__forceinline AABB3f sub_group_shuffle(const sycl::id<1> &localID) const
{
AABB3f result;
result.lower_x = embree::sub_group_shuffle<float>(lower_x,localID);
result.lower_y = embree::sub_group_shuffle<float>(lower_y,localID);
result.lower_z = embree::sub_group_shuffle<float>(lower_z,localID);
result.upper_x = embree::sub_group_shuffle<float>(upper_x,localID);
result.upper_y = embree::sub_group_shuffle<float>(upper_y,localID);
result.upper_z = embree::sub_group_shuffle<float>(upper_z,localID);
return result;
}
__forceinline AABB3f sub_group_scan_exclusive_min_max() const
{
AABB3f result;
result.lower_x = embree::sub_group_exclusive_scan(lower_x, SYCL_EXT_ONEAPI::minimum<float>());
result.lower_y = embree::sub_group_exclusive_scan(lower_y, SYCL_EXT_ONEAPI::minimum<float>());
result.lower_z = embree::sub_group_exclusive_scan(lower_z, SYCL_EXT_ONEAPI::minimum<float>());
result.upper_x = embree::sub_group_exclusive_scan(upper_x, SYCL_EXT_ONEAPI::maximum<float>());
result.upper_y = embree::sub_group_exclusive_scan(upper_y, SYCL_EXT_ONEAPI::maximum<float>());
result.upper_z = embree::sub_group_exclusive_scan(upper_z, SYCL_EXT_ONEAPI::maximum<float>());
return result;
}
__forceinline AABB3f sub_group_scan_inclusive_min_max() const
{
AABB3f result;
result.lower_x = embree::sub_group_inclusive_scan(lower_x, SYCL_EXT_ONEAPI::minimum<float>());
result.lower_y = embree::sub_group_inclusive_scan(lower_y, SYCL_EXT_ONEAPI::minimum<float>());
result.lower_z = embree::sub_group_inclusive_scan(lower_z, SYCL_EXT_ONEAPI::minimum<float>());
result.upper_x = embree::sub_group_inclusive_scan(upper_x, SYCL_EXT_ONEAPI::maximum<float>());
result.upper_y = embree::sub_group_inclusive_scan(upper_y, SYCL_EXT_ONEAPI::maximum<float>());
result.upper_z = embree::sub_group_inclusive_scan(upper_z, SYCL_EXT_ONEAPI::maximum<float>());
return result;
}
__forceinline AABB3f work_group_reduce() const
{
AABB3f result;
result.lower_x = work_group_reduce_min(lower_x);
result.lower_y = work_group_reduce_min(lower_y);
result.lower_z = work_group_reduce_min(lower_z);
result.upper_x = work_group_reduce_max(upper_x);
result.upper_y = work_group_reduce_max(upper_y);
result.upper_z = work_group_reduce_max(upper_z);
return result;
}
__forceinline float halfArea() const
{
const float3 d = size();
return halfarea(d);
}
__forceinline float area() const
{
return halfArea() * 2.0f;
}
__forceinline float maxAbsElement() const
{
const float3 abs_l = abs(lower());
const float3 abs_h = abs(upper());
const float max_abs_l = max(max(abs_l.x(),abs_l.y()),abs_l.z());
const float max_abs_h = max(max(abs_h.x(),abs_h.y()),abs_h.z());
return max(max_abs_l,max_abs_h);
}
__forceinline AABB3f sub_group_masked_reduce(const bool cmp) const
{
AABB3f result;
const float _pos_inf = INFINITY;
const float _neg_inf = -INFINITY;
result.lower_x = cselect(cmp,lower_x,_pos_inf);
result.lower_y = cselect(cmp,lower_y,_pos_inf);
result.lower_z = cselect(cmp,lower_z,_pos_inf);
result.upper_x = cselect(cmp,upper_x,_neg_inf);
result.upper_y = cselect(cmp,upper_y,_neg_inf);
result.upper_z = cselect(cmp,upper_z,_neg_inf);
return result.sub_group_reduce();
}
__forceinline AABB3f sub_group_invalidate_reduce_left(const uint pos) const
{
AABB3f result;
const uint subgroupLocalID = get_sub_group_local_id();
const bool cmp = subgroupLocalID <= pos;
const float _pos_inf = INFINITY;
const float _neg_inf = -INFINITY;
result.lower_x = cselect(cmp,lower_x,_pos_inf);
result.lower_y = cselect(cmp,lower_y,_pos_inf);
result.lower_z = cselect(cmp,lower_z,_pos_inf);
result.upper_x = cselect(cmp,upper_x,_neg_inf);
result.upper_y = cselect(cmp,upper_y,_neg_inf);
result.upper_z = cselect(cmp,upper_z,_neg_inf);
return result.sub_group_reduce();
}
__forceinline AABB3f sub_group_invalidate_reduce_right(const uint pos) const
{
AABB3f result;
const uint subgroupLocalID = get_sub_group_local_id();
const bool cmp = subgroupLocalID > pos;
const float _pos_inf = INFINITY;
const float _neg_inf = -INFINITY;
result.lower_x = cselect(cmp,lower_x,_pos_inf);
result.lower_y = cselect(cmp,lower_y,_pos_inf);
result.lower_z = cselect(cmp,lower_z,_pos_inf);
result.upper_x = cselect(cmp,upper_x,_neg_inf);
result.upper_y = cselect(cmp,upper_y,_neg_inf);
result.upper_z = cselect(cmp,upper_z,_neg_inf);
return result.sub_group_reduce();
}
__forceinline AABB3f conservativeBounds() const {
const float ulps = 1.0f;
const float3 abs_l = abs(lower());
const float3 abs_h = abs(upper());
const float max_abs_l = max(max(abs_l.x(),abs_l.y()),abs_l.z());
const float max_abs_h = max(max(abs_h.x(),abs_h.y()),abs_h.z());
const float err = ulps*std::numeric_limits<float>::epsilon() * max(max_abs_l,max_abs_h);
AABB3f bounds(lower(),upper());
bounds.enlarge(err);
return bounds;
}
__forceinline BBox3f convert() const
{
return BBox3f(Vec3f(lower_x,lower_y,lower_z),Vec3f(upper_x,upper_y,upper_z));
}
__forceinline bool checkNumericalBounds() const
{
const static float FLT_LARGE = 1.844E18f;
if (lower_x < -FLT_LARGE || upper_x > FLT_LARGE) return false;
if (lower_y < -FLT_LARGE || upper_y > FLT_LARGE) return false;
if (lower_z < -FLT_LARGE || upper_z > FLT_LARGE) return false;
return true;
}
__forceinline uint numEqualDims() const
{
uint equal_dims = lower_x == upper_x ? 1 : 0;
equal_dims += lower_y == upper_y ? 1 : 0;
equal_dims += lower_z == upper_z ? 1 : 0;
return equal_dims;
}
friend __forceinline embree_ostream operator<<(embree_ostream cout, const AABB3f &aabb)
{
cout << "AABB3f { ";
cout << " lower = (" << aabb.lower_x << ", " << aabb.lower_y << ", " << aabb.lower_z << ") ";
cout << " upper = (" << aabb.upper_x << ", " << aabb.upper_y << ", " << aabb.upper_z << ") ";
return cout << "}";
}
};
__forceinline AABB3f merge(const AABB3f &a, const AABB3f &b)
{
AABB3f bounds;
bounds.lower_x = min(a.lower_x,b.lower_x);
bounds.lower_y = min(a.lower_y,b.lower_y);
bounds.lower_z = min(a.lower_z,b.lower_z);
bounds.upper_x = max(a.upper_x,b.upper_x);
bounds.upper_y = max(a.upper_y,b.upper_y);
bounds.upper_z = max(a.upper_z,b.upper_z);
return bounds;
}
__forceinline AABB3f intersect(const AABB3f &a, const AABB3f &b)
{
AABB3f bounds;
bounds.lower_x = max(a.lower_x,b.lower_x);
bounds.lower_y = max(a.lower_y,b.lower_y);
bounds.lower_z = max(a.lower_z,b.lower_z);
bounds.upper_x = min(a.upper_x,b.upper_x);
bounds.upper_y = min(a.upper_y,b.upper_y);
bounds.upper_z = min(a.upper_z,b.upper_z);
return bounds;
}
__forceinline float distance(const AABB3f &a, const AABB3f &b)
{
const float3 dist_lower = a.lower() - b.lower();
const float3 dist_upper = a.upper() - b.upper();
return sycl::fma(dist_lower.x(),dist_lower.x(),
sycl::fma(dist_lower.y(),dist_lower.y(),
sycl::fma(dist_lower.z(),dist_lower.z(),
sycl::fma(dist_upper.x(),dist_upper.x(),
sycl::fma(dist_upper.y(), dist_upper.y(), dist_upper.z() * dist_upper.z())))));
}
__forceinline bool operator ==(const AABB3f& a, const AABB3f& b) {
if (a.lower_x != b.lower_x ||
a.lower_y != b.lower_y ||
a.lower_z != b.lower_z ||
a.upper_x != b.upper_x ||
a.upper_y != b.upper_y ||
a.upper_z != b.upper_z)
return false;
return true;
}
__forceinline bool operator !=(const AABB3f& a, const AABB3f& b) {
return !(a==b);
}
}
}
#endif
-348
View File
@@ -1,348 +0,0 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "../../../../common/sys/sycl.h"
using sycl::float16;
using sycl::float8;
using sycl::float4;
using sycl::float3;
using sycl::float2;
using sycl::int16;
using sycl::int8;
using sycl::int4;
using sycl::int3;
using sycl::int2;
using sycl::uint16;
using sycl::uint8;
using sycl::uint4;
using sycl::uint3;
using sycl::uint2;
using sycl::uchar16;
using sycl::uchar8;
using sycl::uchar4;
using sycl::uchar3;
using sycl::uchar2;
using sycl::uchar;
using sycl::ushort16;
using sycl::ushort8;
using sycl::ushort4;
using sycl::ushort3;
using sycl::ushort2;
using sycl::fmax;
using sycl::fmin;
namespace embree
{
namespace gpu
{
__forceinline size_t alignTo(const size_t size, const size_t alignment)
{
return ((size+alignment-1)/alignment)*alignment;
}
template<typename T>
__forceinline T cfma(const T &a, const T &b, const T &c)
{
return sycl::fma(a,b,c);
}
template<typename T>
__forceinline T lerp(const T &a, const T &b, const float t) {
return sycl::fma(T(1.0f-t),a,T(t)*b);
}
__forceinline float halfarea(const sycl::float3 &d)
{
return sycl::fma(d.x(),d.y(),sycl::fma(d.x(),d.z(),d.y()*d.z()));
}
__forceinline float halfarea(const sycl::float4 &d)
{
return sycl::fma((float)d.x(),((float)d.y()+(float)d.z()),(float)d.y()*(float)d.z());
}
__forceinline float area(const sycl::float3 &d)
{
return halfarea(d) * 2.0f;
}
__forceinline float area(const sycl::float4 &d)
{
return halfarea(d) * 2.0f;
}
__forceinline float dot3(const float3 &a,
const float3 &b)
{
return sycl::dot(a,b);
}
template<typename T>
static __forceinline uint atomic_add_global(T *dest, const T count=1)
{
sycl::atomic_ref<T, sycl::memory_order::relaxed, sycl::memory_scope::device,sycl::access::address_space::global_space> counter(*dest);
return counter.fetch_add(count);
}
template<typename T>
static __forceinline uint atomic_min_global(T *dest, const T count=1)
{
sycl::atomic_ref<T, sycl::memory_order::relaxed, sycl::memory_scope::device,sycl::access::address_space::global_space> counter(*dest);
return counter.fetch_min(count);
}
template<typename T>
static __forceinline uint atomic_max_global(T *dest, const T count=1)
{
sycl::atomic_ref<T, sycl::memory_order::relaxed, sycl::memory_scope::device,sycl::access::address_space::global_space> counter(*dest);
return counter.fetch_max(count);
}
template<typename T>
static __forceinline uint atomic_or_global(T *dest, const T count=1)
{
sycl::atomic_ref<T, sycl::memory_order::relaxed, sycl::memory_scope::device,sycl::access::address_space::global_space> counter(*dest);
return counter.fetch_or(count);
}
template<typename T>
static __forceinline uint atomic_add_local(T *dest, const T count=1)
{
sycl::atomic_ref<T, sycl::memory_order::relaxed, sycl::memory_scope::work_group,sycl::access::address_space::local_space> counter(*dest);
return counter.fetch_add(count);
}
template<typename T>
static __forceinline uint atomic_min_local(T *dest, const T count=1)
{
sycl::atomic_ref<T, sycl::memory_order::relaxed, sycl::memory_scope::work_group,sycl::access::address_space::local_space> counter(*dest);
return counter.fetch_min(count);
}
template<typename T>
static __forceinline uint atomic_max_local(T *dest, const T count=1)
{
sycl::atomic_ref<T, sycl::memory_order::relaxed, sycl::memory_scope::work_group,sycl::access::address_space::local_space> counter(*dest);
return counter.fetch_max(count);
}
template<typename T>
static __forceinline uint atomic_or_local(T *dest, const T count=1)
{
sycl::atomic_ref<T, sycl::memory_order::relaxed, sycl::memory_scope::work_group,sycl::access::address_space::local_space> counter(*dest);
return counter.fetch_or(count);
}
template<typename T>
static __forceinline uint as_uint(T t)
{
return __builtin_bit_cast(uint,t);
}
template<typename T>
static __forceinline uint as_int(T t)
{
return __builtin_bit_cast(int,t);
}
template<typename T>
static __forceinline float as_float(T t)
{
return __builtin_bit_cast(float,t);
}
template<typename T>
static __forceinline void* as_void(T t)
{
return __builtin_bit_cast(void*,t);
}
__forceinline uint bitInterleave3D(const uint3 &in)
{
uint x = in.x(), y = in.y(), z = in.z();
x = (x | (x << 16)) & 0x030000FF;
x = (x | (x << 8)) & 0x0300F00F;
x = (x | (x << 4)) & 0x030C30C3;
x = (x | (x << 2)) & 0x09249249;
y = (y | (y << 16)) & 0x030000FF;
y = (y | (y << 8)) & 0x0300F00F;
y = (y | (y << 4)) & 0x030C30C3;
y = (y | (y << 2)) & 0x09249249;
z = (z | (z << 16)) & 0x030000FF;
z = (z | (z << 8)) & 0x0300F00F;
z = (z | (z << 4)) & 0x030C30C3;
z = (z | (z << 2)) & 0x09249249;
return x | (y << 1) | (z << 2);
}
__forceinline uint bitInterleave4D(const uint4 &in)
{
uint x = in.x(), y = in.y(), z = in.z(), w = in.w();
x = x & 0x000000ff;
x = (x ^ (x << 16)) & 0x00c0003f;
x = (x ^ (x << 8)) & 0x00c03807;
x = (x ^ (x << 4)) & 0x08530853;
x = (x ^ (x << 2)) & 0x09090909;
x = (x ^ (x << 1)) & 0x11111111;
y = y & 0x000000ff;
y = (y ^ (y << 16)) & 0x00c0003f;
y = (y ^ (y << 8)) & 0x00c03807;
y = (y ^ (y << 4)) & 0x08530853;
y = (y ^ (y << 2)) & 0x09090909;
y = (y ^ (y << 1)) & 0x11111111;
z = z & 0x000000ff;
z = (z ^ (z << 16)) & 0x00c0003f;
z = (z ^ (z << 8)) & 0x00c03807;
z = (z ^ (z << 4)) & 0x08530853;
z = (z ^ (z << 2)) & 0x09090909;
z = (z ^ (z << 1)) & 0x11111111;
w = w & 0x000000ff;
w = (w ^ (w << 16)) & 0x00c0003f;
w = (w ^ (w << 8)) & 0x00c03807;
w = (w ^ (w << 4)) & 0x08530853;
w = (w ^ (w << 2)) & 0x09090909;
w = (w ^ (w << 1)) & 0x11111111;
return (x | (y << 1) | (z << 2) | (w << 3));
}
__forceinline uint64_t splitBy3(const uint a){
uint64_t x = a & 0x1fffff;
x = (x | x << 32) & 0x1f00000000ffff;
x = (x | x << 16) & 0x1f0000ff0000ff;
x = (x | x << 8) & 0x100f00f00f00f00f;
x = (x | x << 4) & 0x10c30c30c30c30c3;
x = (x | x << 2) & 0x1249249249249249;
return x;
}
__forceinline uint64_t bitInterleave3D_64bits(const uint3 v){
return splitBy3(v.x()) | splitBy3(v.y()) << 1 | splitBy3(v.z()) << 2;
}
__forceinline uint64_t bitInterleave4D_64bits(const uint4 &v){
const uint low = bitInterleave4D(v>>0);
const uint high = bitInterleave4D(v>>8);
return (((uint64_t)high)<<32) | low;
}
__forceinline uint atomic_add_global_sub_group_shared(sycl::atomic_ref<uint, sycl::memory_order::relaxed, sycl::memory_scope::device,sycl::access::address_space::global_space> &counter, const uint add)
{
const uint subgroupLocalID = get_sub_group_local_id();
const uint ballot = sub_group_ballot(true);
const uint first = sycl::ctz(ballot);
const uint popc = sycl::popcount(ballot);
const uint prefix = sycl::popcount(ballot & (((uint)1 << subgroupLocalID)-1));
uint index = 0;
if (subgroupLocalID == first)
index = counter.fetch_add(popc * add);
index = sub_group_broadcast(index,first);
return index + prefix;
}
__forceinline uint atomic_add_local_sub_group_shared(sycl::atomic_ref<uint, sycl::memory_order::relaxed, sycl::memory_scope::work_group,sycl::access::address_space::local_space> &counter, const uint add)
{
const uint subgroupLocalID = get_sub_group_local_id();
const uint ballot = sub_group_ballot(true);
const uint first = sycl::ctz(ballot);
const uint popc = sycl::popcount(ballot);
const uint prefix = sycl::popcount(ballot & (((uint)1 << subgroupLocalID)-1));
uint index = 0;
if (subgroupLocalID == first)
index = counter.fetch_add(popc * add);
index = sub_group_broadcast(index,first);
return index + prefix;
}
template<typename T>
__forceinline uint atomic_add_global_sub_group_varying(sycl::atomic_ref<T, sycl::memory_order::relaxed, sycl::memory_scope::device,sycl::access::address_space::global_space> &counter, const T add)
{
const uint subgroupLocalID = get_sub_group_local_id();
const uint ballot = sub_group_ballot(true);
const uint first = sycl::ctz(ballot);
const T total = sub_group_reduce(add, SYCL_EXT_ONEAPI::plus<T>());
const T prefix = sub_group_exclusive_scan(add, SYCL_EXT_ONEAPI::plus<T>());
uint index = 0;
if (subgroupLocalID == first)
index = counter.fetch_add(total);
index = sub_group_broadcast(index,first);
return index + prefix;
}
template<typename T>
static __forceinline T atomic_add_global_sub_group_varying(T *dest, const T count=1)
{
sycl::atomic_ref<T, sycl::memory_order::relaxed, sycl::memory_scope::device,sycl::access::address_space::global_space> counter(*dest);
return atomic_add_global_sub_group_varying(counter,count);
}
template<typename T>
__forceinline uint atomic_add_local_sub_group_varying(sycl::atomic_ref<T, sycl::memory_order::relaxed, sycl::memory_scope::device,sycl::access::address_space::local_space> &counter, const T add)
{
const uint subgroupLocalID = get_sub_group_local_id();
const uint ballot = sub_group_ballot(true);
const uint first = sycl::ctz(ballot);
const T total = sub_group_reduce(add, SYCL_EXT_ONEAPI::plus<T>());
const T prefix = sub_group_exclusive_scan(add, SYCL_EXT_ONEAPI::plus<T>());
uint index = 0;
if (subgroupLocalID == first)
index = counter.fetch_add(total);
index = sub_group_broadcast(index,first);
return index + prefix;
}
template<typename T>
static __forceinline T atomic_add_local_sub_group_varying(T *dest, const T count=1)
{
sycl::atomic_ref<T, sycl::memory_order::relaxed, sycl::memory_scope::device,sycl::access::address_space::local_space> counter(*dest);
return sub_group_shared_varying_local_atomic(counter,count);
}
__forceinline void waitOnQueueAndCatchException(sycl::queue &gpu_queue)
{
try {
gpu_queue.wait_and_throw();
} catch (sycl::exception const& e) {
std::cout << "Caught synchronous SYCL exception:\n"
<< e.what() << std::endl;
FATAL("SYCL Exception");
}
}
__forceinline void waitOnEventAndCatchException(sycl::event &event)
{
try {
event.wait_and_throw();
} catch (sycl::exception const& e) {
std::cout << "Caught synchronous SYCL exception:\n"
<< e.what() << std::endl;
FATAL("SYCL Exception");
}
}
__forceinline double getDeviceExecutionTiming(sycl::event &queue_event)
{
const auto t0 = queue_event.template get_profiling_info<sycl::info::event_profiling::command_start>();
const auto t1 = queue_event.template get_profiling_info<sycl::info::event_profiling::command_end>();
return (t1-t0)*1E-6;
}
};
};
-289
View File
@@ -1,289 +0,0 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#if defined(EMBREE_SYCL_SUPPORT)
#include "common.h"
namespace embree
{
namespace gpu
{
struct Range {
uint start;
uint end;
__forceinline Range()
{}
__forceinline Range(const uint start, const uint end) : start(start), end(end)
{}
__forceinline uint size() const { return end-start; }
__forceinline uint center() const { return (end+start)>>1; }
};
// ================================================================================================================================================================================
// ============================================================================= MORTON CODES =====================================================================================
// ================================================================================================================================================================================
struct __aligned(8) MortonCodePrimitive40x24Bits3D
{
static const uint GRID_SHIFT = 13; // * 3 = 30
static const uint CODE_SHIFT = 64-(3*GRID_SHIFT+1);
static const uint64_t INDEX_MASK = ((uint64_t)1 << CODE_SHIFT)-1;
uint64_t index_code; // 64bit code + index combo
__forceinline MortonCodePrimitive40x24Bits3D() {}
__forceinline MortonCodePrimitive40x24Bits3D(const uint64_t code, const uint index) { index_code = (code << CODE_SHIFT) | (uint64_t)index; }
__forceinline MortonCodePrimitive40x24Bits3D(const uint3 &v, const uint index)
{
const uint64_t code = gpu::bitInterleave3D(v);
MortonCodePrimitive40x24Bits3D(code,index);
}
__forceinline uint getIndex() const { return (uint)(index_code & INDEX_MASK); }
__forceinline uint64_t getCode() const { return index_code; }
__forceinline uint64_t getMCode() const { return index_code & (~INDEX_MASK); }
__forceinline operator const uint64_t&() const { return index_code; }
__forceinline bool operator < (const MortonCodePrimitive40x24Bits3D& mc) const
{
return index_code < mc.index_code;
}
};
struct __aligned(8) MortonCodePrimitive40x24Bits4D
{
static const uint GRID_SHIFT = 10; // * 4 = 40
static const uint CODE_SHIFT = 64-4*GRID_SHIFT;
static const uint64_t INDEX_MASK = ((uint64_t)1 << CODE_SHIFT)-1;
uint64_t index_code; // 64bit code + index combo
__forceinline MortonCodePrimitive40x24Bits4D() {}
__forceinline MortonCodePrimitive40x24Bits4D(const uint64_t code, const uint index) { index_code = (code << CODE_SHIFT) | (uint64_t)index; }
__forceinline MortonCodePrimitive40x24Bits4D(const uint4 &v, const uint index)
{
const uint64_t code = gpu::bitInterleave4D(v);
MortonCodePrimitive40x24Bits4D(code,index);
}
__forceinline uint getIndex() const { return (uint)(index_code & INDEX_MASK); }
__forceinline uint64_t getCode() const { return index_code; }
__forceinline uint64_t getMCode() const { return index_code & (~INDEX_MASK); }
__forceinline operator const uint64_t&() const { return index_code; }
__forceinline bool operator < (const MortonCodePrimitive40x24Bits4D& mc) const
{
return index_code < mc.index_code;
}
};
/* used by PLOC in a two phase process */
struct __aligned(8) MortonCodePrimitive64Bit_2x
{
static const uint GRID_SHIFT = 21; // * 3 = 63
static const uint CODE_SHIFT = 32;
static const uint64_t INDEX_MASK = ((uint64_t)1 << CODE_SHIFT)-1;
uint64_t index_code; // 64bit code + index combo
__forceinline MortonCodePrimitive64Bit_2x() {}
__forceinline MortonCodePrimitive64Bit_2x(const uint64_t code, const uint index) { index_code = (code << CODE_SHIFT) | (uint64_t)index; }
__forceinline uint getIndex() const { return (uint)(index_code & INDEX_MASK); }
__forceinline uint64_t getCode() const { return index_code; }
__forceinline uint64_t getMCode() const { return index_code & (~INDEX_MASK); }
__forceinline operator const uint64_t&() const { return index_code; }
__forceinline bool operator < (const MortonCodePrimitive64Bit_2x& mc) const
{
return index_code < mc.index_code;
}
};
struct MortonCodePrimitive64x32Bits3D
{
static const uint GRID_SHIFT = 21; // * 3 = 63
static const uint KEY_BITS = 64;
uint64_t code;
uint index;
__forceinline MortonCodePrimitive64x32Bits3D() {}
__forceinline MortonCodePrimitive64x32Bits3D(const uint64_t code, const uint index) : code(code), index(index) {}
__forceinline MortonCodePrimitive64x32Bits3D(const uint3 &v, const uint index) : code(gpu::bitInterleave3D_64bits(v)), index(index)
{
}
__forceinline bool operator < (const MortonCodePrimitive64x32Bits3D& emc) const
{
if (code < emc.code)
return true;
else if (code == emc.code)
return index < emc.index;
else
return false;
}
__forceinline uint64_t getCode() const { return code; }
__forceinline uint64_t getMCode() const { return code; }
__forceinline uint getIndex() const { return index; }
__forceinline operator const uint64_t&() const { return code; }
};
struct MortonCodePrimitive64x32Bits4D
{
static const uint GRID_SHIFT = 16; // * 4 = 64
static const uint KEY_BITS = 64;
uint64_t code;
uint index;
__forceinline MortonCodePrimitive64x32Bits4D() {}
__forceinline MortonCodePrimitive64x32Bits4D(const uint64_t code, const uint index) : code(code), index(index) {}
__forceinline MortonCodePrimitive64x32Bits4D(const uint4 &v, const uint index) : code( gpu::bitInterleave4D_64bits(v)), index(index)
{
}
__forceinline bool operator < (const MortonCodePrimitive64x32Bits4D& emc) const
{
if (code < emc.code)
return true;
else if (code == emc.code)
return index < emc.index;
else
return false;
}
__forceinline uint64_t getCode() const { return code; }
__forceinline uint64_t getMCode() const { return code; }
__forceinline uint getIndex() const { return index; }
__forceinline operator const uint64_t&() const { return code; }
};
template<typename type>
__forceinline unsigned int findSplit64Bit(const gpu::Range &current, const type *const morton)
{
const uint64_t code_start = morton[current.start].getCode();
const uint64_t code_end = morton[current.end-1].getCode();
if (code_start != code_end)
{
uint64_t bitpos = sycl::clz(code_start^code_end);
/* split the items at the topmost different morton code bit */
const uint64_t bitpos_diff = 63-bitpos;
const uint64_t bitmask = (uint64_t)1 << bitpos_diff;
/* find location where bit differs using binary search */
unsigned int begin = current.start;
unsigned int end = current.end;
while (begin + 1 != end) {
const unsigned int mid = (begin+end)/2;
const uint64_t bit = morton[mid].getCode() & bitmask;
if (bit == 0) begin = mid; else end = mid;
}
unsigned int center = end;
return center;
}
else /* if all items mapped to same morton code */
{
uint bitpos = sycl::clz(morton[current.start].getIndex()^morton[current.end-1].getIndex());
/* split the items at the topmost different morton code bit */
const uint bitpos_diff = 31-bitpos;
const uint bitmask = (uint)1 << bitpos_diff;
/* find location where bit differs using binary search */
unsigned int begin = current.start;
unsigned int end = current.end;
while (begin + 1 != end) {
const unsigned int mid = (begin+end)/2;
const uint bit = morton[mid].getIndex() & bitmask;
if (bit == 0) begin = mid; else end = mid;
}
unsigned int center = end;
return center;
}
}
template<typename type>
__forceinline uint delta(const type& m0, const type& m1)
{
return m0.getCode() != m1 .getCode() ? (m0.getCode()^m1.getCode()) : m0.getIndex()^m1.getIndex(); //sycl::ext::intel::ctz(m0.index_code^m1.index_code);
}
template<typename type>
__forceinline void splitRange(const gpu::Range &current, const type *const morton, gpu::Range &left, gpu::Range &right)
{
const uint split = findSplit64Bit(current,morton);
left.start = current.start;
left.end = split;
right.start = split;
right.end = current.end;
}
template<typename type>
__forceinline int sigma(const int i1, const int i2, const type *const morton, const uint numPrimitives)
{
const int left = min(i1, i2);
const int right = max(i1, i2);
if (left < 0 || right >= numPrimitives) return -1;
const ulong left_code = morton[left].getCode();
const ulong right_code = morton[right].getCode();
if (left_code != right_code)
return sycl::clz(left_code ^ right_code);
else
return 64 + sycl::clz(morton[left].getIndex() ^ morton[right].getIndex());
}
template<typename type>
__forceinline struct gpu::Range findSegment(const unsigned int idx, const type *const mc, uint const numPrimitives)
{
const int delta = sigma(idx, idx+1, mc, numPrimitives) >= sigma(idx, idx-1, mc, numPrimitives) ? 1 : -1;
const int sigma_min = sigma(idx, idx-delta, mc, numPrimitives);
int max_range = 2;
while (sigma(idx,idx + max_range * delta, mc, numPrimitives) > sigma_min)
max_range <<= 1;
int step = 0;
int r = max_range;
do
{
r >>= 1;
if(sigma(idx, idx + (step + r)*delta, mc, numPrimitives) > sigma_min)
step += r;
}
while (r > 1);
struct gpu::Range range;
range.start = min(idx, idx + step*delta);
range.end = max(idx, idx + step*delta) + 1;
return range;
}
}
}
#endif
-379
View File
@@ -1,379 +0,0 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#if defined(EMBREE_SYCL_SUPPORT)
#include "common.h"
#define RADIX_SORT_BINS 256
#define RADIX_SORT_MAX_NUM_DSS 128
#define RADIX_SORT_WG_SIZE 512
#define RADIX_ITERATIONS_64BIT 8
namespace embree
{
namespace gpu
{
__forceinline uint getNumWGsScratchSize(const ssize_t scratch_size)
{
return min(max( (int)floorf(scratch_size / (sizeof(uint)*RADIX_SORT_BINS))-1,(int)1),RADIX_SORT_MAX_NUM_DSS);
}
__forceinline void localAtomicBallot(uint *const histogram, const uint ID, const uint add)
{
uint mask = sub_group_ballot(true);
while(mask)
{
const uint first = sycl::ctz(mask);
const uint index = sub_group_broadcast(ID,first);
const bool cmp = ID == index;
const uint cmp_mask = sub_group_ballot(cmp);
const uint reduced_count = sycl::popcount(cmp_mask) * add;
mask &= ~cmp_mask;
sycl::atomic_ref<uint, sycl::memory_order::relaxed, sycl::memory_scope::work_group,sycl::access::address_space::local_space> hist(histogram[ID]);
if (get_sub_group_local_id() == first)
hist += reduced_count;
}
}
__forceinline void radix_sort_single_workgroup(sycl::queue &gpu_queue, uint64_t *_input, uint64_t *_output, const uint numPrimitives, const uint start_iteration, const uint stop_iteration)
{
static const uint RADIX_SORT_SINGLE_WG_SIZE = 256;
struct __aligned(RADIX_SORT_SINGLE_WG_SIZE/32 * sizeof(uint)) BinFlags
{
uint flags[RADIX_SORT_SINGLE_WG_SIZE/32];
};
const sycl::nd_range<1> nd_range1(RADIX_SORT_SINGLE_WG_SIZE,sycl::range<1>(RADIX_SORT_SINGLE_WG_SIZE));
sycl::event event = gpu_queue.submit([&](sycl::handler &cgh) {
sycl::local_accessor< uint, 1> histogram(sycl::range<1>(RADIX_SORT_SINGLE_WG_SIZE),cgh);
sycl::local_accessor< uint, 1> sums(sycl::range<1>(RADIX_SORT_SINGLE_WG_SIZE),cgh);
sycl::local_accessor< uint, 1> prefix_sums(sycl::range<1>(RADIX_SORT_SINGLE_WG_SIZE),cgh);
sycl::local_accessor< uint, 1> local_offset(sycl::range<1>(RADIX_SORT_SINGLE_WG_SIZE),cgh);
sycl::local_accessor< BinFlags, 1> bin_flags(sycl::range<1>(RADIX_SORT_BINS),cgh);
cgh.parallel_for(nd_range1,[=](sycl::nd_item<1> item) EMBREE_SYCL_SIMD(16)
{
const uint localID = item.get_local_id(0);
const uint step_local = item.get_local_range().size();
const uint subgroupID = get_sub_group_id();
const uint subgroupSize = get_sub_group_size();
const uint subgroupLocalID = get_sub_group_local_id();
for (uint iter = start_iteration;iter<stop_iteration;iter++)
{
item.barrier(sycl::access::fence_space::local_space);
const uint shift = iter*8;
const uint64_t *const input = (iter % 2) == 0 ? _input : _output;
uint64_t *const output = (iter % 2) == 1 ? _input : _output;
// ==== bin key into global histogram =====
if (localID < RADIX_SORT_BINS)
histogram[localID] = 0;
item.barrier(sycl::access::fence_space::local_space);
for (uint ID = localID; ID < numPrimitives; ID += step_local)
{
const uint bin = ((uint)(input[ID] >> shift)) & (RADIX_SORT_BINS - 1);
//localAtomicBallot(histogram.get_pointer(),bin,1);
gpu::atomic_add_local((uint*)histogram.get_pointer() + bin,(uint)1);
}
item.barrier(sycl::access::fence_space::local_space);
// ==== reduce global histogram =====
SYCL_EXT_ONEAPI::sub_group sub_group = this_sub_group();
sub_group.barrier();
if (localID < RADIX_SORT_BINS)
{
const uint count = histogram[localID];
const uint sum = sub_group_reduce(count, std::plus<uint>());
const uint prefix_sum = sub_group_exclusive_scan(count, std::plus<uint>());
sums[localID] = sum;
prefix_sums[localID] = prefix_sum;
}
item.barrier(sycl::access::fence_space::local_space);
if (subgroupID == 0)
{
uint off = 0;
for (int i = subgroupLocalID; i < RADIX_SORT_BINS; i += subgroupSize)
{
local_offset[i] = off + prefix_sums[i];
off += sums[i];
}
}
item.barrier(sycl::access::fence_space::local_space);
// ==== scatter key/value pairs according to global historgram =====
const uint flags_bin = localID / 32;
const uint flags_bit = 1 << (localID % 32);
for (uint blockID = 0; blockID < numPrimitives; blockID += step_local)
{
item.barrier(sycl::access::fence_space::local_space);
const uint ID = blockID + localID;
uint binID = 0;
uint binOffset = 0;
if (localID < RADIX_SORT_BINS)
for (int i=0;i<RADIX_SORT_SINGLE_WG_SIZE/32;i++)
bin_flags[localID].flags[i] = 0;
item.barrier(sycl::access::fence_space::local_space);
uint64_t in;
if (ID < numPrimitives)
{
in = input[ID];
binID = (in >> shift) & (RADIX_SORT_BINS - 1);
binOffset = local_offset[binID];
sycl::atomic_ref<uint, sycl::memory_order::relaxed, sycl::memory_scope::work_group,sycl::access::address_space::local_space> bflags(bin_flags[binID].flags[flags_bin]);
bflags.fetch_add(flags_bit);
}
item.barrier(sycl::access::fence_space::local_space);
if (ID < numPrimitives)
{
uint prefix = 0;
uint count = 0;
for (uint i = 0; i < RADIX_SORT_SINGLE_WG_SIZE / 32; i++)
{
const uint bits = bin_flags[binID].flags[i];
const uint full_count = sycl::popcount(bits);
const uint partial_count = sycl::popcount(bits & (flags_bit - 1));
prefix += (i < flags_bin) ? full_count : 0;
prefix += (i == flags_bin) ? partial_count : 0;
count += full_count;
}
output[binOffset + prefix] = in;
if (prefix == count - 1)
local_offset[binID] += count;
}
}
}
});
});
try {
event.wait_and_throw();
} catch (sycl::exception const& e) {
std::cout << "Caught synchronous SYCL exception:\n"
<< e.what() << std::endl;
FATAL("SYCL Exception");
}
}
template<typename sort_type>
sycl::event radix_sort_iteration_type(sycl::queue &gpu_queue, sycl::event &input_event, sort_type *input, sort_type *output, const uint primitives, uint *global_histogram, const uint iter, const uint RADIX_SORT_NUM_DSS=256)
{
const uint shift = iter*8;
// ==== bin key into global histogram =====
const sycl::nd_range<1> nd_range_binning(sycl::range<1>(RADIX_SORT_WG_SIZE*RADIX_SORT_NUM_DSS),sycl::range<1>(RADIX_SORT_WG_SIZE));
sycl::event bin_event = gpu_queue.submit([&](sycl::handler &cgh) {
cgh.depends_on(input_event);
sycl::local_accessor< uint, 1> histogram(sycl::range<1>(RADIX_SORT_BINS),cgh);
cgh.parallel_for(nd_range_binning,[=](sycl::nd_item<1> item) EMBREE_SYCL_SIMD(16)
{
const uint localID = item.get_local_id(0);
const uint step_local = item.get_local_range().size();
const uint groupID = item.get_group(0);
const uint startID = ((size_t)groupID + 0)*(size_t)primitives / RADIX_SORT_NUM_DSS;
const uint endID = ((size_t)groupID + 1)*(size_t)primitives / RADIX_SORT_NUM_DSS;
if (localID < RADIX_SORT_BINS)
histogram[localID] = 0;
item.barrier(sycl::access::fence_space::local_space);
for (uint ID = startID + localID; ID < endID; ID += step_local)
{
const uint64_t key = input[ID];
const uint bin = ((uint)(key >> shift)) & (RADIX_SORT_BINS - 1);
//gpu::localAtomicBallot(histogram.get_pointer(),bin,1);
gpu::atomic_add_local((uint*)histogram.get_pointer() + bin,(uint)1);
}
item.barrier(sycl::access::fence_space::local_space);
if (localID < RADIX_SORT_BINS)
global_histogram[RADIX_SORT_BINS*groupID + localID] = histogram[localID];
});
});
// ==== scatter key/value pairs according to global historgram =====
struct __aligned(64) BinFlags
{
uint flags[RADIX_SORT_WG_SIZE/32];
};
const sycl::nd_range<1> nd_range_scatter(sycl::range<1>(RADIX_SORT_WG_SIZE*RADIX_SORT_NUM_DSS),sycl::range<1>(RADIX_SORT_WG_SIZE));
sycl::event scatter_event = gpu_queue.submit([&](sycl::handler &cgh) {
cgh.depends_on(bin_event);
sycl::local_accessor< uint, 1> local_offset(sycl::range<1>(RADIX_SORT_BINS),cgh);
sycl::local_accessor< uint, 1> sums(sycl::range<1>(RADIX_SORT_BINS),cgh);
sycl::local_accessor< BinFlags, 1> bin_flags(sycl::range<1>(RADIX_SORT_BINS),cgh);
cgh.parallel_for(nd_range_scatter,[=](sycl::nd_item<1> item) EMBREE_SYCL_SIMD(16)
{
const uint groupID = item.get_group(0);
const uint localID = item.get_local_id(0);
const uint step_local = item.get_local_range().size();
const uint subgroupID = get_sub_group_id();
const uint subgroupLocalID = get_sub_group_local_id();
const uint startID = ((size_t)groupID + 0)*(size_t)primitives / RADIX_SORT_NUM_DSS;
const uint endID = ((size_t)groupID + 1)*(size_t)primitives / RADIX_SORT_NUM_DSS;
/* --- reduce global histogram --- */
uint local_hist = 0;
uint prefix_sum = 0;
if (localID < RADIX_SORT_BINS)
{
uint t = 0;
for (uint j = 0; j < RADIX_SORT_NUM_DSS; j++)
{
const uint count = global_histogram[RADIX_SORT_BINS*j + localID];
local_hist = (j == groupID) ? t : local_hist;
t += count;
}
const uint count = t;
const uint sum = sub_group_reduce(count, std::plus<uint>());
prefix_sum = sub_group_exclusive_scan(count, std::plus<uint>());
sums[subgroupID] = sum;
}
item.barrier(sycl::access::fence_space::local_space);
if (localID < RADIX_SORT_BINS)
{
const uint sums_prefix_sum = sub_group_broadcast(sub_group_exclusive_scan(sums[subgroupLocalID], std::plus<uint>()),subgroupID);
const uint global_hist = sums_prefix_sum + prefix_sum;
local_offset[localID] = global_hist + local_hist;
}
// === barrier comes later ===
const uint flags_bin = localID / 32;
const uint flags_bit = 1 << (localID % 32);
for (uint blockID = startID; blockID < endID; blockID += step_local)
{
const uint ID = blockID + localID;
uint binID = 0;
uint binOffset = 0;
#if 0
if (localID < RADIX_SORT_BINS)
for (int i=0;i<RADIX_SORT_WG_SIZE/32;i++)
bin_flags[localID].flags[i] = 0;
#else
uint *const bflags = (uint*)&bin_flags.get_pointer()[0];
for (uint i=localID;i<RADIX_SORT_BINS*RADIX_SORT_WG_SIZE/32;i+=step_local)
bflags[i] = 0;
#endif
item.barrier(sycl::access::fence_space::local_space);
sort_type key_value;
uint64_t key;
if (ID < endID)
{
key_value = input[ID];
key = key_value;
binID = (key >> shift) & (RADIX_SORT_BINS - 1);
binOffset = local_offset[binID];
sycl::atomic_ref<uint, sycl::memory_order::relaxed, sycl::memory_scope::work_group,sycl::access::address_space::local_space> bflags(bin_flags[binID].flags[flags_bin]);
bflags += flags_bit;
}
item.barrier(sycl::access::fence_space::local_space);
if (ID < endID)
{
uint prefix = 0;
uint count = 0;
for (uint i = 0; i < RADIX_SORT_WG_SIZE / 32; i++)
{
const uint bits = bin_flags[binID].flags[i];
const uint full_count = sycl::popcount(bits);
const uint partial_count = sycl::popcount(bits & (flags_bit - 1));
prefix += (i < flags_bin) ? full_count : 0;
prefix += (i == flags_bin) ? partial_count : 0;
count += full_count;
}
output[binOffset + prefix] = key_value;
if (prefix == count - 1)
local_offset[binID] += count;
}
item.barrier(sycl::access::fence_space::local_space);
}
});
});
return scatter_event;
}
template<typename sort_type>
sycl::event radix_sort_Nx8Bit(sycl::queue &gpu_queue, sort_type *input, sort_type *output, const uint items, uint *global_histogram, const uint start_iteration, const uint end_iteration, sycl::event &initial, const uint RADIX_SORT_NUM_DSS=256)
{
sycl::event events[8]; // 8x8=64bit maximum
for (uint i=start_iteration;i<end_iteration;i++)
{
events[i] = radix_sort_iteration_type<sort_type>(gpu_queue,i == start_iteration ? initial : events[i-1],input,output,items,global_histogram,i,RADIX_SORT_NUM_DSS);
std::swap(input,output);
}
return events[end_iteration-1];
}
};
};
#endif
+20 -25
View File
@@ -3,6 +3,14 @@
#pragma once
#if defined(ZE_RAYTRACING)
#include "sys/sysinfo.h"
#include "sys/vector.h"
#include "math/vec2.h"
#include "math/vec3.h"
#include "math/bbox.h"
#include "math/affinespace.h"
#else
#include "../../../common/sys/sysinfo.h"
#include "../../../common/sys/vector.h"
#include "../../../common/math/vec2.h"
@@ -10,6 +18,7 @@
#include "../../../common/math/bbox.h"
#include "../../../common/math/lbbox.h"
#include "../../../common/math/affinespace.h"
#endif
#include <map>
#include <bitset>
@@ -81,13 +90,11 @@ namespace embree
PrimLeafDesc(uint32_t shaderIndex, uint32_t geomIndex, GeometryFlags gflags, uint32_t geomMask, Type type = TYPE_NONE)
: shaderIndex(shaderIndex), geomMask(geomMask), geomIndex(geomIndex), type(type), geomFlags((uint32_t)gflags)
{
#if !defined(__SYCL_DEVICE_ONLY__)
if (shaderIndex > MAX_SHADER_INDEX)
throw std::runtime_error("too large shader ID");
if (geomIndex > MAX_GEOM_INDEX)
throw std::runtime_error("too large geometry ID");
#endif
}
/* compares two PrimLeafDesc's for equality */
@@ -139,7 +146,6 @@ namespace embree
public:
uint32_t shaderIndex : 24; // shader index used for shader record calculations
uint32_t geomMask : 8; // geometry mask used for ray masking
uint32_t geomIndex : 29; // the geometry index specifies the n'th geometry of the scene
/*Type*/ uint32_t type : 1; // enable/disable culling for procedurals and instances
@@ -159,10 +165,6 @@ namespace embree
{
QuadLeaf() {}
QuadLeaf(const QuadLeaf &q) {
memcpy( this,&q, sizeof(QuadLeaf) );
}
QuadLeaf (Vec3f v0, Vec3f v1, Vec3f v2, Vec3f v3,
uint8_t j0, uint8_t j1, uint8_t j2,
uint32_t shaderIndex, uint32_t geomIndex, uint32_t primIndex0, uint32_t primIndex1,
@@ -179,9 +181,6 @@ namespace embree
* distance between them can be at most 0xFFFF as we use 16 bits
* to encode that difference. */
assert(primIndex0 <= primIndex1 && primIndex1 - primIndex0 < 0xFFFF);
// #if !defined(__SYCL_DEVICE_ONLY__)
// print(std::cout,0);
// #endif
}
/* returns the i'th vertex */
@@ -283,26 +282,22 @@ namespace embree
}
public:
union {
struct {
PrimLeafDesc leafDesc; // the leaf header
uint32_t primIndex0; // primitive index of first triangle
struct {
uint32_t primIndex1Delta : 16; // delta encoded primitive index of second triangle
uint32_t j0 : 2; // specifies first vertex of second triangle
uint32_t j1 : 2; // specified second vertex of second triangle
uint32_t j2 : 2; // specified third vertex of second triangle
uint32_t last : 1; // true if the second triangle is the last triangle in a leaf list
uint32_t pad : 9; // unused bits
};
};
uint header[4];
PrimLeafDesc leafDesc; // the leaf header
uint32_t primIndex0; // primitive index of first triangle
struct {
uint32_t primIndex1Delta : 16; // delta encoded primitive index of second triangle
uint32_t j0 : 2; // specifies first vertex of second triangle
uint32_t j1 : 2; // specified second vertex of second triangle
uint32_t j2 : 2; // specified third vertex of second triangle
uint32_t last : 1; // true if the second triangle is the last triangle in a leaf list
uint32_t pad : 9; // unused bits
};
Vec3f v0; // first vertex of first triangle
Vec3f v1; // second vertex of first triangle
Vec3f v2; // third vertex of first triangle
Vec3f v3; // forth vertex used for second triangle
Vec3f v3; // forth vertex used for second triangle
};
static_assert(sizeof(QuadLeaf) == 64, "QuadLeaf must be 64 bytes large");
+7 -15
View File
@@ -6,7 +6,7 @@
namespace embree
{
template<typename InternalNode>
void computeInternalNodeStatistics(BVHStatistics& stats, QBVH6::Node node, const BBox1f time_range, const float node_bounds_area, const float root_bounds_area, size_t depth)
void computeInternalNodeStatistics(BVHStatistics& stats, QBVH6::Node node, const BBox1f time_range, const float node_bounds_area, const float root_bounds_area)
{
InternalNode* inner = node.innerNode<InternalNode>();
@@ -16,7 +16,7 @@ namespace embree
if (inner->valid(i))
{
size++;
computeStatistics(stats, inner->child(i), time_range, area(inner->bounds(i)), root_bounds_area, InternalNode::NUM_CHILDREN, depth+1);
computeStatistics(stats, inner->child(i), time_range, area(inner->bounds(i)), root_bounds_area, InternalNode::NUM_CHILDREN);
}
}
@@ -26,10 +26,9 @@ namespace embree
stats.internalNode.numChildrenTotal += InternalNode::NUM_CHILDREN;
stats.internalNode.nodeSAH += time_range.size() * node_bounds_area / root_bounds_area;
stats.internalNode.numBytes += sizeof(InternalNode);
stats.depth = max(stats.depth, depth);
}
void computeStatistics(BVHStatistics& stats, QBVH6::Node node, const BBox1f time_range, const float node_bounds_area, const float root_bounds_area, uint32_t numChildren, size_t depth)
void computeStatistics(BVHStatistics& stats, QBVH6::Node node, const BBox1f time_range, const float node_bounds_area, const float root_bounds_area, uint32_t numChildren)
{
switch (node.type)
{
@@ -109,7 +108,7 @@ namespace embree
}
case NODE_TYPE_INTERNAL:
{
computeInternalNodeStatistics<QBVH6::InternalNode6>(stats, node, time_range, node_bounds_area, root_bounds_area, depth);
computeInternalNodeStatistics<QBVH6::InternalNode6>(stats, node, time_range, node_bounds_area, root_bounds_area);
break;
}
default:
@@ -120,15 +119,14 @@ namespace embree
BVHStatistics QBVH6::computeStatistics() const
{
BVHStatistics stats;
if (empty()) return stats;
embree::computeStatistics(stats,root(),BBox1f(0,1),area(bounds),area(bounds),6,1);
if (empty()) return stats;
embree::computeStatistics(stats,root(),BBox1f(0,1),area(bounds),area(bounds),6);
return stats;
}
template<typename QInternalNode>
void QBVH6::printInternalNodeStatistics(std::ostream& cout, QBVH6::Node node, uint32_t depth, uint32_t numChildren)
{
#if !defined(__SYCL_DEVICE_ONLY__)
QInternalNode* inner = node.innerNode<QInternalNode>();
inner->print(cout, depth, false);
std::cout << std::endl;
@@ -140,14 +138,10 @@ namespace embree
}
cout << tab(depth) << "}" << std::endl;
#endif
}
void QBVH6::print( std::ostream& cout, QBVH6::Node node, uint32_t depth, uint32_t numChildren)
{
#if !defined(__SYCL_DEVICE_ONLY__)
if (depth == 1) return;
switch (node.type)
{
case NODE_TYPE_INSTANCE: {
@@ -220,7 +214,6 @@ namespace embree
std::cout << "{ INVALID_NODE }" << std::endl;
//assert(false);
}
#endif
}
unsigned* getBackPointersData(const QBVH6* base) { // FIXME: should be member function
@@ -241,7 +234,7 @@ namespace embree
void QBVH6::print ( std::ostream& cout ) const
{
#if !defined(__SYCL_DEVICE_ONLY__)
cout << "QBVH @ "<< this <<" header: {\n";
cout << " rootNodeOffset = " << rootNodeOffset << std::endl;
cout << " bounds = " << bounds << std::endl;
@@ -268,7 +261,6 @@ namespace embree
}
cout << "}\n";
}
#endif
}
template<typename QInternalNode>
+92 -89
View File
@@ -6,12 +6,20 @@
#include "qbvh6.h"
#include "statistics.h"
#include "quadifier.h"
#include "rthwif_builder.h"
#include "rtbuild.h"
#include <atomic>
#if defined(ZE_RAYTRACING)
#include "builders/priminfo.h"
#include "builders/primrefgen_presplit.h"
#include "builders/heuristic_binning_array_aligned.h"
#include "algorithms/parallel_for_for_prefix_sum.h"
#else
#include "../../builders/priminfo.h"
#include "../../builders/primrefgen_presplit.h"
#include "../../builders/heuristic_binning_array_aligned.h"
#include "../../../common/algorithms/parallel_for_for_prefix_sum.h"
#endif
namespace embree
{
@@ -25,6 +33,11 @@ namespace embree
/* the type of primitive that is referenced */
enum Type { TRIANGLE=0, QUAD=1, PROCEDURAL=2, INSTANCE=3, UNKNOWN=4, NUM_TYPES=5 };
/* check when we use spatial splits */
static bool useSpatialSplits(ze_rtas_builder_build_quality_hint_exp_t build_quality, ze_rtas_builder_build_op_exp_flags_t build_flags) {
return build_quality == ZE_RTAS_BUILDER_BUILD_QUALITY_HINT_EXP_HIGH && !(build_flags & ZE_RTAS_BUILDER_BUILD_OP_EXP_FLAG_NO_DUPLICATE_ANYHIT_INVOCATION);
}
/* BVH allocator */
struct Allocator
{
@@ -42,22 +55,22 @@ namespace embree
__forceinline void* malloc(size_t bytes, size_t align = 16)
{
assert(align <= RTHWIF_ACCELERATION_STRUCTURE_ALIGNMENT);
if (likely(cur.load() >= end)) throw std::bad_alloc();
assert(align <= 128); //ZE_RAYTRACING_ACCELERATION_STRUCTURE_ALIGNMENT_EXT
if (unlikely(cur.load() >= end)) return nullptr;
const size_t extra = (align - cur) & (align-1);
const size_t bytes_align = bytes + extra;
const size_t cur_old = cur.fetch_add(bytes_align);
const size_t cur_new = cur_old + bytes_align;
if (likely(cur_new > end)) throw std::bad_alloc();
if (unlikely(cur_new >= end)) return nullptr;
return &ptr[cur_old + extra];
}
private:
char* ptr; // data buffer pointer
size_t end; // size of data buffer in bytes
__aligned(64) std::atomic<size_t> cur; // current pointer to allocate next data block from
};
/* triangle data for leaf creation */
struct Triangle
{
@@ -191,12 +204,10 @@ namespace embree
__forceinline size_t end () const { return prims.end(); }
__forceinline size_t size () const { return prims.size(); }
__forceinline bool equalType() const { return type != UNKNOWN; }
#if !defined(__SYCL_DEVICE_ONLY__)
friend inline std::ostream& operator<<(std::ostream& cout, const BuildRecord& r) {
return cout << "BuildRecord { depth = " << r.depth << ", pinfo = " << r.prims << ", type = " << r.type << " }";
}
#endif
public:
size_t depth; //!< Depth of the root of this subtree.
@@ -226,10 +237,12 @@ namespace embree
struct ReductionTy
{
ReductionTy() {}
ReductionTy() : node(nullptr) {}
ReductionTy (void* node, NodeType type, uint8_t nodeMask, PrimRange primRange)
: node((char*)node), type(type), nodeMask(nodeMask), primRange(primRange) {}
inline bool valid() { return node != nullptr; }
public:
char* node;
NodeType type;
@@ -308,7 +321,8 @@ namespace embree
const getProceduralFunc& getProcedural,
const getInstanceFunc& getInstance,
void* scratch_ptr, size_t scratch_bytes,
RTHWIF_BUILD_QUALITY build_quality,
ze_rtas_builder_build_quality_hint_exp_t build_quality,
ze_rtas_builder_build_op_exp_flags_t build_flags,
bool verbose)
: getSize(getSize),
getType(getType),
@@ -320,6 +334,7 @@ namespace embree
getInstance(getInstance),
prims(scratch_ptr,scratch_bytes),
build_quality(build_quality),
build_flags(build_flags),
verbose(verbose) {}
ReductionTy setInternalNode(char* curAddr, size_t curBytes, NodeType nodeTy, char* childAddr,
@@ -395,7 +410,7 @@ namespace embree
return QuadLeaf(quad.p0,quad.p1,quad.p3,quad.p2, 3,2,1, 0, geomID, primID, primID, quad.gflags, quad.gmask, false );
}
}
const ReductionTy createQuads(Type ty, const BuildRecord& curRecord, char* curAddr_)
{
QuadLeaf* curAddr = (QuadLeaf*) curAddr_;
@@ -414,17 +429,20 @@ namespace embree
{
/*! allocate data for all children */
char* childData = (char*) allocator.malloc(curRecord.prims.size()*sizeof(QuadLeaf), 64);
if (!childData)
return ReductionTy();
/* create each child */
ReductionTy values[BVH_WIDTH];
for (size_t i=0, j=0; i<numChildren; i++) {
values[i] = createQuads(ty,children[i],childData+j*sizeof(QuadLeaf));
j += children[i].size();
}
return setNode(curAddr,curBytes,NODE_TYPE_QUAD,childData,children,values,numChildren);
}
const ReductionTy createProcedurals(const BuildRecord& curRecord, char* curAddr, size_t curBytes)
{
const uint32_t numPrims MAYBE_UNUSED = curRecord.size();
@@ -442,9 +460,12 @@ namespace embree
numGeometries += desc0 != desc1;
desc0 = desc1;
}
char* childData = (char*) allocator.malloc(numGeometries*sizeof(ProceduralLeaf), 64);
if (!childData)
return ReductionTy();
ProceduralLeafBuilder procedural_leaf_builder(childData, numGeometries);
ProceduralLeaf* first_procedural = procedural_leaf_builder.getCurProcedural();
@@ -476,7 +497,10 @@ namespace embree
/* allocate data for all children */
InstanceLeaf* childData = (InstanceLeaf*) allocator.malloc(numPrimitives*sizeof(InstanceLeaf), 64);
if (!childData)
return ReductionTy();
QBVH6::InternalNode6* qnode = new (curAddr) QBVH6::InternalNode6(curRecord.bounds(),NODE_TYPE_INSTANCE);
qnode->setChildOffset(childData);
@@ -683,10 +707,10 @@ namespace embree
return createInstances(curRecord,curAddr,curBytes);
else
assert(false);
return ReductionTy();
}
const ReductionTy createLargeLeaf(const BuildRecord& curRecord, char* curAddr, size_t curBytes)
{
/* this should never occur but is a fatal error */
@@ -719,21 +743,25 @@ namespace embree
/*! allocate data for all children */
size_t childrenBytes = numChildren*sizeof(QBVH6::InternalNode6);
char* childBase = (char*) allocator.malloc(childrenBytes, 64);
if (!childBase)
return ReductionTy();
/* recurse into each child and perform reduction */
char* childPtr = childBase;
for (size_t i=0; i<numChildren; i++) {
values[i] = createLargeLeaf(children[i],childPtr,sizeof(QBVH6::InternalNode6));
if (!values[i].valid()) return ReductionTy();
childPtr += sizeof(QBVH6::InternalNode6);
}
return setNode(curAddr,curBytes,NODE_TYPE_INTERNAL,childBase,children,values,numChildren);
}
const ReductionTy createInternalNode(BuildRecord& curRecord, char* curAddr, size_t curBytes)
{
/* create leaf when threshold reached or we are too deep */
bool createLeaf = curRecord.prims.size() <= cfg.leafSize[curRecord.type] ||
bool createLeaf = curRecord.prims.size() <= cfg.leafSize[curRecord.type] ||
curRecord.depth+MIN_LARGE_LEAF_LEVELS >= cfg.maxDepth;
bool performTypeSplit = !curRecord.equalType() && (createLeaf || curRecord.size() <= cfg.typeSplitSize);
@@ -787,28 +815,41 @@ namespace embree
/*! allocate data for all children */
size_t childrenBytes = numChildren*sizeof(QBVH6::InternalNode6);
char* childBase = (char*) allocator.malloc(childrenBytes, 64);
if (!childBase)
return ReductionTy();
/* spawn tasks */
if (curRecord.size() > 1024) // cfg.singleThreadThreshold
{
std::atomic<bool> success = true;
parallel_for(size_t(0), numChildren, [&] (const range<size_t>& r) {
if (!success) return;
for (size_t i=r.begin(); i<r.end(); i++) {
values[i] = createInternalNode(/*nullptr,*/children[i],childBase+i*sizeof(QBVH6::InternalNode6),sizeof(QBVH6::InternalNode6));
values[i] = createInternalNode(children[i],childBase+i*sizeof(QBVH6::InternalNode6),sizeof(QBVH6::InternalNode6));
if (!values[i].valid()) {
success = false;
return;
}
}
});
if (!success)
return ReductionTy();
/* create node */
return setNode(curAddr,curBytes,NODE_TYPE_INTERNAL,childBase,children,values,numChildren);
}
/* recurse into each child */
else
{
/* recurse into each child */
for (size_t i=0; i<numChildren; i++) {
values[i] = createInternalNode(children[i],childBase+i*sizeof(QBVH6::InternalNode6),sizeof(QBVH6::InternalNode6));
if (!values[i].valid()) return ReductionTy();
}
/* create node */
return setNode(curAddr,curBytes,NODE_TYPE_INTERNAL,childBase,children,values,numChildren);
}
@@ -1013,9 +1054,6 @@ namespace embree
ReductionTy build(uint32_t numGeometries, PrimInfo& pinfo_o, char* root)
{
//PING;
//PRINT(numGeometries);
double t1 = verbose ? getSeconds() : 0.0;
/* quadify all triangles */
@@ -1043,7 +1081,7 @@ namespace embree
}, [](const PrimInfo& a, const PrimInfo& b) -> PrimInfo { return PrimInfo::merge(a,b); });
double t3 = verbose ? getSeconds() : 0.0;
if (verbose) std::cout << "primrefgen : " << numPrimitives << " " << std::setw(10) << (t3-t2)*1000.0 << "ms, " << std::setw(10) << 1E-6*double(numPrimitives)/(t3-t2) << " Mprims/s" << std::endl;
if (verbose) std::cout << "primrefgen : " << std::setw(10) << (t3-t2)*1000.0 << "ms, " << std::setw(10) << 1E-6*double(numPrimitives)/(t3-t2) << " Mprims/s" << std::endl;
/* if we need to filter out geometry, run again */
if (pinfo.size() != numPrimitives)
@@ -1064,10 +1102,8 @@ namespace embree
if (verbose) std::cout << "primrefgen2 : " << std::setw(10) << (t4-t3)*1000.0 << "ms, " << std::setw(10) << 1E-6*double(numPrimitives)/(t4-t3) << " Mprims/s" << std::endl;
/* perform pre-splitting */
if ((build_quality == RTHWIF_BUILD_QUALITY_HIGH) && numPrimitives)
if (useSpatialSplits(build_quality,build_flags) && numPrimitives)
{
PRINT("PRE-SPLITTING DISABLED");
auto splitter = [this] (const PrimRef& prim, const size_t dim, const float pos, PrimRef& left_o, PrimRef& right_o) {
splitTriangleOrQuad(prim,dim,pos,left_o,right_o);
};
@@ -1109,7 +1145,7 @@ namespace embree
return r;
}
void build(size_t numGeometries, char* accel, size_t bytes, BBox3f* boundsOut, size_t* accelBufferBytesOut, void* dispatchGlobalsPtr)
bool build(size_t numGeometries, char* accel, size_t bytes, BBox3f* boundsOut, size_t* accelBufferBytesOut, void* dispatchGlobalsPtr)
{
double t0 = verbose ? getSeconds() : 0.0;
@@ -1159,6 +1195,12 @@ namespace embree
/* build BVH static BVH */
QBVH6::InternalNode6* root = roots+0;
ReductionTy r = build(numGeometries,pinfo,(char*)root);
/* check if build failed */
if (!r.valid()) {
return false;
}
bounds.extend(pinfo.geomBounds);
if (boundsOut) *boundsOut = bounds;
@@ -1175,14 +1217,6 @@ namespace embree
qbvh->numTimeSegments = 1;
qbvh->dispatchGlobalsPtr = (uint64_t) dispatchGlobalsPtr;
#if 0
BVHStatistics stats2 = qbvh->computeStatistics();
stats2.print(std::cout);
stats2.print_raw(std::cout);
qbvh->print();
#endif
#if 0
BVHStatistics stats = qbvh->computeStatistics();
stats.print(std::cout);
@@ -1194,44 +1228,10 @@ namespace embree
for (size_t i=0; i<bytes; i++) {
if (i % 32 == 0) std::cout << std::endl << " ";
std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0') << (unsigned)((unsigned char*)accel)[i] << ", ";
=======
/* fill QBVH6 header */
allocator.clear();
QBVH6* qbvh = new (accel.data()) QBVH6(QBVH6::SizeEstimate());
qbvh->numPrims = numPrimitives;
uint64_t rootNodeOffset = QBVH6::Node((char*)(r0.node - (char*)qbvh), r0.type, r0.primRange.cur_prim);
assert(rootNodeOffset == QBVH6::rootNodeOffset);
qbvh->bounds = bounds;
qbvh->numTimeSegments = max(1u,maxTimeSegments);
qbvh->dispatchGlobalsPtr = (uint64_t) dispatchGlobalsPtr;
break;
}
catch (std::bad_alloc&)
{
if (verbose) {
allocator.cleanup();
FastAllocator::AllStatistics stats1(&allocator);
stats1.print(numPrimitives);
}
if (bytes >= worst_case_bytes) {
throw std::runtime_error("BVH build failed");
return empty;
}
}
}
/* print BVH statistics in verbose mode */
if (verbose)
{
QBVH6* qbvh = (QBVH6*) accel.data();
BVHStatistics stats = qbvh->computeStatistics();
stats.print(std::cout);
stats.print_raw(std::cout);
qbvh->print();
}
std::cout << std::endl << "};" << std::endl;*/
#endif
return true;
}
private:
@@ -1247,18 +1247,20 @@ namespace embree
evector<PrimRef> prims;
Allocator allocator;
std::vector<std::vector<uint16_t>> quadification;
RTHWIF_BUILD_QUALITY build_quality;
ze_rtas_builder_build_quality_hint_exp_t build_quality;
ze_rtas_builder_build_op_exp_flags_t build_flags;
bool verbose;
};
template<typename getSizeFunc,
typename getTypeFunc>
static void estimateSize(size_t numGeometries,
const getSizeFunc& getSize,
const getTypeFunc& getType,
RTHWIF_BUILD_QUALITY build_quality,
ze_rtas_builder_build_quality_hint_exp_t build_quality,
ze_rtas_builder_build_op_exp_flags_t build_flags,
size_t& expectedBytes,
size_t& worstCaseBytes,
size_t& scratchBytes)
@@ -1278,7 +1280,7 @@ namespace embree
};
}
if (build_quality == RTHWIF_BUILD_QUALITY_HIGH)
if (useSpatialSplits(build_quality,build_flags))
stats.estimate_presplits(1.2);
worstCaseBytes = stats.worst_case_bvh_bytes();
@@ -1296,7 +1298,7 @@ namespace embree
typename getProceduralFunc,
typename getInstanceFunc>
static void build(size_t numGeometries,
static bool build(size_t numGeometries,
Device* device,
const getSizeFunc& getSize,
const getTypeFunc& getType,
@@ -1310,7 +1312,8 @@ namespace embree
void* scratch_ptr, size_t scratch_bytes,
BBox3f* boundsOut,
size_t* accelBufferBytesOut,
RTHWIF_BUILD_QUALITY build_quality,
ze_rtas_builder_build_quality_hint_exp_t build_quality,
ze_rtas_builder_build_op_exp_flags_t build_flags,
bool verbose,
void* dispatchGlobalsPtr)
{
@@ -1320,10 +1323,10 @@ namespace embree
throw std::runtime_error("scratch buffer cannot get aligned");
BuilderT<getSizeFunc, getTypeFunc, createPrimRefArrayFunc, getTriangleFunc, getTriangleIndicesFunc, getQuadFunc, getProceduralFunc, getInstanceFunc> builder
(device, getSize, getType, createPrimRefArray, getTriangle, getTriangleIndices, getQuad, getProcedural, getInstance, scratch_ptr, scratch_bytes, build_quality, verbose);
(device, getSize, getType, createPrimRefArray, getTriangle, getTriangleIndices, getQuad, getProcedural, getInstance, scratch_ptr, scratch_bytes, build_quality, build_flags, verbose);
builder.build(numGeometries, accel_ptr, accel_bytes, boundsOut, accelBufferBytesOut, dispatchGlobalsPtr);
}
return builder.build(numGeometries, accel_ptr, accel_bytes, boundsOut, accelBufferBytesOut, dispatchGlobalsPtr);
}
};
}
}
+10 -12
View File
@@ -183,12 +183,12 @@ namespace embree
NodeType nodeType; // the type of the node
uint8_t pad; // unused byte
int8_t exp_x; // 2^exp_x is the size of the grid in x dimension
int8_t exp_y; // 2^exp_y is the size of the grid in y dimension
int8_t exp_z; // 2^exp_z is the size of the grid in z dimension
uint8_t nodeMask; // mask used for ray filtering
struct ChildData
{
uint8_t blockIncr : 2; // size of child in 64 byte blocks
@@ -196,14 +196,12 @@ namespace embree
uint8_t pad : 2; // unused bits
} childData[NUM_CHILDREN];
struct {
uint8_t lower_x[NUM_CHILDREN]; // the quantized lower bounds in x-dimension
uint8_t upper_x[NUM_CHILDREN]; // the quantized upper bounds in x-dimension
uint8_t lower_y[NUM_CHILDREN]; // the quantized lower bounds in y-dimension
uint8_t upper_y[NUM_CHILDREN]; // the quantized upper bounds in y-dimension
uint8_t lower_z[NUM_CHILDREN]; // the quantized lower bounds in z-dimension
uint8_t upper_z[NUM_CHILDREN]; // the quantized upper bounds in z-dimension
};
uint8_t lower_x[NUM_CHILDREN]; // the quantized lower bounds in x-dimension
uint8_t upper_x[NUM_CHILDREN]; // the quantized upper bounds in x-dimension
uint8_t lower_y[NUM_CHILDREN]; // the quantized lower bounds in y-dimension
uint8_t upper_y[NUM_CHILDREN]; // the quantized upper bounds in y-dimension
uint8_t lower_z[NUM_CHILDREN]; // the quantized lower bounds in z-dimension
uint8_t upper_z[NUM_CHILDREN]; // the quantized upper bounds in z-dimension
};
static_assert(sizeof(InternalNode6Data) == 64, "InternalNode6Data must be 64 bytes large");
@@ -372,7 +370,6 @@ namespace embree
int64_t getChildOffset(uint32_t childID) const
{
int64_t ofs = this->childOffset;
if (ofs == 0) FATAL("OFFSET == 0");
for (uint32_t j = 0; j < childID; j++)
ofs += this->childData[j].blockIncr;
return 64 * ofs;
@@ -488,7 +485,7 @@ namespace embree
dst->setChildOffset((char*)this + getChildOffset(0));
}
#if !defined(__RTRT_GSIM) && !defined(__SYCL_DEVICE_ONLY__)
#if !defined(__RTRT_GSIM)
/* output of internal node */
void print(std::ostream& cout, uint32_t depth, bool close) const
@@ -498,6 +495,7 @@ namespace embree
cout << tab(depth) << " childOffset = " << 64 * int64_t(this->childOffset) << std::endl;
cout << tab(depth) << " nodeType = " << NodeType(this->nodeType) << std::endl;
cout << tab(depth) << " nodeMask = " << std::bitset<8>(this->nodeMask) << std::endl;
for (uint32_t i = 0; i < NUM_CHILDREN; i++)
{
cout << tab(depth) << " child" << i << " = { ";
+14 -5
View File
@@ -3,9 +3,16 @@
#pragma once
#if defined(ZE_RAYTRACING)
#include "sys/sysinfo.h"
#include "sys/vector.h"
#include "math/vec2.h"
#include "math/vec3.h"
#include "math/bbox.h"
#include "math/affinespace.h"
#else
#include "../../common/default.h"
#define WINDOW_SIZE 32
#endif
namespace embree
{
@@ -80,7 +87,7 @@ namespace embree
}
template<typename GetTriangleFunc>
__forceinline void merge_triangle_window( uint32_t geomID, static_deque<uint32_t,WINDOW_SIZE>& triangleWindow, QuadifierType* quads_o, const GetTriangleFunc& getTriangle )
__forceinline void merge_triangle_window( uint32_t geomID, static_deque<uint32_t,32>& triangleWindow, QuadifierType* quads_o, const GetTriangleFunc& getTriangle )
{
uint32_t primID0 = triangleWindow.pop_front();
@@ -120,7 +127,7 @@ namespace embree
template<typename GetTriangleFunc>
inline size_t pair_triangles( uint32_t geomID, QuadifierType* quads_o, uint32_t primID0, uint32_t primID1, const GetTriangleFunc& getTriangle )
{
static_deque<uint32_t, WINDOW_SIZE> triangleWindow;
static_deque<uint32_t, 32> triangleWindow;
size_t numTrianglePairs = 0;
for (uint32_t primID=primID0; primID<primID1; primID++)
@@ -131,11 +138,13 @@ namespace embree
merge_triangle_window(geomID, triangleWindow,quads_o,getTriangle);
numTrianglePairs++;
}
}
}
while (triangleWindow.size()) {
merge_triangle_window(geomID, triangleWindow,quads_o,getTriangle);
numTrianglePairs++;
}
return numTrianglePairs;
}
}
+807
View File
@@ -0,0 +1,807 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#define RTHWIF_EXPORT_API
#include "rtbuild.h"
#include "qbvh6_builder_sah.h"
namespace embree
{
using namespace embree::isa;
static std::unique_ptr<tbb::task_arena> g_arena;
typedef enum _ze_raytracing_accel_format_internal_t {
ZE_RTAS_DEVICE_FORMAT_EXP_INVALID = 0, // invalid acceleration structure format
ZE_RTAS_DEVICE_FORMAT_EXP_VERSION_1 = 1, // acceleration structure format version 1
ZE_RTAS_DEVICE_FORMAT_EXP_VERSION_2 = 2, // acceleration structure format version 2
ZE_RTAS_DEVICE_FORMAT_EXP_VERSION_MAX = 2
} ze_raytracing_accel_format_internal_t;
inline ze_rtas_triangle_indices_uint32_exp_t getPrimitive(const ze_rtas_builder_triangles_geometry_info_exp_t* geom, uint32_t primID) {
assert(primID < geom->triangleCount);
return *(ze_rtas_triangle_indices_uint32_exp_t*)((char*)geom->pTriangleBuffer + uint64_t(primID)*geom->triangleStride);
}
inline Vec3f getVertex(const ze_rtas_builder_triangles_geometry_info_exp_t* geom, uint32_t vertexID) {
assert(vertexID < geom->vertexCount);
return *(Vec3f*)((char*)geom->pVertexBuffer + uint64_t(vertexID)*geom->vertexStride);
}
inline ze_rtas_quad_indices_uint32_exp_t getPrimitive(const ze_rtas_builder_quads_geometry_info_exp_t* geom, uint32_t primID) {
assert(primID < geom->quadCount);
return *(ze_rtas_quad_indices_uint32_exp_t*)((char*)geom->pQuadBuffer + uint64_t(primID)*geom->quadStride);
}
inline Vec3f getVertex(const ze_rtas_builder_quads_geometry_info_exp_t* geom, uint32_t vertexID) {
assert(vertexID < geom->vertexCount);
return *(Vec3f*)((char*)geom->pVertexBuffer + uint64_t(vertexID)*geom->vertexStride);
}
inline AffineSpace3fa getTransform(const ze_rtas_builder_instance_geometry_info_exp_t* geom)
{
switch (geom->transformFormat)
{
case ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3X4_COLUMN_MAJOR: {
const ze_rtas_transform_float3x4_column_major_exp_t* xfm = (const ze_rtas_transform_float3x4_column_major_exp_t*) geom->pTransform;
return {
{ xfm->vx_x, xfm->vx_y, xfm->vx_z },
{ xfm->vy_x, xfm->vy_y, xfm->vy_z },
{ xfm->vz_x, xfm->vz_y, xfm->vz_z },
{ xfm-> p_x, xfm-> p_y, xfm-> p_z }
};
}
case ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3X4_ALIGNED_COLUMN_MAJOR: {
const ze_rtas_transform_float3x4_aligned_column_major_exp_t* xfm = (const ze_rtas_transform_float3x4_aligned_column_major_exp_t*) geom->pTransform;
return {
{ xfm->vx_x, xfm->vx_y, xfm->vx_z },
{ xfm->vy_x, xfm->vy_y, xfm->vy_z },
{ xfm->vz_x, xfm->vz_y, xfm->vz_z },
{ xfm-> p_x, xfm-> p_y, xfm-> p_z }
};
}
case ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3X4_ROW_MAJOR: {
const ze_rtas_transform_float3x4_row_major_exp_t* xfm = (const ze_rtas_transform_float3x4_row_major_exp_t*) geom->pTransform;
return {
{ xfm->vx_x, xfm->vx_y, xfm->vx_z },
{ xfm->vy_x, xfm->vy_y, xfm->vy_z },
{ xfm->vz_x, xfm->vz_y, xfm->vz_z },
{ xfm-> p_x, xfm-> p_y, xfm-> p_z }
};
}
default:
throw std::runtime_error("invalid transform format");
}
}
inline void verifyGeometryDesc(const ze_rtas_builder_triangles_geometry_info_exp_t* geom)
{
if (geom->triangleFormat != ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_TRIANGLE_INDICES_UINT32)
throw std::runtime_error("triangle format must be ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_TRIANGLE_INDICES_UINT32");
if (geom->vertexFormat != ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3)
throw std::runtime_error("vertex format must be ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3");
if (geom->triangleCount && geom->pTriangleBuffer == nullptr) throw std::runtime_error("no triangle buffer specified");
if (geom->vertexCount && geom->pVertexBuffer == nullptr) throw std::runtime_error("no vertex buffer specified");
}
inline void verifyGeometryDesc(const ze_rtas_builder_quads_geometry_info_exp_t* geom)
{
if (geom->quadFormat != ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_QUAD_INDICES_UINT32)
throw std::runtime_error("quad format must be ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_QUAD_INDICES_UINT32");
if (geom->vertexFormat != ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3)
throw std::runtime_error("vertex format must be ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3");
if (geom->quadCount && geom->pQuadBuffer == nullptr) throw std::runtime_error("no quad buffer specified");
if (geom->vertexCount && geom->pVertexBuffer == nullptr) throw std::runtime_error("no vertex buffer specified");
}
inline void verifyGeometryDesc(const ze_rtas_builder_procedural_geometry_info_exp_t* geom)
{
if (geom->primCount && geom->pfnGetBoundsCb == nullptr) throw std::runtime_error("no bounds function specified");
}
inline void verifyGeometryDesc(const ze_rtas_builder_instance_geometry_info_exp_t* geom)
{
if (geom->pTransform == nullptr) throw std::runtime_error("no instance transformation specified");
if (geom->pBounds == nullptr) throw std::runtime_error("no acceleration structure bounds specified");
if (geom->pAccelerationStructure == nullptr) throw std::runtime_error("no acceleration structure to instanciate specified");
}
inline bool buildBounds(const ze_rtas_builder_triangles_geometry_info_exp_t* geom, uint32_t primID, BBox3fa& bbox, void* buildUserPtr)
{
if (primID >= geom->triangleCount) return false;
const ze_rtas_triangle_indices_uint32_exp_t tri = getPrimitive(geom,primID);
if (unlikely(tri.v0 >= geom->vertexCount)) return false;
if (unlikely(tri.v1 >= geom->vertexCount)) return false;
if (unlikely(tri.v2 >= geom->vertexCount)) return false;
const Vec3f p0 = getVertex(geom,tri.v0);
const Vec3f p1 = getVertex(geom,tri.v1);
const Vec3f p2 = getVertex(geom,tri.v2);
if (unlikely(!isvalid(p0))) return false;
if (unlikely(!isvalid(p1))) return false;
if (unlikely(!isvalid(p2))) return false;
bbox = BBox3fa(min(p0,p1,p2),max(p0,p1,p2));
return true;
}
inline bool buildBounds(const ze_rtas_builder_quads_geometry_info_exp_t* geom, uint32_t primID, BBox3fa& bbox, void* buildUserPtr)
{
if (primID >= geom->quadCount) return false;
const ze_rtas_quad_indices_uint32_exp_t tri = getPrimitive(geom,primID);
if (unlikely(tri.v0 >= geom->vertexCount)) return false;
if (unlikely(tri.v1 >= geom->vertexCount)) return false;
if (unlikely(tri.v2 >= geom->vertexCount)) return false;
if (unlikely(tri.v3 >= geom->vertexCount)) return false;
const Vec3f p0 = getVertex(geom,tri.v0);
const Vec3f p1 = getVertex(geom,tri.v1);
const Vec3f p2 = getVertex(geom,tri.v2);
const Vec3f p3 = getVertex(geom,tri.v3);
if (unlikely(!isvalid(p0))) return false;
if (unlikely(!isvalid(p1))) return false;
if (unlikely(!isvalid(p2))) return false;
if (unlikely(!isvalid(p3))) return false;
bbox = BBox3fa(min(p0,p1,p2,p3),max(p0,p1,p2,p3));
return true;
}
inline bool buildBounds(const ze_rtas_builder_procedural_geometry_info_exp_t* geom, uint32_t primID, BBox3fa& bbox, void* buildUserPtr)
{
if (primID >= geom->primCount) return false;
if (geom->pfnGetBoundsCb == nullptr) return false;
BBox3f bounds;
ze_rtas_geometry_aabbs_exp_cb_params_t params = { ZE_STRUCTURE_TYPE_RTAS_GEOMETRY_AABBS_EXP_CB_PARAMS };
params.primID = primID;
params.primIDCount = 1;
params.pGeomUserPtr = geom->pGeomUserPtr;
params.pBuildUserPtr = buildUserPtr;
params.pBoundsOut = (ze_rtas_aabb_exp_t*) &bounds;
(geom->pfnGetBoundsCb)(&params);
if (unlikely(!isvalid(bounds.lower))) return false;
if (unlikely(!isvalid(bounds.upper))) return false;
if (unlikely(bounds.empty())) return false;
bbox = (BBox3f&) bounds;
return true;
}
inline bool buildBounds(const ze_rtas_builder_instance_geometry_info_exp_t* geom, uint32_t primID, BBox3fa& bbox, void* buildUserPtr)
{
if (primID >= 1) return false;
if (geom->pAccelerationStructure == nullptr) return false;
if (geom->pTransform == nullptr) return false;
const AffineSpace3fa local2world = getTransform(geom);
const Vec3fa lower(geom->pBounds->lower.x,geom->pBounds->lower.y,geom->pBounds->lower.z);
const Vec3fa upper(geom->pBounds->upper.x,geom->pBounds->upper.y,geom->pBounds->upper.z);
const BBox3fa bounds = xfmBounds(local2world,BBox3fa(lower,upper));
if (unlikely(!isvalid(bounds.lower))) return false;
if (unlikely(!isvalid(bounds.upper))) return false;
if (unlikely(bounds.empty())) return false;
bbox = bounds;
return true;
}
template<typename GeometryType>
PrimInfo createGeometryPrimRefArray(const GeometryType* geom, void* buildUserPtr, evector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID)
{
PrimInfo pinfo(empty);
for (uint32_t primID=r.begin(); primID<r.end(); primID++)
{
BBox3fa bounds = empty;
if (!buildBounds(geom,primID,bounds,buildUserPtr)) continue;
const PrimRef prim(bounds,geomID,primID);
pinfo.add_center2(prim);
prims[k++] = prim;
}
return pinfo;
}
RTHWIF_API void zeRTASInitExp()
{
uint32_t numThreads = tbb::this_task_arena::max_concurrency();
g_arena.reset(new tbb::task_arena(numThreads,numThreads));
}
RTHWIF_API void zeRTASExitExp()
{
g_arena.reset();
}
typedef struct _zet_base_desc_t
{
/** [in] type of this structure */
ze_structure_type_t stype;
/** [in,out][optional] must be null or a pointer to an extension-specific structure */
const void* pNext;
} zet_base_desc_t_;
#define VALIDATE(arg) \
{\
ze_result_t result = validate(arg);\
if (result != ZE_RESULT_SUCCESS) return result; \
}
#define VALIDATE_PTR(arg) \
{ \
if ((arg) == nullptr) return ZE_RESULT_ERROR_INVALID_NULL_POINTER; \
} \
ze_result_t validate(ze_driver_handle_t hDriver)
{
if (hDriver == nullptr)
return ZE_RESULT_ERROR_INVALID_NULL_HANDLE;
return ZE_RESULT_SUCCESS;
}
ze_result_t validate(ze_device_handle_t hDevice)
{
if (hDevice == nullptr)
return ZE_RESULT_ERROR_INVALID_NULL_HANDLE;
return ZE_RESULT_SUCCESS;
}
bool checkDescChain(zet_base_desc_t_* desc)
{
/* supporting maximal 1024 to also detect cycles */
for (size_t i=0; i<1024; i++) {
if (desc->pNext == nullptr) return true;
desc = (zet_base_desc_t_*) desc->pNext;
}
return false;
}
struct ze_rtas_builder
{
ze_rtas_builder () {
}
~ze_rtas_builder() {
magick = 0x0;
}
bool verify() const {
return magick == MAGICK;
}
enum { MAGICK = 0x45FE67E1 };
uint32_t magick = MAGICK;
};
ze_result_t validate(ze_rtas_builder_exp_handle_t hBuilder)
{
if (hBuilder == nullptr)
return ZE_RESULT_ERROR_INVALID_NULL_HANDLE;
if (!((ze_rtas_builder*)hBuilder)->verify())
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
return ZE_RESULT_SUCCESS;
}
struct ze_rtas_parallel_operation_t
{
//ze_rtas_parallel_operation_t(ze_rtas_builder_exp_handle_t hBuilder)
//: hBuilder(hBuilder) {}
ze_rtas_parallel_operation_t() {
}
~ze_rtas_parallel_operation_t() {
magick = 0x0;
//hBuilder = nullptr;
}
bool verify() const {
//return (magick == MAGICK) && (validate(hBuilder) == ZE_RESULT_SUCCESS);
return (magick == MAGICK);
}
enum { MAGICK = 0xE84567E1 };
uint32_t magick = MAGICK;
//ze_rtas_builder_exp_handle_t hBuilder = nullptr;
ze_result_t errorCode = ZE_RESULT_SUCCESS;
tbb::task_group group;
};
ze_result_t validate(ze_rtas_parallel_operation_exp_handle_t hParallelOperation)
{
if (hParallelOperation == nullptr)
return ZE_RESULT_ERROR_INVALID_NULL_HANDLE;
if (!((ze_rtas_parallel_operation_t*)hParallelOperation)->verify())
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
return ZE_RESULT_SUCCESS;
}
ze_result_t validate(const ze_rtas_builder_exp_desc_t* pDescriptor)
{
if (pDescriptor == nullptr)
return ZE_RESULT_ERROR_INVALID_NULL_POINTER;
if (pDescriptor->stype != ZE_STRUCTURE_TYPE_RTAS_BUILDER_EXP_DESC)
return ZE_RESULT_ERROR_INVALID_ENUMERATION;
if (!checkDescChain((zet_base_desc_t_*)pDescriptor))
return ZE_RESULT_ERROR_INVALID_ENUMERATION;
if (uint32_t(ZE_RTAS_BUILDER_EXP_VERSION_CURRENT) < uint32_t(pDescriptor->builderVersion))
return ZE_RESULT_ERROR_INVALID_ENUMERATION;
return ZE_RESULT_SUCCESS;
}
ze_result_t validate(ze_rtas_device_exp_properties_t* pProperties)
{
if (pProperties == nullptr)
return ZE_RESULT_ERROR_INVALID_NULL_POINTER;
if (pProperties->stype != ZE_STRUCTURE_TYPE_RTAS_DEVICE_EXP_PROPERTIES)
return ZE_RESULT_ERROR_INVALID_ENUMERATION;
if (!checkDescChain((zet_base_desc_t_*)pProperties))
return ZE_RESULT_ERROR_INVALID_ENUMERATION;
return ZE_RESULT_SUCCESS;
}
ze_result_t validate(ze_rtas_format_exp_t rtasFormat)
{
if (uint32_t(rtasFormat) > uint32_t(ZE_RTAS_DEVICE_FORMAT_EXP_VERSION_MAX))
return ZE_RESULT_ERROR_INVALID_ENUMERATION;
return ZE_RESULT_SUCCESS;
}
ze_result_t validate(const ze_rtas_builder_build_op_exp_desc_t* args)
{
/* check for valid pointers */
if (args == nullptr)
return ZE_RESULT_ERROR_INVALID_NULL_POINTER;
/* check if input descriptor has proper type */
if (args->stype != ZE_STRUCTURE_TYPE_RTAS_BUILDER_BUILD_OP_EXP_DESC)
return ZE_RESULT_ERROR_INVALID_ENUMERATION;
/* check valid pNext chain */
if (!checkDescChain((zet_base_desc_t_*)args))
return ZE_RESULT_ERROR_INVALID_ENUMERATION;
/* check if acceleration structure format is supported */
VALIDATE(args->rtasFormat);
/* check for valid geometries array */
if (args->ppGeometries == nullptr && args->numGeometries > 0)
return ZE_RESULT_ERROR_INVALID_NULL_POINTER;
/* validate build quality */
if (args->buildQuality < 0 || ZE_RTAS_BUILDER_BUILD_QUALITY_HINT_EXP_HIGH < args->buildQuality)
return ZE_RESULT_ERROR_INVALID_ENUMERATION;
/* validate build flags */
if (args->buildFlags >= (ZE_RTAS_BUILDER_BUILD_OP_EXP_FLAG_NO_DUPLICATE_ANYHIT_INVOCATION<<1))
return ZE_RESULT_ERROR_INVALID_ENUMERATION;
return ZE_RESULT_SUCCESS;
}
ze_result_t validate(ze_rtas_builder_exp_properties_t* pProp)
{
/* check for valid pointers */
if (pProp == nullptr)
return ZE_RESULT_ERROR_INVALID_NULL_POINTER;
/* check if return property has proper type */
if (pProp->stype != ZE_STRUCTURE_TYPE_RTAS_BUILDER_EXP_PROPERTIES)
return ZE_RESULT_ERROR_INVALID_ENUMERATION;
/* check valid pNext chain */
if (!checkDescChain((zet_base_desc_t_*)pProp))
return ZE_RESULT_ERROR_INVALID_ENUMERATION;
return ZE_RESULT_SUCCESS;
}
ze_result_t validate(ze_rtas_parallel_operation_exp_properties_t* pProperties)
{
/* check for valid pointer */
if (pProperties == nullptr)
return ZE_RESULT_ERROR_INVALID_NULL_POINTER;
/* check for proper property */
if (pProperties->stype != ZE_STRUCTURE_TYPE_RTAS_PARALLEL_OPERATION_EXP_PROPERTIES)
return ZE_RESULT_ERROR_INVALID_ENUMERATION;
/* check valid pNext chain */
if (!checkDescChain((zet_base_desc_t_*)pProperties))
return ZE_RESULT_ERROR_INVALID_ENUMERATION;
return ZE_RESULT_SUCCESS;
}
RTHWIF_API ze_result_t zeRTASBuilderCreateExp(ze_driver_handle_t hDriver, const ze_rtas_builder_exp_desc_t *pDescriptor, ze_rtas_builder_exp_handle_t *phBuilder)
{
/* input validation */
VALIDATE(hDriver);
VALIDATE(pDescriptor);
VALIDATE_PTR(phBuilder);
*phBuilder = (ze_rtas_builder_exp_handle_t) new ze_rtas_builder();
return ZE_RESULT_SUCCESS;
}
RTHWIF_API ze_result_t zeRTASBuilderDestroyExp(ze_rtas_builder_exp_handle_t hBuilder)
{
VALIDATE(hBuilder);
delete (ze_rtas_builder*) hBuilder;
return ZE_RESULT_SUCCESS;
}
RTHWIF_API ze_result_t zeDeviceGetRTASPropertiesExp( const ze_device_handle_t hDevice, ze_rtas_device_exp_properties_t* pProperties )
{
/* input validation */
VALIDATE(hDevice);
VALIDATE(pProperties);
/* fill properties */
pProperties->flags = 0;
pProperties->rtasFormat = (ze_rtas_format_exp_t) ZE_RTAS_DEVICE_FORMAT_EXP_INVALID;
pProperties->rtasBufferAlignment = 128;
#if defined(EMBREE_LEVEL_ZERO)
/* check for supported device ID */
ze_device_properties_t device_props{ ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES };
ze_result_t status = zeDeviceGetProperties(hDevice, &device_props);
if (status != ZE_RESULT_SUCCESS)
return status;
/* check for Intel vendor */
const uint32_t vendor_id = device_props.vendorId;
const uint32_t device_id = device_props.deviceId;
if (vendor_id != 0x8086) return ZE_RESULT_ERROR_UNKNOWN;
bool dg2 =
(0x4F80 <= device_id && device_id <= 0x4F88) ||
(0x5690 <= device_id && device_id <= 0x5698) ||
(0x56A0 <= device_id && device_id <= 0x56A6) ||
(0x56B0 <= device_id && device_id <= 0x56B3) ||
(0x56C0 <= device_id && device_id <= 0x56C1);
bool pvc =
(0x0BD0 <= device_id && device_id <= 0x0BDB) ||
(device_id == 0x0BE5 );
if (dg2 || pvc) {
pProperties->rtasFormat = (ze_rtas_format_exp_t) ZE_RTAS_DEVICE_FORMAT_EXP_VERSION_1;
return ZE_RESULT_SUCCESS;
}
return ZE_RESULT_ERROR_UNKNOWN;
#else
pProperties->rtasFormat = (ze_rtas_format_exp_t) ZE_RTAS_DEVICE_FORMAT_EXP_VERSION_1;
return ZE_RESULT_SUCCESS;
#endif
}
RTHWIF_API ze_result_t zeRTASBuilderDeviceFormatCompatibilityCheckExp( ze_rtas_builder_exp_handle_t hBuilder,
const ze_rtas_format_exp_t accelFormat,
const ze_rtas_format_exp_t otherAccelFormat )
{
/* input validation */
VALIDATE(hBuilder);
VALIDATE(accelFormat);
VALIDATE(otherAccelFormat);
/* check if rtas formats are compatible */
if (accelFormat == otherAccelFormat)
return ZE_RESULT_SUCCESS;
/* report incompatible format */
return ZE_RESULT_EXP_ERROR_OPERANDS_INCOMPATIBLE;
}
uint32_t getNumPrimitives(const ze_rtas_builder_geometry_info_exp_t* geom)
{
switch (geom->geometryType) {
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_TRIANGLES : return ((ze_rtas_builder_triangles_geometry_info_exp_t*) geom)->triangleCount;
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL : return ((ze_rtas_builder_procedural_geometry_info_exp_t*) geom)->primCount;
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_QUADS : return ((ze_rtas_builder_quads_geometry_info_exp_t*) geom)->quadCount;
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_INSTANCE : return 1;
default : return 0;
};
}
RTHWIF_API ze_result_t zeRTASBuilderGetBuildPropertiesExp(ze_rtas_builder_exp_handle_t hBuilder,
const ze_rtas_builder_build_op_exp_desc_t* args,
ze_rtas_builder_exp_properties_t* pProp)
{
/* input validation */
VALIDATE(hBuilder);
VALIDATE(args);
VALIDATE(pProp);
const ze_rtas_builder_geometry_info_exp_t** geometries = args->ppGeometries;
const size_t numGeometries = args->numGeometries;
auto getSize = [&](uint32_t geomID) -> size_t {
const ze_rtas_builder_geometry_info_exp_t* geom = geometries[geomID];
if (geom == nullptr) return 0;
return getNumPrimitives(geom);
};
auto getType = [&](unsigned int geomID)
{
const ze_rtas_builder_geometry_info_exp_t* geom = geometries[geomID];
assert(geom);
switch (geom->geometryType) {
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_TRIANGLES : return QBVH6BuilderSAH::TRIANGLE;
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_QUADS: return QBVH6BuilderSAH::QUAD;
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL: return QBVH6BuilderSAH::PROCEDURAL;
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_INSTANCE: return QBVH6BuilderSAH::INSTANCE;
default: throw std::runtime_error("invalid geometry type");
};
};
/* query memory requirements from builder */
size_t expectedBytes = 0;
size_t worstCaseBytes = 0;
size_t scratchBytes = 0;
QBVH6BuilderSAH::estimateSize(numGeometries, getSize, getType, args->buildQuality, args->buildFlags, expectedBytes, worstCaseBytes, scratchBytes);
/* fill return struct */
pProp->flags = 0;
pProp->rtasBufferSizeBytesExpected = expectedBytes;
pProp->rtasBufferSizeBytesMaxRequired = worstCaseBytes;
pProp->scratchBufferSizeBytes = scratchBytes;
return ZE_RESULT_SUCCESS;
}
RTHWIF_API ze_result_t zeRTASBuilderBuildExpInternal(const ze_rtas_builder_build_op_exp_desc_t* args,
void *pScratchBuffer, size_t scratchBufferSizeBytes,
void *pRtasBuffer, size_t rtasBufferSizeBytes,
void *pBuildUserPtr, ze_rtas_aabb_exp_t *pBounds, size_t *pRtasBufferSizeBytes) try
{
const ze_rtas_builder_geometry_info_exp_t** geometries = args->ppGeometries;
const uint32_t numGeometries = args->numGeometries;
/* verify input descriptors */
parallel_for(numGeometries,[&](uint32_t geomID) {
const ze_rtas_builder_geometry_info_exp_t* geom = geometries[geomID];
if (geom == nullptr) return;
switch (geom->geometryType) {
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_TRIANGLES : verifyGeometryDesc((ze_rtas_builder_triangles_geometry_info_exp_t*)geom); break;
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_QUADS : verifyGeometryDesc((ze_rtas_builder_quads_geometry_info_exp_t* )geom); break;
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL : verifyGeometryDesc((ze_rtas_builder_procedural_geometry_info_exp_t*)geom); break;
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_INSTANCE : verifyGeometryDesc((ze_rtas_builder_instance_geometry_info_exp_t* )geom); break;
default: throw std::runtime_error("invalid geometry type");
};
});
auto getSize = [&](uint32_t geomID) -> size_t {
const ze_rtas_builder_geometry_info_exp_t* geom = geometries[geomID];
if (geom == nullptr) return 0;
return getNumPrimitives(geom);
};
auto getType = [&](unsigned int geomID)
{
const ze_rtas_builder_geometry_info_exp_t* geom = geometries[geomID];
assert(geom);
switch (geom->geometryType) {
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_TRIANGLES : return QBVH6BuilderSAH::TRIANGLE;
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_QUADS: return QBVH6BuilderSAH::QUAD;
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL: return QBVH6BuilderSAH::PROCEDURAL;
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_INSTANCE: return QBVH6BuilderSAH::INSTANCE;
default: throw std::runtime_error("invalid geometry type");
};
};
auto createPrimRefArray = [&] (evector<PrimRef>& prims, BBox1f time_range, const range<size_t>& r, size_t k, unsigned int geomID) -> PrimInfo
{
const ze_rtas_builder_geometry_info_exp_t* geom = geometries[geomID];
assert(geom);
switch (geom->geometryType) {
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_TRIANGLES : return createGeometryPrimRefArray((ze_rtas_builder_triangles_geometry_info_exp_t*)geom,pBuildUserPtr,prims,r,k,geomID);
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_QUADS : return createGeometryPrimRefArray((ze_rtas_builder_quads_geometry_info_exp_t* )geom,pBuildUserPtr,prims,r,k,geomID);
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL: return createGeometryPrimRefArray((ze_rtas_builder_procedural_geometry_info_exp_t*)geom,pBuildUserPtr,prims,r,k,geomID);
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_INSTANCE: return createGeometryPrimRefArray((ze_rtas_builder_instance_geometry_info_exp_t* )geom,pBuildUserPtr,prims,r,k,geomID);
default: throw std::runtime_error("invalid geometry type");
};
};
auto convertGeometryFlags = [&] (ze_rtas_builder_packed_geometry_exp_flags_t flags) -> GeometryFlags {
return (flags & ZE_RTAS_BUILDER_GEOMETRY_EXP_FLAG_NON_OPAQUE) ? GeometryFlags::NONE : GeometryFlags::OPAQUE;
};
auto getTriangle = [&](unsigned int geomID, unsigned int primID)
{
const ze_rtas_builder_triangles_geometry_info_exp_t* geom = (const ze_rtas_builder_triangles_geometry_info_exp_t*) geometries[geomID];
assert(geom);
const ze_rtas_triangle_indices_uint32_exp_t tri = getPrimitive(geom,primID);
if (unlikely(tri.v0 >= geom->vertexCount)) return QBVH6BuilderSAH::Triangle();
if (unlikely(tri.v1 >= geom->vertexCount)) return QBVH6BuilderSAH::Triangle();
if (unlikely(tri.v2 >= geom->vertexCount)) return QBVH6BuilderSAH::Triangle();
const Vec3f p0 = getVertex(geom,tri.v0);
const Vec3f p1 = getVertex(geom,tri.v1);
const Vec3f p2 = getVertex(geom,tri.v2);
if (unlikely(!isvalid(p0))) return QBVH6BuilderSAH::Triangle();
if (unlikely(!isvalid(p1))) return QBVH6BuilderSAH::Triangle();
if (unlikely(!isvalid(p2))) return QBVH6BuilderSAH::Triangle();
const GeometryFlags gflags = convertGeometryFlags(geom->geometryFlags);
return QBVH6BuilderSAH::Triangle(tri.v0,tri.v1,tri.v2,p0,p1,p2,gflags,geom->geometryMask);
};
auto getTriangleIndices = [&] (uint32_t geomID, uint32_t primID) {
const ze_rtas_builder_triangles_geometry_info_exp_t* geom = (const ze_rtas_builder_triangles_geometry_info_exp_t*) geometries[geomID];
assert(geom);
const ze_rtas_triangle_indices_uint32_exp_t tri = getPrimitive(geom,primID);
return Vec3<uint32_t>(tri.v0,tri.v1,tri.v2);
};
auto getQuad = [&](unsigned int geomID, unsigned int primID)
{
const ze_rtas_builder_quads_geometry_info_exp_t* geom = (const ze_rtas_builder_quads_geometry_info_exp_t*) geometries[geomID];
assert(geom);
const ze_rtas_quad_indices_uint32_exp_t quad = getPrimitive(geom,primID);
const Vec3f p0 = getVertex(geom,quad.v0);
const Vec3f p1 = getVertex(geom,quad.v1);
const Vec3f p2 = getVertex(geom,quad.v2);
const Vec3f p3 = getVertex(geom,quad.v3);
const GeometryFlags gflags = convertGeometryFlags(geom->geometryFlags);
return QBVH6BuilderSAH::Quad(p0,p1,p2,p3,gflags,geom->geometryMask);
};
auto getProcedural = [&](unsigned int geomID, unsigned int primID) {
const ze_rtas_builder_procedural_geometry_info_exp_t* geom = (const ze_rtas_builder_procedural_geometry_info_exp_t*) geometries[geomID];
assert(geom);
return QBVH6BuilderSAH::Procedural(geom->geometryMask); // FIXME: pass gflags
};
auto getInstance = [&](unsigned int geomID, unsigned int primID)
{
assert(geometries[geomID]);
assert(geometries[geomID]->geometryType == ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_INSTANCE);
const ze_rtas_builder_instance_geometry_info_exp_t* geom = (const ze_rtas_builder_instance_geometry_info_exp_t*) geometries[geomID];
void* accel = geom->pAccelerationStructure;
const AffineSpace3fa local2world = getTransform(geom);
return QBVH6BuilderSAH::Instance(local2world,accel,geom->geometryMask,geom->instanceUserID); // FIXME: pass instance flags
};
/* dispatch globals ptr for debugging purposes */
void* dispatchGlobalsPtr = nullptr;
#if defined(EMBREE_SYCL_ALLOC_DISPATCH_GLOBALS)
dispatchGlobalsPtr = args->dispatchGlobalsPtr;
#endif
bool verbose = false;
bool success = QBVH6BuilderSAH::build(numGeometries, nullptr,
getSize, getType,
createPrimRefArray, getTriangle, getTriangleIndices, getQuad, getProcedural, getInstance,
(char*)pRtasBuffer, rtasBufferSizeBytes,
pScratchBuffer, scratchBufferSizeBytes,
(BBox3f*) pBounds, pRtasBufferSizeBytes,
args->buildQuality, args->buildFlags, verbose, dispatchGlobalsPtr);
if (!success) {
return ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY;
}
return ZE_RESULT_SUCCESS;
}
catch (std::exception& e) {
std::cerr << "caught exception during BVH build: " << e.what() << std::endl;
return ZE_RESULT_ERROR_UNKNOWN;
}
RTHWIF_API ze_result_t zeRTASBuilderBuildExp(ze_rtas_builder_exp_handle_t hBuilder,
const ze_rtas_builder_build_op_exp_desc_t* args,
void *pScratchBuffer, size_t scratchBufferSizeBytes,
void *pRtasBuffer, size_t rtasBufferSizeBytes,
ze_rtas_parallel_operation_exp_handle_t hParallelOperation,
void *pBuildUserPtr, ze_rtas_aabb_exp_t *pBounds, size_t *pRtasBufferSizeBytes)
{
/* input validation */
VALIDATE(hBuilder);
VALIDATE(args);
VALIDATE_PTR(pScratchBuffer);
VALIDATE_PTR(pRtasBuffer);
/* if parallel operation is provided then execute using thread arena inside task group ... */
if (hParallelOperation)
{
VALIDATE(hParallelOperation);
ze_rtas_parallel_operation_t* op = (ze_rtas_parallel_operation_t*) hParallelOperation;
//if (op->hBuilder != hBuilder)
// return ZE_RESULT_ERROR_INVALID_ARGUMENT;
g_arena->execute([&](){ op->group.run([=](){
op->errorCode = zeRTASBuilderBuildExpInternal(args,
pScratchBuffer, scratchBufferSizeBytes,
pRtasBuffer, rtasBufferSizeBytes,
pBuildUserPtr, pBounds, pRtasBufferSizeBytes);
});
});
return ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE;
}
/* ... otherwise we just execute inside task arena to avoid spawning of TBB worker threads */
else
{
ze_result_t errorCode = ZE_RESULT_SUCCESS;
g_arena->execute([&](){ errorCode = zeRTASBuilderBuildExpInternal(args,
pScratchBuffer, scratchBufferSizeBytes,
pRtasBuffer, rtasBufferSizeBytes,
pBuildUserPtr, pBounds, pRtasBufferSizeBytes);
});
return errorCode;
}
}
RTHWIF_API ze_result_t zeRTASParallelOperationCreateExp(ze_driver_handle_t hDriver, ze_rtas_parallel_operation_exp_handle_t* phParallelOperation)
{
/* input validation */
VALIDATE(hDriver);
VALIDATE_PTR(phParallelOperation);
/* create parallel operation object */
*phParallelOperation = (ze_rtas_parallel_operation_exp_handle_t) new ze_rtas_parallel_operation_t();
return ZE_RESULT_SUCCESS;
}
RTHWIF_API ze_result_t zeRTASParallelOperationDestroyExp( ze_rtas_parallel_operation_exp_handle_t hParallelOperation )
{
/* input validation */
VALIDATE(hParallelOperation);
/* delete parallel operation */
delete (ze_rtas_parallel_operation_t*) hParallelOperation;
return ZE_RESULT_SUCCESS;
}
RTHWIF_API ze_result_t zeRTASParallelOperationGetPropertiesExp( ze_rtas_parallel_operation_exp_handle_t hParallelOperation, ze_rtas_parallel_operation_exp_properties_t* pProperties )
{
/* input validation */
VALIDATE(hParallelOperation);
VALIDATE(pProperties);
/* return properties */
pProperties->flags = 0;
pProperties->maxConcurrency = tbb::this_task_arena::max_concurrency();
return ZE_RESULT_SUCCESS;
}
RTHWIF_API ze_result_t zeRTASParallelOperationJoinExp( ze_rtas_parallel_operation_exp_handle_t hParallelOperation)
{
/* check for valid handle */
VALIDATE(hParallelOperation);
ze_rtas_parallel_operation_t* op = (ze_rtas_parallel_operation_t*) hParallelOperation;
g_arena->execute([&](){ op->group.wait(); });
return op->errorCode;
}
}
+83
View File
@@ -0,0 +1,83 @@
// Copyright 2009-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <stddef.h>
#include <stdint.h>
#if defined(__cplusplus)
# define RTHWIF_API_EXTERN_C extern "C"
#else
# define RTHWIF_API_EXTERN_C
#endif
#if defined(_WIN32)
#if defined(EMBREE_RTHWIF_STATIC_LIB)
# define RTHWIF_API_IMPORT RTHWIF_API_EXTERN_C
# define RTHWIF_API_EXPORT RTHWIF_API_EXTERN_C
#else
# define RTHWIF_API_IMPORT RTHWIF_API_EXTERN_C __declspec(dllimport)
# define RTHWIF_API_EXPORT RTHWIF_API_EXTERN_C __declspec(dllexport)
#endif
#else
# define RTHWIF_API_IMPORT RTHWIF_API_EXTERN_C
# define RTHWIF_API_EXPORT RTHWIF_API_EXTERN_C __attribute__ ((visibility ("default")))
#endif
#if defined(RTHWIF_EXPORT_API)
# define RTHWIF_API RTHWIF_API_EXPORT
#else
# define RTHWIF_API RTHWIF_API_IMPORT
#endif
#define ZE_APICALL_
#if defined(EMBREE_LEVEL_ZERO)
#include <level_zero/ze_api.h>
#else
typedef struct _ze_driver_handle_t *ze_driver_handle_t;
typedef struct _ze_device_handle_t *ze_device_handle_t;
typedef enum _ze_result_t
{
ZE_RESULT_SUCCESS = 0, ///< [Core] success
ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY = 0x70000002,///< [Core] insufficient host memory to satisfy call
ZE_RESULT_EXP_ERROR_OPERANDS_INCOMPATIBLE = 0x7ff00004, ///< [Core, Experimental] operands of comparison are not compatible
ZE_RESULT_ERROR_INVALID_ARGUMENT = 0x78000004, ///< [Validation] generic error code for invalid arguments
ZE_RESULT_ERROR_INVALID_NULL_HANDLE = 0x78000005, ///< [Validation] handle argument is not valid
ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE = 0x78000006, ///< [Validation] object pointed to by handle still in-use by device
ZE_RESULT_ERROR_INVALID_NULL_POINTER = 0x78000007, ///< [Validation] pointer argument may not be nullptr
ZE_RESULT_ERROR_INVALID_ENUMERATION = 0x7800000c, ///< [Validation] enumerator argument is not valid
ZE_RESULT_ERROR_UNKNOWN = 0x7ffffffe, ///< [Core] unknown or internal error
ZE_RESULT_FORCE_UINT32 = 0x7fffffff
} ze_result_t;
typedef enum _ze_structure_type_t {} ze_structure_type_t;
#ifndef ZE_MAKE_VERSION
# define ZE_MAKE_VERSION( _major, _minor ) (( _major << 16 )|( _minor & 0x0000ffff))
#endif // ZE_MAKE_VERSION
#ifndef ZE_BIT
# define ZE_BIT( _i ) ( 1 << _i )
#endif // ZE_BIT
#define ZE_APICALL
#endif
#if !defined(ZE_RTAS_BUILDER_EXP_NAME)
#undef ZE_APIEXPORT
#define ZE_APIEXPORT RTHWIF_API_EXPORT
#include "ze_rtas.h"
#endif
RTHWIF_API ze_result_t ZE_APICALL_ zeDeviceGetRTASPropertiesExp( const ze_device_handle_t hDevice, ze_rtas_device_exp_properties_t* pRtasProp );
/*
* Initializes the library.
*/
RTHWIF_API void zeRTASInitExp();
/*
* Cleans up the library.
*/
RTHWIF_API void zeRTASExitExp();
-507
View File
@@ -1,507 +0,0 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#define RTHWIF_EXPORT_API
#include "../../../common/tasking/taskscheduler.h"
#include "rthwif_builder.h"
#include "qbvh6_builder_sah.h"
#if defined(EMBREE_LEVEL_ZERO)
#include <level_zero/ze_api.h>
#endif
namespace embree
{
using namespace embree::isa;
static std::unique_ptr<tbb::task_arena> g_arena;
inline RTHWIF_TRIANGLE_INDICES getPrimitive(const RTHWIF_GEOMETRY_TRIANGLES_DESC* geom, uint32_t primID) {
assert(primID < geom->triangleCount);
return *(RTHWIF_TRIANGLE_INDICES*)((char*)geom->triangleBuffer + uint64_t(primID)*geom->triangleStride);
}
inline Vec3f getVertex(const RTHWIF_GEOMETRY_TRIANGLES_DESC* geom, uint32_t vertexID) {
assert(vertexID < geom->vertexCount);
return *(Vec3f*)((char*)geom->vertexBuffer + uint64_t(vertexID)*geom->vertexStride);
}
inline RTHWIF_QUAD_INDICES getPrimitive(const RTHWIF_GEOMETRY_QUADS_DESC* geom, uint32_t primID) {
assert(primID < geom->quadCount);
return *(RTHWIF_QUAD_INDICES*)((char*)geom->quadBuffer + uint64_t(primID)*geom->quadStride);
}
inline Vec3f getVertex(const RTHWIF_GEOMETRY_QUADS_DESC* geom, uint32_t vertexID) {
assert(vertexID < geom->vertexCount);
return *(Vec3f*)((char*)geom->vertexBuffer + uint64_t(vertexID)*geom->vertexStride);
}
inline AffineSpace3fa getTransform(const RTHWIF_GEOMETRY_INSTANCE_DESC* geom)
{
switch (geom->transformFormat)
{
case RTHWIF_TRANSFORM_FORMAT_FLOAT3X4_COLUMN_MAJOR: {
const RTHWIF_TRANSFORM_FLOAT3X4_COLUMN_MAJOR* xfm = (const RTHWIF_TRANSFORM_FLOAT3X4_COLUMN_MAJOR*) geom->transform;
return {
{ xfm->vx_x, xfm->vx_y, xfm->vx_z },
{ xfm->vy_x, xfm->vy_y, xfm->vy_z },
{ xfm->vz_x, xfm->vz_y, xfm->vz_z },
{ xfm-> p_x, xfm-> p_y, xfm-> p_z }
};
}
case RTHWIF_TRANSFORM_FORMAT_FLOAT4X4_COLUMN_MAJOR: {
const RTHWIF_TRANSFORM_FLOAT4X4_COLUMN_MAJOR* xfm = (const RTHWIF_TRANSFORM_FLOAT4X4_COLUMN_MAJOR*) geom->transform;
return {
{ xfm->vx_x, xfm->vx_y, xfm->vx_z },
{ xfm->vy_x, xfm->vy_y, xfm->vy_z },
{ xfm->vz_x, xfm->vz_y, xfm->vz_z },
{ xfm-> p_x, xfm-> p_y, xfm-> p_z }
};
}
case RTHWIF_TRANSFORM_FORMAT_FLOAT3X4_ROW_MAJOR: {
const RTHWIF_TRANSFORM_FLOAT3X4_ROW_MAJOR* xfm = (const RTHWIF_TRANSFORM_FLOAT3X4_ROW_MAJOR*) geom->transform;
return {
{ xfm->vx_x, xfm->vx_y, xfm->vx_z },
{ xfm->vy_x, xfm->vy_y, xfm->vy_z },
{ xfm->vz_x, xfm->vz_y, xfm->vz_z },
{ xfm-> p_x, xfm-> p_y, xfm-> p_z }
};
}
default:
throw std::runtime_error("invalid transform format");
}
}
inline void verifyGeometryDesc(const RTHWIF_GEOMETRY_TRIANGLES_DESC* geom)
{
if (geom->reserved0 != 0) throw std::runtime_error("reserved member must be 0");
if (geom->reserved1 != 0) throw std::runtime_error("reserved member must be 0");
if (geom->triangleCount && geom->triangleBuffer == nullptr) throw std::runtime_error("no triangle buffer specified");
if (geom->vertexCount && geom->vertexBuffer == nullptr) throw std::runtime_error("no vertex buffer specified");
}
inline void verifyGeometryDesc(const RTHWIF_GEOMETRY_QUADS_DESC* geom)
{
if (geom->reserved0 != 0) throw std::runtime_error("reserved member must be 0");
if (geom->reserved1 != 0) throw std::runtime_error("reserved member must be 0");
if (geom->quadCount && geom->quadBuffer == nullptr) throw std::runtime_error("no quad buffer specified");
if (geom->vertexCount && geom->vertexBuffer == nullptr) throw std::runtime_error("no vertex buffer specified");
}
inline void verifyGeometryDesc(const RTHWIF_GEOMETRY_AABBS_FPTR_DESC* geom)
{
if (geom->reserved != 0) throw std::runtime_error("reserved member must be 0");
if (geom->primCount && geom->getBounds == nullptr) throw std::runtime_error("no bounds function specified");
}
inline void verifyGeometryDesc(const RTHWIF_GEOMETRY_INSTANCE_DESC* geom)
{
if (geom->transform == nullptr) throw std::runtime_error("no instance transformation specified");
if (geom->bounds == nullptr) throw std::runtime_error("no acceleration structure bounds specified");
if (geom->accel == nullptr) throw std::runtime_error("no acceleration structure to instanciate specified");
}
inline bool buildBounds(const RTHWIF_GEOMETRY_TRIANGLES_DESC* geom, uint32_t primID, BBox3fa& bbox, void* buildUserPtr)
{
if (primID >= geom->triangleCount) return false;
const RTHWIF_TRIANGLE_INDICES tri = getPrimitive(geom,primID);
if (unlikely(tri.v0 >= geom->vertexCount)) return false;
if (unlikely(tri.v1 >= geom->vertexCount)) return false;
if (unlikely(tri.v2 >= geom->vertexCount)) return false;
const Vec3f p0 = getVertex(geom,tri.v0);
const Vec3f p1 = getVertex(geom,tri.v1);
const Vec3f p2 = getVertex(geom,tri.v2);
if (unlikely(!isvalid(p0))) return false;
if (unlikely(!isvalid(p1))) return false;
if (unlikely(!isvalid(p2))) return false;
bbox = BBox3fa(min(p0,p1,p2),max(p0,p1,p2));
return true;
}
inline bool buildBounds(const RTHWIF_GEOMETRY_QUADS_DESC* geom, uint32_t primID, BBox3fa& bbox, void* buildUserPtr)
{
if (primID >= geom->quadCount) return false;
const RTHWIF_QUAD_INDICES tri = getPrimitive(geom,primID);
if (unlikely(tri.v0 >= geom->vertexCount)) return false;
if (unlikely(tri.v1 >= geom->vertexCount)) return false;
if (unlikely(tri.v2 >= geom->vertexCount)) return false;
if (unlikely(tri.v3 >= geom->vertexCount)) return false;
const Vec3f p0 = getVertex(geom,tri.v0);
const Vec3f p1 = getVertex(geom,tri.v1);
const Vec3f p2 = getVertex(geom,tri.v2);
const Vec3f p3 = getVertex(geom,tri.v3);
if (unlikely(!isvalid(p0))) return false;
if (unlikely(!isvalid(p1))) return false;
if (unlikely(!isvalid(p2))) return false;
if (unlikely(!isvalid(p3))) return false;
bbox = BBox3fa(min(p0,p1,p2,p3),max(p0,p1,p2,p3));
return true;
}
inline bool buildBounds(const RTHWIF_GEOMETRY_AABBS_FPTR_DESC* geom, uint32_t primID, BBox3fa& bbox, void* buildUserPtr)
{
if (primID >= geom->primCount) return false;
if (geom->getBounds == nullptr) return false;
BBox3f bounds;
(geom->getBounds)(primID,1,geom->geomUserPtr,buildUserPtr,(RTHWIF_AABB*)&bounds);
if (unlikely(!isvalid(bounds.lower))) return false;
if (unlikely(!isvalid(bounds.upper))) return false;
if (unlikely(bounds.empty())) return false;
bbox = (BBox3f&) bounds;
return true;
}
inline bool buildBounds(const RTHWIF_GEOMETRY_INSTANCE_DESC* geom, uint32_t primID, BBox3fa& bbox, void* buildUserPtr)
{
if (primID >= 1) return false;
if (geom->accel == nullptr) return false;
if (geom->transform == nullptr) return false;
const AffineSpace3fa local2world = getTransform(geom);
const Vec3fa lower(geom->bounds->lower.x,geom->bounds->lower.y,geom->bounds->lower.z);
const Vec3fa upper(geom->bounds->upper.x,geom->bounds->upper.y,geom->bounds->upper.z);
const BBox3fa bounds = xfmBounds(local2world,BBox3fa(lower,upper));
if (unlikely(!isvalid(bounds.lower))) return false;
if (unlikely(!isvalid(bounds.upper))) return false;
if (unlikely(bounds.empty())) return false;
bbox = bounds;
return true;
}
template<typename GeometryType>
PrimInfo createGeometryPrimRefArray(const GeometryType* geom, void* buildUserPtr, evector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID)
{
PrimInfo pinfo(empty);
for (uint32_t primID=r.begin(); primID<r.end(); primID++)
{
BBox3fa bounds = empty;
if (!buildBounds(geom,primID,bounds,buildUserPtr)) continue;
const PrimRef prim(bounds,geomID,primID);
pinfo.add_center2(prim);
prims[k++] = prim;
}
return pinfo;
}
RTHWIF_API void rthwifInit()
{
uint32_t numThreads = tbb::this_task_arena::max_concurrency();
g_arena.reset(new tbb::task_arena(numThreads,numThreads));
}
RTHWIF_API void rthwifExit()
{
g_arena.reset();
}
#if defined(EMBREE_LEVEL_ZERO)
RTHWIF_API RTHWIF_FEATURES rthwifGetSupportedFeatures(ze_device_handle_t hDevice)
{
/* check for supported device ID */
ze_device_properties_t device_props{ ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES };
ze_result_t status = zeDeviceGetProperties(hDevice, &device_props);
if (status != ZE_RESULT_SUCCESS)
return RTHWIF_FEATURES_NONE;
/* check for Intel vendor */
const uint32_t vendor_id = device_props.vendorId;
const uint32_t device_id = device_props.deviceId;
if (vendor_id != 0x8086) return RTHWIF_FEATURES_NONE;
/* return supported features */
uint32_t features_xe = RTHWIF_FEATURES_NONE;
features_xe |= RTHWIF_FEATURES_GEOMETRY_TYPE_TRIANGLES;
features_xe |= RTHWIF_FEATURES_GEOMETRY_TYPE_QUADS;
features_xe |= RTHWIF_FEATURES_GEOMETRY_TYPE_AABBS_FPTR;
features_xe |= RTHWIF_FEATURES_GEOMETRY_TYPE_INSTANCE;
// DG2
if (0x4F80 <= device_id && device_id <= 0x4F88) return (RTHWIF_FEATURES) features_xe;
if (0x5690 <= device_id && device_id <= 0x5698) return (RTHWIF_FEATURES) features_xe;
if (0x56A0 <= device_id && device_id <= 0x56A6) return (RTHWIF_FEATURES) features_xe;
if (0x56B0 <= device_id && device_id <= 0x56B3) return (RTHWIF_FEATURES) features_xe;
if (0x56C0 <= device_id && device_id <= 0x56C1) return (RTHWIF_FEATURES) features_xe;
// PVC
if (0x0BD0 <= device_id && device_id <= 0x0BDB) return (RTHWIF_FEATURES) features_xe;
if (device_id == 0x0BE5 ) return (RTHWIF_FEATURES) features_xe;
return RTHWIF_FEATURES_NONE;
}
#else
RTHWIF_API RTHWIF_FEATURES rthwifGetSupportedFeatures(ze_device_handle_t hDevice)
{
uint32_t features_xe = RTHWIF_FEATURES_NONE;
features_xe |= RTHWIF_FEATURES_GEOMETRY_TYPE_TRIANGLES;
features_xe |= RTHWIF_FEATURES_GEOMETRY_TYPE_QUADS;
features_xe |= RTHWIF_FEATURES_GEOMETRY_TYPE_AABBS_FPTR;
features_xe |= RTHWIF_FEATURES_GEOMETRY_TYPE_INSTANCE;
return RTHWIF_FEATURES(features_xe);
}
#endif
uint32_t getNumPrimitives(const RTHWIF_GEOMETRY_DESC* geom)
{
switch (geom->geometryType) {
case RTHWIF_GEOMETRY_TYPE_TRIANGLES : return ((RTHWIF_GEOMETRY_TRIANGLES_DESC*) geom)->triangleCount;
case RTHWIF_GEOMETRY_TYPE_AABBS_FPTR : return ((RTHWIF_GEOMETRY_AABBS_FPTR_DESC*) geom)->primCount;
case RTHWIF_GEOMETRY_TYPE_QUADS : return ((RTHWIF_GEOMETRY_QUADS_DESC*) geom)->quadCount;
case RTHWIF_GEOMETRY_TYPE_INSTANCE : return 1;
default : return 0;
};
}
/* fill all arg members that app did not know of yet */
RTHWIF_BUILD_ACCEL_ARGS rthwifPrepareBuildAccelArgs(const RTHWIF_BUILD_ACCEL_ARGS& args_i)
{
RTHWIF_BUILD_ACCEL_ARGS args;
memset(&args,0,sizeof(RTHWIF_BUILD_ACCEL_ARGS));
memcpy(&args,&args_i,std::min(sizeof(RTHWIF_BUILD_ACCEL_ARGS),args_i.structBytes));
args.structBytes = sizeof(RTHWIF_BUILD_ACCEL_ARGS);
return args;
}
RTHWIF_API RTHWIF_ERROR rthwifGetAccelSize(const RTHWIF_BUILD_ACCEL_ARGS& args_i, RTHWIF_ACCEL_SIZE& size_o)
{
RTHWIF_BUILD_ACCEL_ARGS args = rthwifPrepareBuildAccelArgs(args_i);
const RTHWIF_GEOMETRY_DESC** geometries = args.geometries;
const size_t numGeometries = args.numGeometries;
auto getSize = [&](uint32_t geomID) -> size_t {
const RTHWIF_GEOMETRY_DESC* geom = geometries[geomID];
if (geom == nullptr) return 0;
return getNumPrimitives(geom);
};
auto getType = [&](unsigned int geomID)
{
const RTHWIF_GEOMETRY_DESC* geom = geometries[geomID];
assert(geom);
switch (geom->geometryType) {
case RTHWIF_GEOMETRY_TYPE_TRIANGLES : return QBVH6BuilderSAH::TRIANGLE;
case RTHWIF_GEOMETRY_TYPE_QUADS: return QBVH6BuilderSAH::QUAD;
case RTHWIF_GEOMETRY_TYPE_AABBS_FPTR: return QBVH6BuilderSAH::PROCEDURAL;
case RTHWIF_GEOMETRY_TYPE_INSTANCE: return QBVH6BuilderSAH::INSTANCE;
default: throw std::runtime_error("invalid geometry type");
};
};
/* query memory requirements from builder */
size_t expectedBytes = 0;
size_t worstCaseBytes = 0;
size_t scratchBytes = 0;
QBVH6BuilderSAH::estimateSize(numGeometries, getSize, getType, args.quality, expectedBytes, worstCaseBytes, scratchBytes);
/* return size to user */
RTHWIF_ACCEL_SIZE size;
memset(&size,0,sizeof(RTHWIF_ACCEL_SIZE));
size.accelBufferExpectedBytes = expectedBytes;
size.accelBufferWorstCaseBytes = worstCaseBytes;
size.scratchBufferBytes = scratchBytes;
size_t bytes_o = size_o.structBytes;
memset(&size_o,0,bytes_o);
memcpy(&size_o,&size,bytes_o);
size_o.structBytes = bytes_o;
return RTHWIF_ERROR_NONE;
}
RTHWIF_API RTHWIF_ERROR rthwifBuildAccelInternal(const RTHWIF_BUILD_ACCEL_ARGS& args_i) try
{
/* prepare input arguments */
const RTHWIF_BUILD_ACCEL_ARGS args = rthwifPrepareBuildAccelArgs(args_i);
const RTHWIF_GEOMETRY_DESC** geometries = args.geometries;
const uint32_t numGeometries = args.numGeometries;
if (args.accelBuffer == nullptr) return RTHWIF_ERROR_OTHER;
/* verify input descriptors */
parallel_for(numGeometries,[&](uint32_t geomID) {
const RTHWIF_GEOMETRY_DESC* geom = geometries[geomID];
if (geom == nullptr) return;
switch (geom->geometryType) {
case RTHWIF_GEOMETRY_TYPE_TRIANGLES : verifyGeometryDesc((RTHWIF_GEOMETRY_TRIANGLES_DESC*)geom); break;
case RTHWIF_GEOMETRY_TYPE_QUADS : verifyGeometryDesc((RTHWIF_GEOMETRY_QUADS_DESC* )geom); break;
case RTHWIF_GEOMETRY_TYPE_AABBS_FPTR : verifyGeometryDesc((RTHWIF_GEOMETRY_AABBS_FPTR_DESC*)geom); break;
case RTHWIF_GEOMETRY_TYPE_INSTANCE : verifyGeometryDesc((RTHWIF_GEOMETRY_INSTANCE_DESC* )geom); break;
default: throw std::runtime_error("invalid geometry type");
};
});
auto getSize = [&](uint32_t geomID) -> size_t {
const RTHWIF_GEOMETRY_DESC* geom = geometries[geomID];
if (geom == nullptr) return 0;
return getNumPrimitives(geom);
};
auto getType = [&](unsigned int geomID)
{
const RTHWIF_GEOMETRY_DESC* geom = geometries[geomID];
assert(geom);
switch (geom->geometryType) {
case RTHWIF_GEOMETRY_TYPE_TRIANGLES : return QBVH6BuilderSAH::TRIANGLE;
case RTHWIF_GEOMETRY_TYPE_QUADS: return QBVH6BuilderSAH::QUAD;
case RTHWIF_GEOMETRY_TYPE_AABBS_FPTR: return QBVH6BuilderSAH::PROCEDURAL;
case RTHWIF_GEOMETRY_TYPE_INSTANCE: return QBVH6BuilderSAH::INSTANCE;
default: throw std::runtime_error("invalid geometry type");
};
};
auto createPrimRefArray = [&] (evector<PrimRef>& prims, BBox1f time_range, const range<size_t>& r, size_t k, unsigned int geomID) -> PrimInfo
{
const RTHWIF_GEOMETRY_DESC* geom = geometries[geomID];
assert(geom);
switch (geom->geometryType) {
case RTHWIF_GEOMETRY_TYPE_TRIANGLES : return createGeometryPrimRefArray((RTHWIF_GEOMETRY_TRIANGLES_DESC*)geom,args.buildUserPtr,prims,r,k,geomID);
case RTHWIF_GEOMETRY_TYPE_QUADS : return createGeometryPrimRefArray((RTHWIF_GEOMETRY_QUADS_DESC* )geom,args.buildUserPtr,prims,r,k,geomID);
case RTHWIF_GEOMETRY_TYPE_AABBS_FPTR: return createGeometryPrimRefArray((RTHWIF_GEOMETRY_AABBS_FPTR_DESC*)geom,args.buildUserPtr,prims,r,k,geomID);
case RTHWIF_GEOMETRY_TYPE_INSTANCE: return createGeometryPrimRefArray((RTHWIF_GEOMETRY_INSTANCE_DESC* )geom,args.buildUserPtr,prims,r,k,geomID);
default: throw std::runtime_error("invalid geometry type");
};
};
auto getTriangle = [&](unsigned int geomID, unsigned int primID)
{
const RTHWIF_GEOMETRY_TRIANGLES_DESC* geom = (const RTHWIF_GEOMETRY_TRIANGLES_DESC*) geometries[geomID];
assert(geom);
const RTHWIF_TRIANGLE_INDICES tri = getPrimitive(geom,primID);
if (unlikely(tri.v0 >= geom->vertexCount)) return QBVH6BuilderSAH::Triangle();
if (unlikely(tri.v1 >= geom->vertexCount)) return QBVH6BuilderSAH::Triangle();
if (unlikely(tri.v2 >= geom->vertexCount)) return QBVH6BuilderSAH::Triangle();
const Vec3f p0 = getVertex(geom,tri.v0);
const Vec3f p1 = getVertex(geom,tri.v1);
const Vec3f p2 = getVertex(geom,tri.v2);
if (unlikely(!isvalid(p0))) return QBVH6BuilderSAH::Triangle();
if (unlikely(!isvalid(p1))) return QBVH6BuilderSAH::Triangle();
if (unlikely(!isvalid(p2))) return QBVH6BuilderSAH::Triangle();
const GeometryFlags gflags = (GeometryFlags) geom->geometryFlags;
return QBVH6BuilderSAH::Triangle(tri.v0,tri.v1,tri.v2,p0,p1,p2,gflags,geom->geometryMask);
};
auto getTriangleIndices = [&] (uint32_t geomID, uint32_t primID) {
const RTHWIF_GEOMETRY_TRIANGLES_DESC* geom = (const RTHWIF_GEOMETRY_TRIANGLES_DESC*) geometries[geomID];
assert(geom);
const RTHWIF_TRIANGLE_INDICES tri = getPrimitive(geom,primID);
return Vec3<uint32_t>(tri.v0,tri.v1,tri.v2);
};
auto getQuad = [&](unsigned int geomID, unsigned int primID)
{
const RTHWIF_GEOMETRY_QUADS_DESC* geom = (const RTHWIF_GEOMETRY_QUADS_DESC*) geometries[geomID];
assert(geom);
const RTHWIF_QUAD_INDICES quad = getPrimitive(geom,primID);
const Vec3f p0 = getVertex(geom,quad.v0);
const Vec3f p1 = getVertex(geom,quad.v1);
const Vec3f p2 = getVertex(geom,quad.v2);
const Vec3f p3 = getVertex(geom,quad.v3);
const GeometryFlags gflags = (GeometryFlags) geom->geometryFlags;
return QBVH6BuilderSAH::Quad(p0,p1,p2,p3,gflags,geom->geometryMask);
};
auto getProcedural = [&](unsigned int geomID, unsigned int primID) {
const RTHWIF_GEOMETRY_AABBS_FPTR_DESC* geom = (const RTHWIF_GEOMETRY_AABBS_FPTR_DESC*) geometries[geomID];
assert(geom);
return QBVH6BuilderSAH::Procedural(geom->geometryMask); // FIXME: pass gflags
};
auto getInstance = [&](unsigned int geomID, unsigned int primID)
{
assert(geometries[geomID]);
assert(geometries[geomID]->geometryType == RTHWIF_GEOMETRY_TYPE_INSTANCE);
const RTHWIF_GEOMETRY_INSTANCE_DESC* geom = (const RTHWIF_GEOMETRY_INSTANCE_DESC*) geometries[geomID];
void* accel = geom->accel;
const AffineSpace3fa local2world = getTransform(geom);
return QBVH6BuilderSAH::Instance(local2world,accel,geom->geometryMask,geom->instanceUserID); // FIXME: pass instance flags
};
/* dispatch globals ptr for debugging purposes */
void* dispatchGlobalsPtr = nullptr;
#if defined(EMBREE_SYCL_ALLOC_DISPATCH_GLOBALS)
dispatchGlobalsPtr = args.dispatchGlobalsPtr;
#endif
bool verbose = false;
QBVH6BuilderSAH::build(numGeometries, nullptr,
getSize, getType,
createPrimRefArray, getTriangle, getTriangleIndices, getQuad, getProcedural, getInstance,
(char*)args.accelBuffer, args.accelBufferBytes,
args.scratchBuffer, args.scratchBufferBytes,
(BBox3f*) args.boundsOut, args.accelBufferBytesOut,
args.quality, verbose, dispatchGlobalsPtr);
return RTHWIF_ERROR_NONE;
}
catch (std::exception& e) {
if (std::string(e.what()) == std::string(std::bad_alloc().what())) {
return RTHWIF_ERROR_RETRY;
}
else {
return RTHWIF_ERROR_OTHER;
}
}
struct RTHWIF_PARALLEL_OPERATION_IMPL
{
RTHWIF_ERROR errorCode = RTHWIF_ERROR_NONE;
tbb::task_group group;
};
RTHWIF_API RTHWIF_ERROR rthwifBuildAccel(const RTHWIF_BUILD_ACCEL_ARGS& args_i)
{
/* if parallel operation is provided then execute using thread arena inside task group ... */
if (args_i.parallelOperation)
{
RTHWIF_PARALLEL_OPERATION_IMPL* op = (RTHWIF_PARALLEL_OPERATION_IMPL*) args_i.parallelOperation;
g_arena->execute([&](){ op->group.run([=](){ op->errorCode = rthwifBuildAccelInternal(args_i); }); });
return RTHWIF_ERROR_PARALLEL_OPERATION;
}
/* ... otherwise we just execute inside task arena to avoid spawning of TBB worker threads */
else
{
RTHWIF_ERROR errorCode = RTHWIF_ERROR_NONE;
g_arena->execute([&](){ errorCode = rthwifBuildAccelInternal(args_i); });
return errorCode;
}
}
RTHWIF_API RTHWIF_PARALLEL_OPERATION rthwifNewParallelOperation()
{
return (RTHWIF_PARALLEL_OPERATION) new RTHWIF_PARALLEL_OPERATION_IMPL;
}
RTHWIF_API void rthwifDeleteParallelOperation( RTHWIF_PARALLEL_OPERATION parallelOperation )
{
delete (RTHWIF_PARALLEL_OPERATION_IMPL*) parallelOperation;
}
RTHWIF_API uint32_t rthwifGetParallelOperationMaxConcurrency( RTHWIF_PARALLEL_OPERATION parallelOperation )
{
return tbb::this_task_arena::max_concurrency();
}
RTHWIF_API RTHWIF_ERROR rthwifJoinParallelOperation( RTHWIF_PARALLEL_OPERATION parallelOperation)
{
RTHWIF_PARALLEL_OPERATION_IMPL* op = (RTHWIF_PARALLEL_OPERATION_IMPL*) parallelOperation;
g_arena->execute([&](){ op->group.wait(); });
return op->errorCode;
}
}
-474
View File
@@ -1,474 +0,0 @@
// Copyright 2009-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#if !defined(EMBREE_LEVEL_ZERO)
struct _ze_device_handle_t {};
#else
struct _ze_device_handle_t;
#endif
typedef struct _ze_device_handle_t *ze_device_handle_t;
#if defined(__cplusplus)
# define RTHWIF_API_EXTERN_C extern "C"
#else
# define RTHWIF_API_EXTERN_C
#endif
#if defined(_WIN32)
#if defined(EMBREE_RTHWIF_STATIC_LIB)
# define RTHWIF_API_IMPORT RTHWIF_API_EXTERN_C
# define RTHWIF_API_EXPORT RTHWIF_API_EXTERN_C
#else
# define RTHWIF_API_IMPORT RTHWIF_API_EXTERN_C __declspec(dllimport)
# define RTHWIF_API_EXPORT RTHWIF_API_EXTERN_C __declspec(dllexport)
#endif
#else
# define RTHWIF_API_IMPORT RTHWIF_API_EXTERN_C
# define RTHWIF_API_EXPORT RTHWIF_API_EXTERN_C __attribute__ ((visibility ("default")))
#endif
#if defined(RTHWIF_EXPORT_API)
# define RTHWIF_API RTHWIF_API_EXPORT
#else
# define RTHWIF_API RTHWIF_API_IMPORT
#endif
/* Required alignment of acceleration structure buffers. */
#define RTHWIF_ACCELERATION_STRUCTURE_ALIGNMENT 128
/* Geometry flags supported (identical to DXR spec). */
typedef enum RTHWIF_GEOMETRY_FLAGS : uint8_t
{
RTHWIF_GEOMETRY_FLAG_NONE = 0,
RTHWIF_GEOMETRY_FLAG_OPAQUE = 0x1, // Opaque geometries do not invoke an anyhit shader
RTHWIF_GEOMETRY_FLAG_NO_DUPLICATE_ANYHIT_INVOCATION = 0x2 // Guarantees single anyhit shader invokation for primitives.
} RTHWIF_GEOMETRY_FLAGS;
/* A 3-component short vector type. */
typedef struct RTHWIF_FLOAT3 {
float x, y, z;
} RTHWIF_FLOAT3;
/* A 3x4 affine transformation with column vectors vx, vy, vz, and p
* transforming a point (x,y,z) to x*vx + y*vy + z*vz + p. */
typedef struct RTHWIF_TRANSFORM_FLOAT3X4_COLUMN_MAJOR {
float vx_x, vx_y, vx_z; // column 0
float vy_x, vy_y, vy_z; // column 1
float vz_x, vz_y, vz_z; // column 2
float p_x, p_y, p_z; // column 3
} RTHWIF_TRANSFORM_FLOAT3X4_COLUMN_MAJOR;
/* Same as RTHWIF_TRANSFORM_FLOAT3X4_COLUMN_MAJOR, with ignored 4th
* component of column vectors. */
typedef struct RTHWIF_TRANSFORM_FLOAT4X4_COLUMN_MAJOR {
float vx_x, vx_y, vx_z, pad0; // column 0
float vy_x, vy_y, vy_z, pad1; // column 1
float vz_x, vz_y, vz_z, pad2; // column 2
float p_x, p_y, p_z, pad3; // column 3
} RTHWIF_TRANSFORM_FLOAT4X4_COLUMN_MAJOR;
/* Same as RTHWIF_TRANSFORM_FLOAT3X4_COLUMN_MAJOR, but using row major
* layout. */
typedef struct RTHWIF_TRANSFORM_FLOAT3X4_ROW_MAJOR {
float vx_x, vy_x, vz_x, p_x; // row 0
float vx_y, vy_y, vz_y, p_y; // row 1
float vx_z, vy_z, vz_z, p_z; // row 2
} RTHWIF_TRANSFORM_FLOAT3X4_ROW_MAJOR;
/* An axis aligned bounding box with lower and upper bounds in each
* dimension. */
typedef struct RTHWIF_AABB
{
RTHWIF_FLOAT3 lower; // lower bounds
RTHWIF_FLOAT3 upper; // upper bounds
} RTHWIF_AABB;
/* A triangle represented using 3 vertex indices. */
typedef struct RTHWIF_TRIANGLE_INDICES {
uint32_t v0, v1, v2; // 3 triangle indices pointing into vertex array
} RTHWIF_TRIANGLE_INDICES;
/* A quad (triangle pair) represented using 4 vertex indices. */
typedef struct RTHWIF_QUAD_INDICES {
uint32_t v0, v1, v2, v3; // 4 quad indices pointing into vertex array
} RTHWIF_QUAD_INDICES;
/* The types of geometries supported. */
typedef enum RTHWIF_GEOMETRY_TYPE : uint8_t
{
RTHWIF_GEOMETRY_TYPE_TRIANGLES = 0, // triangle mesh geometry type
RTHWIF_GEOMETRY_TYPE_QUADS = 1, // quad mesh geometry type
RTHWIF_GEOMETRY_TYPE_AABBS_FPTR = 2, // procedural geometry with AABB bounds per primitive
RTHWIF_GEOMETRY_TYPE_INSTANCE = 3, // instance geometry
} RTHWIF_GEOMETRY_TYPE;
/* The format of transformations supported. */
typedef enum RTHWIF_TRANSFORM_FORMAT : uint8_t
{
RTHWIF_TRANSFORM_FORMAT_FLOAT3X4_COLUMN_MAJOR = 0, // 3x4 affine transformation in column major format (see RTHWIF_TRANSFORM_FLOAT3X4_COLUMN_MAJOR layout)
RTHWIF_TRANSFORM_FORMAT_FLOAT4X4_COLUMN_MAJOR = 1, // 4x4 affine transformation in column major format (see RTHWIF_TRANSFORM_FLOAT4X4_COLUMN_MAJOR layout)
RTHWIF_TRANSFORM_FORMAT_FLOAT3X4_ROW_MAJOR = 2, // 3x4 affine transformation in row major format (see RTHWIF_TRANSFORM_FLOAT3X4_ROW_MAJOR layout)
} RTHWIF_TRANSFORM_FORMAT;
/* Instance flags supported (identical to DXR spec) */
typedef enum RTHWIF_INSTANCE_FLAGS : uint8_t
{
RTHWIF_INSTANCE_FLAG_NONE = 0,
RTHWIF_INSTANCE_FLAG_TRIANGLE_CULL_DISABLE = 0x1,
RTHWIF_INSTANCE_FLAG_TRIANGLE_FRONT_COUNTERCLOCKWISE = 0x2,
RTHWIF_INSTANCE_FLAG_FORCE_OPAQUE = 0x4,
RTHWIF_INSTANCE_FLAG_FORCE_NON_OPAQUE = 0x8
} RTHWIF_INSTANCE_FLAGS;
/* Triangle mesh geometry descriptor. */
typedef struct RTHWIF_GEOMETRY_TRIANGLES_DESC // 40 bytes
{
RTHWIF_GEOMETRY_TYPE geometryType; // must be RTHWIF_GEOMETRY_TYPE_TRIANGLES
RTHWIF_GEOMETRY_FLAGS geometryFlags; // geometry flags for all primitives of this geometry
uint8_t geometryMask; // 8-bit geometry mask for ray masking
uint8_t reserved0; // must be zero
uint32_t reserved1; // must be zero
unsigned int triangleCount; // number of triangles in triangleBuffer
unsigned int triangleStride; // stride in bytes of triangles in triangleBuffer
unsigned int vertexCount; // number of vertices in vertexBuffer
unsigned int vertexStride; // stride in bytes of vertices in vertexBuffer
RTHWIF_TRIANGLE_INDICES* triangleBuffer; // pointer to array of triangle indices
RTHWIF_FLOAT3* vertexBuffer; // pointer to array of triangle vertices
} RTHWIF_RAYTRACING_GEOMETRY_TRIANGLES_DESC;
/* Quad mesh geometry descriptor. A quad with vertices v0,v1,v2,v3 is
* rendered as a pair of triangles (v0,v1,v3) and (v2,v3,v1), with
* barycentric coordinates u/v of the second triangle corrected by
* u=1-u, and v=1-v to make a u/v parametrization of the entire
* [0,1]x[0,1] uv space. */
typedef struct RTHWIF_GEOMETRY_QUADS_DESC // 40 bytes
{
RTHWIF_GEOMETRY_TYPE geometryType; // must be RTHWIF_GEOMETRY_TYPE_QUADS
RTHWIF_GEOMETRY_FLAGS geometryFlags; // geometry flags for all primitives of this geometry
uint8_t geometryMask; // 8-bit geometry mask for ray masking
uint8_t reserved0; // must be zero
uint32_t reserved1; // must be zero
unsigned int quadCount; // number of quads in quadBuffer
unsigned int quadStride; // stride in bytes of quads in quadBuffer
unsigned int vertexCount; // number of vertices in vertexBuffer
unsigned int vertexStride; // stride in bytes of vertices in vertexBuffer
RTHWIF_QUAD_INDICES* quadBuffer; // pointer to array of quad indices
RTHWIF_FLOAT3* vertexBuffer; // pointer to array of quad vertices
} RTHWIF_RAYTRACING_GEOMETRY_QUADS_DESC;
/* Function pointer type to return AABBs for a range of procedural primitives. */
typedef void (*RTHWIF_GEOMETRY_AABBS_FPTR)(const uint32_t primID, // first primitive to return bounds for
const uint32_t primIDCount, // number of primitives to return bounds for
void* geomUserPtr, // pointer provided through geometry descriptor
void* buildUserPtr, // pointer provided through rthwifBuildAccel function
RTHWIF_AABB* boundsOut // destination buffer to write AABB bounds to
);
/* Geometry with procedural primitives bound by AABBs. */
typedef struct RTHWIF_GEOMETRY_AABBS_FPTR_DESC // 24 bytes
{
RTHWIF_GEOMETRY_TYPE geometryType; // must be RTHWIF_GEOMETRY_TYPE_AABBS_FPTR
RTHWIF_GEOMETRY_FLAGS geometryFlags; // geometry flags for all primitives of this geometry
uint8_t geometryMask; // 8-bit geometry mask for ray masking
uint8_t reserved; // must be zero
unsigned int primCount; // number of primitives in geometry
RTHWIF_GEOMETRY_AABBS_FPTR getBounds; // function pointer to return bounds for a range of primitives
void* geomUserPtr; // geometry user pointer passed to callback
} RTHWIF_GEOMETRY_AABBS_DESC;
/* Instance geometry descriptor. */
typedef struct RTHWIF_GEOMETRY_INSTANCE_DESC // 32 bytes
{
RTHWIF_GEOMETRY_TYPE geometryType; // must be RTHWIF_GEOMETRY_TYPE_INSTANCE
RTHWIF_INSTANCE_FLAGS instanceFlags; // flags for the instance (see RTHWIF_INSTANCE_FLAGS)
uint8_t geometryMask; // 8-bit geometry mask for ray masking
RTHWIF_TRANSFORM_FORMAT transformFormat; // format of the specified transformation
unsigned int instanceUserID; // a user specified identifier for the instance
float* transform; // local to world instance transformation in specified format
RTHWIF_AABB* bounds; // AABB of the instanced acceleration structure
void* accel; // pointer to acceleration structure to instantiate
} RTHWIF_GEOMETRY_INSTANCE_DESC;
/* A geometry descriptor. */
typedef struct RTHWIF_GEOMETRY_DESC {
RTHWIF_GEOMETRY_TYPE geometryType; // the first byte of a geometry descriptor is always its type and user can case to geometry descriptor structs above
} RTHWIF_GEOMETRY_DESC;
/* Bitmask with features supported. */
typedef enum RTHWIF_FEATURES {
RTHWIF_FEATURES_NONE = 0,
RTHWIF_FEATURES_GEOMETRY_TYPE_TRIANGLES = 1 << 0, // support for RTHWIF_GEOMETRY_TYPE_TRIANGLES geometries
RTHWIF_FEATURES_GEOMETRY_TYPE_QUADS = 1 << 1, // support for RTHWIF_GEOMETRY_TYPE_QUADS geometries
RTHWIF_FEATURES_GEOMETRY_TYPE_AABBS_FPTR = 1 << 2, // support for RTHWIF_GEOMETRY_TYPE_AABBS_FPTR geometries
RTHWIF_FEATURES_GEOMETRY_TYPE_INSTANCE = 1 << 3, // support for RTHWIF_GEOMETRY_TYPE_INSTANCE geometries
} RTHWIF_FEATURES;
/* Return errors from API functions. */
typedef enum RTHWIF_ERROR
{
RTHWIF_ERROR_NONE = 0x0, // no error occured
RTHWIF_ERROR_RETRY = 0x1, // build ran out of memory, app should re-try with more memory
RTHWIF_ERROR_OTHER = 0x2, // some unspecified error occured
RTHWIF_ERROR_PARALLEL_OPERATION = 0x3, // task executing in parallel operation
} RTHWIF_ERROR;
/* Build quality hint for acceleration structure build. */
typedef enum RTHWIF_BUILD_QUALITY
{
RTHWIF_BUILD_QUALITY_LOW = 0, // build low quality acceleration structure (fast)
RTHWIF_BUILD_QUALITY_MEDIUM = 1, // build medium quality acceleration structure (slower)
RTHWIF_BUILD_QUALITY_HIGH = 2, // build high quality acceleration structure (slow)
} RTHWIF_BUILD_QUALITY;
/* Some additional hints for acceleration structure build. */
typedef enum RTHWIF_BUILD_FLAGS
{
RTHWIF_BUILD_FLAG_NONE = 0,
RTHWIF_BUILD_FLAG_DYNAMIC = (1 << 0), // optimize for dynamic content
RTHWIF_BUILD_FLAG_COMPACT = (1 << 1), // build more compact acceleration structure
} RTHWIF_BUILD_FLAGS;
/* A handle of a parallel operation that can get joined with worker threads. */
typedef void* RTHWIF_PARALLEL_OPERATION;
/* Structure returned by rthwifGetAccelSize that contains acceleration
* structure size estimates. */
typedef struct RTHWIF_ACCEL_SIZE
{
/* The size of this structure in bytes. */
size_t structBytes;
/* The expected number of bytes required for the acceleration
* structure. When using an acceleration structure buffer of that
* size, the build is expected to succeed mostly, but it may fail
* with RTHWIF_ERROR_RETRY. */
size_t accelBufferExpectedBytes;
/* The worst number of bytes required for the acceleration
* structure. When using an acceleration structure buffer of that
* size, the build is guaranteed to not run out of memory. */
size_t accelBufferWorstCaseBytes;
/* The scratch buffer bytes required for the acceleration structure
* build. */
size_t scratchBufferBytes;
} RTHWIF_ACCEL_SIZE;
/* Argument structure passed to rthwifBuildAccel function. */
typedef struct RTHWIF_BUILD_ACCEL_ARGS
{
/* The size of this structure in bytes */
size_t structBytes;
/* Array of pointers to geometry descriptors. This array and the
* geometry descriptors themselves can be standard host memory
* allocations. A pointer to a geometry descriptor can be null, in
* which case the geometry is treated as empty. */
const RTHWIF_GEOMETRY_DESC** geometries;
/* Number of geometries in geometry descriptor array. */
uint32_t numGeometries;
/* Destination buffer for acceleration structure. This has to be a
* shared memory allocation aligned to
* RTHWIF_ACCELERATION_STRUCTURE_ALIGNMENT bytes and using the ray
* tracing allocation descriptor
* (ze_raytracing_mem_alloc_ext_desc_t) in the zeMemAllocShared
* call. */
void* accelBuffer;
/* Number of allocated bytes of the acceleration structure
* buffer. This can be 0 in which case the build implementation may
* just return an improved accel buffer expected size estimate by
* looking at the scene data. */
size_t accelBufferBytes;
/* Scratch space buffer to be used during accleration structure
* construction. Can be a standard host allocation. */
void* scratchBuffer;
/* Number of allocated bytes of the scratch space buffer. */
size_t scratchBufferBytes;
/* Build quality to use (see RTHWIF_BUILD_QUALITY) */
RTHWIF_BUILD_QUALITY quality;
/* Some hints for acceleration structure build (see RTHWIF_BUILD_FLAGS) */
RTHWIF_BUILD_FLAGS flags;
/* When parallelOperation is NULL, the build is executed
* sequentially on the current thread. If a parallelOperation is
* specified, then the parallel operation gets attached to the
* parallel build handle. This handle can then get joined with
* worker threads to perform the parallel build operation. Only a
* single build operation can be attached to a parallel build
* operation at a given time. */
RTHWIF_PARALLEL_OPERATION parallelOperation;
/* A pointer passed to callbacks. */
void* buildUserPtr;
/* When the pointer is NULL no data is returned. When the build
* fails with RTHWIF_ERROR_RETRY, this returns new expected
* acceleration structure bytes to be used for re-build. When build
* succeeds this returns the number of bytes used in the
* acceleration structure buffer. */
size_t* accelBufferBytesOut;
/* Destination address to write acceleration structure bounds to (can be NULL). */
RTHWIF_AABB* boundsOut;
/* for debugging purposes use only */
#if defined(EMBREE_SYCL_ALLOC_DISPATCH_GLOBALS)
void* dispatchGlobalsPtr;
#endif
} RTHWIF_BUILD_ACCEL_ARGS;
/*
* Initializes the library.
*/
RTHWIF_API void rthwifInit();
/*
* Cleans up the library.
*/
RTHWIF_API void rthwifExit();
/*
* Returns features supported by the implementation.
*/
RTHWIF_API RTHWIF_FEATURES rthwifGetSupportedFeatures(ze_device_handle_t hDevice);
/*
* The rthwifGetAccelSize function calculates the size of buffers
* required for the acceleration structure build.
args: Specifies the build operation to estimate the buffer sizes
for. The rthwifGetAccelSize function may look at the number
of geometries, the geometry descriptors (but not referenced
data), the existence of an acceleration structure to link,
the build quality, and build flags.
sizeOut: A structure that contains the size information returned,
see RTHWIF_ACCEL_SIZE for more details.
*/
RTHWIF_API RTHWIF_ERROR rthwifGetAccelSize(const RTHWIF_BUILD_ACCEL_ARGS& args, RTHWIF_ACCEL_SIZE& sizeOut);
/*
* The rthwifBuildAccel function builds an acceleration structure of
* the scene consisting of the specified geometry descriptors and
* writes the acceleration structure to the provided destination
* buffer. The build happens on the CPU and is synchronous, thus after
* the function returns the acceleration structure can get used.
*
* It is the users responsibility to manage the acceleration structure
* buffer allocation, deallocation, and potential prefetching to the
* device memory. The required size of the accleration structure
* buffer can be queried with the rthwifGetAccelSize function. The
* acceleration structure buffer must be a shared USM allocation and
* should be present on the host at build time. The referenced scene
* data (index and vertex buffers) can be standard host allocations,
* and will not be referenced into by the build acceleration
* structure.
*
* Before an accleration structure is build, the user has to query the
* size of the acceleration structure and scratch space buffer to
* allocate using the rthwifGetAccelSize. When using the worst case
* size to allocate the acceleration structure buffer, then the
* rthwifGetAccelSize function will never fail with an out of memory
* error. When using the expected size for the acceleration structure
* buffer, then the build may fail with RTHWIF_ERROR_RETRY and
* should then get re-tried with a larger amount of data. Using the
* AccelBufferBytesExpected pointer, the build itself returns an
* improved size estimate which the user can use to re-try the build.
*
* The parallelization of the acceleration structure is abstracted,
* such that the user can decide which tasking library to use,
* e.g. Intel(R) oneAPI Threading Building Blocks. Therefore, the user
* specifies a function pointer to the parallelFor implementation of
* its tasking system. The parallelFor function pointer gets invoked
* by the implementation using the parallel_for body to
* parallelize. The tasking system has to support nested parallelism
* (thus parallel_for can get invoked inside a parallel_for) and C++
* exceptions have to get properly propagated to a parent task to be
* potentially catched by the user.
*/
RTHWIF_API RTHWIF_ERROR rthwifBuildAccel(const RTHWIF_BUILD_ACCEL_ARGS& args);
/*
* Creates a new parallel operation that can get attached to a build
* operation. Only a single build operation can be attached to a
* parallel operation at a given time.
*/
RTHWIF_API RTHWIF_PARALLEL_OPERATION rthwifNewParallelOperation();
/*
* Destroys a parallel operation.
*/
RTHWIF_API void rthwifDeleteParallelOperation( RTHWIF_PARALLEL_OPERATION parallelOperation );
/*
* Returns the maximal number of threads that can join the parallel operation.
*/
RTHWIF_API uint32_t rthwifGetParallelOperationMaxConcurrency( RTHWIF_PARALLEL_OPERATION parallelOperation );
/*
* Called by worker threads to join a parallel build operation. When
* the build finished, all worker threads return from this function
* with the same error code for the build.
*/
RTHWIF_API RTHWIF_ERROR rthwifJoinParallelOperation( RTHWIF_PARALLEL_OPERATION parallelOperation );
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
RTHWIF_API RTHWIF_ERROR rthwifGetAccelSizeGPU(const RTHWIF_BUILD_ACCEL_ARGS& args_i, RTHWIF_ACCEL_SIZE& size_o, void *sycl_queue, uint verbose_level=0);
RTHWIF_API RTHWIF_ERROR rthwifBuildAccelGPU(const RTHWIF_BUILD_ACCEL_ARGS& args, void *sycl_queue, uint verbose_level=0);
RTHWIF_API RTHWIF_ERROR rthwifPrefetchAccelGPU(const RTHWIF_BUILD_ACCEL_ARGS& args, void *sycl_queue, uint verbose_level=0);
#endif
@@ -1,970 +0,0 @@
// Copyright 2009-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <level_zero/ze_api.h>
/**
\file
\brief This file contains a Level Zero API extension to build ray
tracing acceleration structures to be used with an OpenCL ray
tracing API extension.
Ray Tracing Acceleration Structure Build API
============================================
The L0 ray tracing acceleration structure build API provides
functionality to build acceleration structures for 3D scenes on the
host, which can get used for ray tracing on GPU devices.
It is the users responsibility to manage the acceleration structure
buffer allocation and deallocation. The required size of the
accleration structure buffer can be queried with the
zeRaytracingGetAccelSizeExt function and the acceleration structure
an get build on the host using the zeRaytracingBuildAccelExt
function.
To build an acceleration structure one first has to setup a scene
that consists of multiple geometry descriptors, such as
ze_raytracing_geometry_triangles_ext_desc_t for triangle meshes,
ze_raytracing_geometry_quads_ext_desc_t for quad meshes,
ze_raytracing_geometry_aabbs_fptr_ext_desc_t for procedural
primitives with attached axis aligned bounding box, and
ze_raytracing_geometry_instance_ext_desc_t for instances of other
acceleration structures.
The followign example creates an
ze_raytracing_geometry_triangles_ext_desc_t descriptor to specify
a triangle mesh with triangles indices and vertices stored
inside two vectors:
ze_raytracing_geometry_triangles_ext_desc_t mesh;
memset(&mesh,0,sizeof(mesh));
mesh.geometryType = ZE_RAYTRACING_GEOMETRY_TYPE_EXT_TRIANGLES;
mesh.geometryFlags = ZE_RAYTRACING_GEOMETRY_EXT_FLAG_OPAQUE;
mesh.geometryMask = 0xFF;
mesh.triangleFormat = ZE_RAYTRACING_FORMAT_EXT_TRIANGLE_INDICES_UINT32;
mesh.triangleCount = triangles.size();
mesh.triangleStride = 12;
mesh.triangleBuffer = triangles.data();
mesh.vertexFormat = ZE_RAYTRACING_FORMAT_EXT_FLOAT3;
mesh.vertexCount = vertices.size();
mesh.vertexStride = 12;
mesh.vertexBuffer = vertices.data();
The specified geometry flag ZE_RAYTRACING_GEOMETRY_EXT_FLAG_OPAQUE
enables a fast mode where traveral does not return to the caller of
ray tracing for each hit. The proper data formats of the triangle
and vertex buffer is specified, including the strides, and pointer
to first elements in these buffers.
To refer to multiple of these geometries that make a scene, pointers to
these descriptors can be put into an array as follows:
std::vector<ze_raytracing_geometry_ext_desc_t*> geometries;
geometries.push_back((ze_raytracing_geometry_ext_desc_t*)&mesh);
geometries.push_back((ze_raytracing_geometry_ext_desc_t*)&mesh1);
...
This completes the definition of the geometry for the scene to
construct the acceleration structure for. To initiate the BVH build
one first fills the ze_raytracing_build_accel_ext_desc_t structure
with all arguments required for the acceleration structure build as
in the following example:
ze_raytracing_build_accel_ext_desc_t build_desc;
memset(&build_desc,0,sizeof(build_desc));
build_desc.stype = ZE_STRUCTURE_TYPE_RAYTRACING_BUILD_ACCEL_EXT_DESC;
build_desc.pNext = nullptr;
build_desc.hDevice = hDevice;
build_desc.geometries = geometries.data();
build_desc.numGeometries = geometries.size();
build_desc.quality = ZE_RAYTRACING_BUILD_QUALITY_EXT_MEDIUM;
build_desc.flags = ZE_RAYTRACING_BUILD_EXT_FLAG_NONE;
Besides just passing a pointer to the geometries array this sets
some default build flags for a medium quality acceleration
structure. Next the application has to query the buffer sizes
required for the acceleration strucuture and scratch memory required
for the build like in this example:
ze_raytracing_accel_size_ext_properties_t accel_size;
memset(&accel_size,0,sizeof(accel_size));
accel_size.stype = ZE_STRUCTURE_TYPE_RAYTRACING_ACCEL_SIZE_EXT_PROPERTIES;
accel_size.pNext = nullptr;
ze_result_t result = zeRaytracingGetAccelSizeExt( &build_desc, &accel_size );
assert(result == ZE_RESULT_SUCCESS);
This queries the buffer sizes for the build operation specified in
the provided build descriptor. Note that the sizes are only correct
for the provided build descriptor, thus if parameters such as the
build quality get changed for the actual build, calculated sizes are
invalid.
Now we allocate the scratch buffer:
void* scratchBuffer = malloc(accel_size.scratchBufferBytes);
and the acceleration structure buffer using the worst cast
estimates:
ze_raytracing_mem_alloc_ext_desc_t rt_desc;
rt_desc.stype = ZE_STRUCTURE_TYPE_DEVICE_RAYTRACING_EXT_PROPERTIES;
rt_desc.pNext = nullptr;
rt_desc.flags = 0;
ze_device_mem_alloc_desc_t device_desc;
device_desc.stype = ZE_STRUCTURE_TYPE_DEVICE_MEM_ALLOC_DESC;
device_desc.pNext = &rt_desc;
device_desc.flags = ZE_DEVICE_MEM_ALLOC_FLAG_BIAS_CACHED;
device_desc.ordinal = 0;
ze_host_mem_alloc_desc_t host_desc;
host_desc.stype = ZE_STRUCTURE_TYPE_HOST_MEM_ALLOC_DESC;
host_desc.pNext = nullptr;
host_desc.flags = ZE_HOST_MEM_ALLOC_FLAG_BIAS_CACHED;
void* accelBuffer = nullptr;
ze_result_t result = zeMemAllocShared(hContext,
&device_desc, &host_desc,
accel_size.accelBufferWorstCaseBytes,
ZE_RAYTRACING_ACCELERATION_STRUCTURE_ALIGNMENT_EXT,
hDevice,&accelBuffer);
assert(result == ZE_RESULT_SUCCESS);
When using worst case estimate for the acceleration structure
buffer, the build of the acceleration structure is guaranteed not to
run out of memory.
To initiate the build operation we need to additionally specify the
just created buffers in the build descriptor:
build_desc.accelBuffer = accelBuffer;
build_desc.accelBufferBytes = accel_size.accelBufferWorstCaseBytes;
build_desc.scratchBuffer = scratchBuffer;
build_desc.scratchBufferBytes = accelsize.scratchBufferBytes;
Now a single threaded build on the host CPU can get initiated using
the zeRaytracingBuildAccelExt function:
ze_result_t result = zeRaytracingBuildAccelExt( &build_desc );
assert(result == ZE_RESULT_SUCCESS);
When the build completes successfully the acceleration structure
buffer can get used as acceleration structure by the ray tracing
API.
Parallel Build
--------------
In order to speed up the build operation with multiple worker
thread, some parallel operation object can get attached to the build
and joined with application provided worker threads as in the
following example:
ze_raytracing_parallel_operation_ext_handle_t hParallelOperation;
ze_result_t result = zeRaytracingParallelOperationCreateExt(&hParallelOperation);
assert(result == ZE_RESULT_SUCCESS);
build_desc.parallelOperation = hParallelOperation;
result = zeRaytracingBuildAccelExt( &build_desc );
assert(result == ZE_RESULT_RAYTRACING_EXT_OPERATION_DEFERRED);
uint32_t pMaxConcurrency = 0;
result = zeRaytracingParallelOperationGetMaxConcurrencyExt( hParallelOperation, &MaxConcurrency );
assert(result == ZE_RESULT_SUCCESS);
tbb::parallel_for(0u,pMaxConcurrency,1u,[&](uint32_t i) {
ze_result_t result = zeRaytracingParallelOperationJoinExt(hParallelOperation);
assert(result == ZE_RESULT_SUCCESS);
});
result = zeRaytracingParallelOperationDestroyExt(hParallelOperation);
assert(result == ZE_RESULT_SUCCESS);
Conservative Acceleration Buffer Size
-------------------------------------
While using the conservative size estimate of the acceleration
structure guarantees a successfull build, the memory requirements
are larger than typically required. To reduce memory usage the
application can also use the expected acceleration buffer size and
re-try the build operation in case it ran out of memory. The
following code illustrates this concept:
void* accelBuffer = nullptr;
size_t accel_bytes = accel_size.accelBufferExpectedBytes;
while (true)
{
accelBuffer = allocate_accel_buffer(accel_bytes);
build_desc.accelBuffer = accelBuffer;
build_desc.accelBufferBytes = accel_bytes;
build_desc.accelBufferBytesOut = &accel_bytes;
ze_result_t result = zeRaytracingBuildAccelExt( &build_desc );
if (result == ZE_RESULT_SUCCESS) break;
assert(result == ZE_RESULT_RAYTRACING_EXT_RETRY_BUILD_ACCEL);
// accel_bytes got increased to a larger estimate for a next try
free_accel_buffer(accelBuffer);
}
The loop starts with the expected acceleration buffer size, for
which the build will mostly succeed. If the build runs out of memory
the ZE_RESULT_RAYTRACING_EXT_RETRY_BUILD_ACCEL result is returned
and the build can get re-tried with a larger acceleration structure
buffer.
The example above passes a pointer to the accel_bytes variable as
accelBufferBytesOut input to the build operation. This causes the
builder to write a larger acceleration structure size estimate to be
used in the next try into the accel_bytes variable. Alternatively,
the application can also increase the acceleration buffer size for
the next try by some percentage, or just use the worst case size for
a second try.
/**
\brief Additional ze_result_t enum fields.
*/
typedef enum _ze_result_t
{
ZE_RESULT_SUCCESS, ///< operation was successfull
ZE_RESULT_ERROR_UNKNOWN, ///< unknown error occurred
ZE_RESULT_RAYTRACING_EXT_RETRY_BUILD_ACCEL, ///< acceleration structure build ran out of memory, app should re-try with more memory
ZE_RESULT_RAYTRACING_EXT_OPERATION_DEFERRED, ///< operation is deferred to a parallel operation
ZE_RESULT_RAYTRACING_EXT_ACCEL_INCOMPATIBLE, ///< the tested devices have incompatible acceleration structures
} ze_result_t;
/**
\brief Additional ze_structure_type_t enum fields.
*/
typedef enum _ze_structure_type_t
{
ZE_STRUCTURE_TYPE_RAYTRACING_ACCEL_SIZE_EXT_PROPERTIES, ///< ze_raytracing_accel_size_ext_properties_t
ZE_STRUCTURE_TYPE_RAYTRACING_BUILD_ACCEL_EXT_DESC, ///< ze_raytracing_build_accel_ext_desc_t
} ze_structure_type_t;
/**
\brief Feature bit for acceleration structure build API
*/
typedef enum _ze_device_raytracing_ext_flag_t {
ZE_DEVICE_RAYTRACING_EXT_FLAG_ACCEL_BUILD, ///< support for ray tracing acceleration structure build API
} ze_device_raytracing_ext_flag_t;
/**
\brief A handle of a parallel operation that can get joined with worker threads.
A parallel operation object can get used to perform acceleration
structure build operations in parallel on multiple hardware
thread. Therefore, a parallel build operation attached to an
acceleration strucutre build can get joined by application manged
threads to assist in building the acceleration structure.
*/
typedef _ze_raytracing_parallel_operation_ext_handle_t* ze_raytracing_parallel_operation_ext_handle_t;
/**
\brief Create new parallel operation
Creates a new parallel operation that can get attached to a build
operation. Only a single build operation can be attached to a
parallel operation at a given time.
*/
ZE_APIEXPORT ze_result_t ZE_APICALL zeRaytracingParallelOperationCreateExt( ze_raytracing_parallel_operation_ext_handle_t* phParallelOperation );
/**
\brief Destroy parallel operation.
*/
ZE_APIEXPORT ze_result ZE_APICALL zeRaytracingParallelOperationDestroyExt( ze_raytracing_parallel_operation_ext_handle_t hParallelOperation );
/**
\brief Returns the maximal number of threads that can join the parallel operation.
*/
ZE_APIEXPORT ze_result ZE_APICALL zeRaytracingParallelOperationGetMaxConcurrencyExt( ze_raytracing_parallel_operation_ext_handle_t hParallelOperation, uint32_t* pMaxConcurrency );
/**
\brief Join parallel operation
Called by worker threads to join a parallel build operation. When
the build finished, all worker threads return from this function
with the same error code of the build.
*/
ZE_APIEXPORT ze_result_t ZE_APICALL zeRaytracingParallelOperationJoinExt( ze_raytracing_parallel_operation_ext_handle_t hParallelOperation );
/** Required alignment of acceleration structure buffer. */
#define ZE_RAYTRACING_ACCELERATION_STRUCTURE_ALIGNMENT_EXT 128
/**
\brief Enumeration of geometry flags supported by the geometries.
*/
typedef uint8_t ze_raytracing_geometry_ext_flags_t;
typedef enum _ze_raytracing_geometry_ext_flag_t : uint8_t
{
ZE_RAYTRACING_GEOMETRY_EXT_FLAG_NONE = 0, ///< Default geometry flags
ZE_RAYTRACING_GEOMETRY_EXT_FLAG_OPAQUE = 1, ///< Opaque geometries do not invoke an anyhit shader
} ze_raytracing_geometry_ext_flag_t;
/**
\brief Format of elements in data buffers.
The format is used to specify the format of elements of data buffer,
such as the format of transformation used for instancing, or index
format for triangles and quads.
*/
typedef enum _ze_raytracing_format_ext_t : uint8_t
{
ZE_RAYTRACING_FORMAT_EXT_FLOAT3, ///< 3 component float vector (see ze_raytracing_float3_ext_t layout)
ZE_RAYTRACING_FORMAT_EXT_FLOAT3X4_COLUMN_MAJOR, ///< 3x4 affine transformation in column major format (see ze_raytracing_transform_float3x4_column_major_ext_t layout)
ZE_RAYTRACING_FORMAT_EXT_FLOAT3X4_ALIGNED_COLUMN_MAJOR, ///< 3x4 affine transformation in column major format (see ze_raytracing_transform_float3x4_aligned_column_major_ext_t layout)
ZE_RAYTRACING_FORMAT_EXT_FLOAT3X4_ROW_MAJOR, ///< 3x4 affine transformation in row major format (see ze_raytracing_transform_float3x4_row_major_ext_t layout)
ZE_RAYTRACING_FORMAT_EXT_AABB, ///< 3 dimensional axis aligned bounding box (see ze_raytracing_aabb_ext_t layout)
ZE_RAYTRACING_FORMAT_EXT_TRIANGLE_INDICES_UINT32, ///< triangle indices of uint32 type (see ze_raytracing_triangle_indices_uint32_ext_t layout)
ZE_RAYTRACING_FORMAT_EXT_QUAD_INDICES_UINT32, ///< quad indices of uint32 type (see ze_raytracing_quad_indices_uint32_ext_t layout)
} ze_raytracing_format_ext_t;
/**
\brief A 3-component short vector type.
*/
typedef struct _ze_raytracing_float3_ext_t {
float x; ///< x coordinate of float3 vector
float y; ///< y coordinate of float3 vector
float z; ///< z coordinate of float3 vector
} ze_raytracing_float3_ext_t;
/**
\brief 3x4 affine transformation in column major layout
A 3x4 affine transformation in column major layout, consisting of
vectors vx=(vx_x,vx_y,vx_z), vy=(vy_x,vy_y,vy_z),
vz=(vz_x,vz_y,vz_z), and p=(p_x,p_y,p_z). The transformation
transforms a point (x,y,z) to x*vx + y*vy + z*vz + * p.
*/
typedef struct _ze_raytracing_transform_float3x4_column_major_ext_t {
float vx_x, vx_y, vx_z; ///< column 0 of 3x4 matrix
float vy_x, vy_y, vy_z; ///< column 1 of 3x4 matrix
float vz_x, vz_y, vz_z; ///< column 2 of 3x4 matrix
float p_x, p_y, p_z; ///< column 3 of 3x4 matrix
} ze_raytracing_transform_float3x4_column_major_ext_t;
/**
\brief 3x4 affine transformation in column major layout with aligned column vectors
A 3x4 affine transformation in column major layout, consisting of
vectors vx=(vx_x,vx_y,vx_z), vy=(vy_x,vy_y,vy_z),
vz=(vz_x,vz_y,vz_z), and p=(p_x,p_y,p_z). The transformation
transforms a point (x,y,z) to x*vx + y*vy + z*vz + p. The column
vectors are aligned to 16 bytes and pad members are ignored.
*/
typedef struct _ze_raytracing_transform_float3x4_aligned_column_major_ext_t
{
float vx_x, vx_y, vx_z, pad0; ///< column 0 of 3x4 matrix with ignored padding
float vy_x, vy_y, vy_z, pad1; ///< column 1 of 3x4 matrix with ignored padding
float vz_x, vz_y, vz_z, pad2; ///< column 2 of 3x4 matrix with ignored padding
float p_x, p_y, p_z, pad3; ///< column 3 of 3x4 matrix with ignored padding
} ze_raytracing_transform_float3x4_aligned_column_major_ext_t;
/**
\brief 3x4 affine transformation in row major layout
A 3x4 affine transformation in row major layout, consisting of
vectors vx=(vx_x,vx_y,vx_z), vy=(vy_x,vy_y,vy_z),
vz=(vz_x,vz_y,vz_z), and p=(p_x,p_y,p_z). The transformation
transforms a point (x,y,z) to x*vx + y*vy + z*vz + p.
*/
typedef struct _ze_raytracing_transform_float3x4_row_major_ext_t
{
float vx_x, vy_x, vz_x, p_x; ///< row 0 of 3x4 matrix
float vx_y, vy_y, vz_y, p_y; ///< row 1 of 3x4 matrix
float vx_z, vy_z, vz_z, p_z; ///< row 2 of 3x4 matrix
} ze_raytracing_transform_float3x4_row_major_ext_t;
/**
\brief Axis aligned 3-dimensional bounding box (AABB) with lower and
upper bounds in each dimension.
*/
typedef struct _ze_raytracing_aabb_ext_t
{
ze_raytracing_float3_ext_t lower; ///< lower bounds of AABB
ze_raytracing_float3_ext_t upper; ///< upper bounds of AABB
} ze_raytracing_aabb_ext_t;
/**
\brief Triangle represented using 3 vertex indices
This strucure represents a triangle using 3 vertex indices that
index into a vertex array that needs to be provided together with
the index array.
The linear barycentric u/v parametrization of the triangle is
defined to be (u=0, v=0) at v0, (u=1, v=0) at v1, and (u=0, v=1) at
v2.
*/
typedef struct _ze_raytracing_triangle_indices_uint32_ext_t
{
uint32_t v0; ///< first index pointing to the first triangle vertex in vertex array
uint32_t v1; ///< second index pointing to the second triangle vertex in vertex array
uint32_t v2; ///< third index pointing to the third triangle vertex in vertex array
} ze_raytracing_triangle_indices_uint32_ext_t;
/**
\brief Quad represented using 4 vertex indices
Represents a quad composed of 4 indices that index into a vertex
array that needs to be provided together with the index array.
A quad is a triangle pair represented using 4 vertex indices
v0,v1,v2,v3. The first triangle is made out of indices v0,v1,v3 and
the second triangle from indices v2,v3,v1. The piecewise linear
barycentric u/v pametrization of the quad is defined to be (u=0,
v=0) at v0, (u=1, v=0) at v1, (u=0, v=1) at v3, and (u=1, v=1) at
v2. This is achieved by correcting the u'/v' coordinates of the
second triangle by u = 1-u' and v = 1-v', yielding a piecewise
linear parametrization.
*/
typedef struct _ze_raytracing_quad_indices_uint32_ext_t
{
uint32_t v0; ///< first index pointing to the first quad vertex in vertex array
uint32_t v1; ///< second index pointing to the second quad vertex in vertex array
uint32_t v2; ///< third index pointing to the third quad vertex in vertex array
uint32_t v3; ///< forth index pointing to the forth quad vertex in vertex array
} ze_raytracing_quad_indices_uint32_ext_t;
/**
\brief The types of geometries supported.
A type that identifies the various geometry descriptors supported by
the API. Each geometry descriptor has this type stored as it first
member at offset 0 to identify the type of the descriptor.
*/
typedef enum _ze_raytracing_geometry_type_ext_t : uint8_t
{
ZE_RAYTRACING_GEOMETRY_TYPE_EXT_TRIANGLES = 0, ///< triangle mesh geometry type identifying ze_raytracing_geometry_triangles_ext_desc_t
ZE_RAYTRACING_GEOMETRY_TYPE_EXT_QUADS = 1, ///< quad mesh geometry type identifying ze_raytracing_geometry_quads_ext_desc_t
ZE_RAYTRACING_GEOMETRY_TYPE_EXT_AABBS_FPTR = 2, ///< procedural geometry type identifying ze_raytracing_geometry_aabbs_fptr_ext_desc_t
ZE_RAYTRACING_GEOMETRY_TYPE_EXT_INSTANCE = 3, ///< instance geometry type identifying ze_raytracing_geometry_instance_ext_desc_t
} ze_raytracing_geometry_type_ext_t;
/**
\brief Instance flags supported
This enumation lists flags to be used to specify instances.
*/
typedef uint8_t ze_raytracing_instance_ext_flags_t;
typedef enum _ze_raytracing_instance_ext_flag_t : uint8_t
{
ZE_RAYTRACING_INSTANCE_EXT_FLAG_NONE = 0, ///< default instance flag
ZE_RAYTRACING_INSTANCE_EXT_FLAG_TRIANGLE_CULL_DISABLE = 0x1, ///< disables culling of front and backfacing triangles
ZE_RAYTRACING_INSTANCE_EXT_FLAG_TRIANGLE_FRONT_COUNTERCLOCKWISE = 0x2, ///< reverses front and back face of triangles
ZE_RAYTRACING_INSTANCE_EXT_FLAG_FORCE_OPAQUE = 0x4, ///< forces instanced geometry to be opaque, unless ray flag forces it to be non-opaque
ZE_RAYTRACING_INSTANCE_EXT_FLAG_FORCE_NON_OPAQUE = 0x8 ///< forces instanced geometry to be non-opaque, unless ray flag forces it to be opaque
} ze_raytracing_instance_ext_flag_ext_t;
/**
\brief Base structure for all geometry descriptors.
Each geometry descriptor has a geometry type as it's first argument
that identifies which geometry is represented. See
ze_raytracing_geometry_type_ext_t for details.
*/
typedef struct _ze_raytracing_geometry_ext_desc_t {
ze_raytracing_geometry_type_ext_t geometryType; ///< type of geometry descriptor
} ze_raytracing_geometry_ext_desc_t;
/**
\brief Geometry descriptor of a triangle mesh
This geometry descriptor describes a triangle mesh consisting of an
triangle buffer (index buffer), and a vertex buffer.
The linear barycentric u/v parametrization of the triangle is
defined to be (u=0, v=0) at v0, (u=1, v=0) at v1, and (u=0, v=1) at
v2.
*/
typedef struct _ze_raytracing_geometry_triangles_ext_desc_t // 40 bytes
{
ze_raytracing_geometry_type_ext_t geometryType; ///< must be ZE_RAYTRACING_GEOMETRY_TYPE_EXT_TRIANGLES
ze_raytracing_geometry_ext_flags_t geometryFlags; ///< geometry flags for all primitives of this geometry
uint8_t geometryMask; ///< 8-bit geometry mask for ray masking
uint8_t reserved0; ///< must be zero
uint8_t reserved1; ///< must be zero
uint8_t reserved2; ///< must be zero
ze_raytracing_format_ext_t triangleFormat; ///< format of triangleBuffer (must be ZE_RAYTRACING_FORMAT_EXT_TRIANGLE_INDICES_UINT32)
ze_raytracing_format_ext_t vertexFormat; ///< format of vertexBuffer (must be ZE_RAYTRACING_FORMAT_EXT_FLOAT3)
unsigned int triangleCount; ///< number of triangles in triangleBuffer
unsigned int vertexCount; ///< number of vertices in vertexBuffer
unsigned int triangleStride; ///< stride in bytes of triangles in triangleBuffer
unsigned int vertexStride; ///< stride in bytes of vertices in vertexBuffer
void* triangleBuffer; ///< pointer to array of triangle indices in specified format
void* vertexBuffer; ///< pointer to array of triangle vertices in specified format
} ze_raytracing_geometry_triangles_ext_desc_t;
/**
\brief Geometry descriptor of a quad mesh
This geometry descriptor describes a quad mesh consisting of a quad
buffer (index buffer), and vertex buffer. The indices index
respective vertices in the vertex array.
A quad is a triangle pair represented using 4 vertex indices
v0,v1,v2,v3. The first triangle is made out of indices v0,v1,v3 and
the second triangle from indices v2,v3,v1. The piecewise linear
barycentric u/v pametrization of the quad is defined to be (u=0,
v=0) at v0, (u=1, v=0) at v1, (u=0, v=1) at v3, and (u=1, v=1) at
v2. This is achieved by correcting the u'/v' coordinates of the
second triangle by u = 1-u' and v = 1-v', yielding a piecewise
linear parametrization.
*/
typedef struct _ze_raytracing_geometry_quads_ext_desc_t // 40 bytes
{
ze_raytracing_geometry_type_ext_t geometryType; ///< must be ZE_RAYTRACING_GEOMETRY_TYPE_EXT_QUADS
ze_raytracing_geometry_ext_flags_t geometryFlags; ///< geometry flags for all primitives of this geometry
uint8_t geometryMask; ///< 8-bit geometry mask for ray masking
uint8_t reserved0; ///< must be zero
uint8_t reserved1; ///< must be zero
uint8_t reserved2; ///< must be zero
ze_raytracing_format_ext_t quadFormat; ///< format of quadBuffer (must be ZE_RAYTRACING_FORMAT_EXT_QUAD_INDICES_UINT32)
ze_raytracing_format_ext_t vertexFormat; ///< format of vertexBuffer (must be ZE_RAYTRACING_FORMAT_EXT_FLOAT3)
unsigned int quadCount; ///< number of quads in quadBuffer
unsigned int vertexCount; ///< number of vertices in vertexBuffer
unsigned int quadStride; ///< stride in bytes of quads in quadBuffer
unsigned int vertexStride; ///< stride in bytes of vertices in vertexBuffer
void* quadBuffer; ///< pointer to an array of quad indices in specified format
void* vertexBuffer; ///< pointer to an array of quad vertices in specified format
} ze_raytracing_geometry_quads_ext_desc_t;
/**
\brief Function pointer type to return AABBs for a range of procedural primitives.
*/
typedef void (*ze_raytracing_geometry_aabbs_fptr_ext_t)(const uint32_t primID, ///< [in] first primitive to return bounds for
const uint32_t primIDCount, ///< [in] number of primitives to return bounds for
void* geomUserPtr, ///< [in] pointer provided through geometry descriptor
void* buildUserPtr, ///< [in] pointer provided through zeRaytracingBuildAccelExt function
ze_raytracing_aabb_ext_t* pBoundsOut ///< [out] destination buffer to write AABB bounds to
);
/**
\brief Geometry descriptor of procedural primitives
Geometry with procedural primitives bound by AABBs. A host side
bounds function is provided that is invoked by the acceleration
structure builder to query bounds of procedural primitives on
demand. The callback is passed some geomUserPtr provided with the
geometry that can point to an application side representation of the
procedural primitives. Futher, a second buildUserPtr pointer is
passed to the callback, that can get set through the
zeRaytracingBuildAccel function. This allows the build to change the
bounds of the procedural geometry, e.g. to build a BVH only over a
short time range to implement multi-segment motion blur.
*/
typedef struct _ze_raytracing_geometry_aabbs_fptr_ext_desc_t // 24 bytes
{
ze_raytracing_geometry_type_ext_t geometryType; ///< must be ZE_RAYTRACING_GEOMETRY_TYPE_EXT_AABBS_FPTR
ze_raytracing_geometry_ext_flags_t geometryFlags; ///< geometry flags for all primitives of this geometry
uint8_t geometryMask; ///< 8-bit geometry mask for ray masking
uint8_t reserved; ///< must be zero
unsigned int primCount; ///< number of primitives in geometry
ze_raytracing_geometry_aabbs_fptr_ext_t getBounds; ///< function pointer to return bounds for a range of primitives
void* geomUserPtr; ///< geometry user pointer passed to callback
} ze_raytracing_geometry_aabbs_fptr_ext_desc_t;
/**
\brief Geometry descriptor of an instance
Instance geometry descriptor which contains a pointer to an
acceleration structure to instantiate, a pointer to the object to
world transformation used for instancing, and a pointer to the
object space bounding box of the instantiated acceleration
structure.
*/
typedef struct _ze_raytracing_geometry_instance_ext_desc_t // 32 bytes
{
ze_raytracing_geometry_type_ext_t geometryType; ///< must be ZE_RAYTRACING_GEOMETRY_TYPE_EXT_INSTANCE
ze_raytracing_instance_ext_flags_t instanceFlags; ///< flags for the instance (see ze_raytracing_instance_ext_flags_t)
uint8_t geometryMask; ///< 8-bit geometry mask for ray masking
ze_raytracing_format_ext_t transformFormat; ///< format of the specified transformation
unsigned int instanceUserID; ///< a user specified identifier for the instance
void* transform; ///< object to world instance transformation in specified format
ze_raytracing_aabb_ext_t* bounds; ///< AABB of the instanced acceleration structure
void* accel; ///< pointer to acceleration structure to instantiate
} ze_raytracing_geometry_instance_ext_desc_t;
/**
\brief Build quality hint for acceleration structure build.
Depending on use case different quality modes for acceleration structure build are supported.
A low quality build builds an accelertion structure fast, but at
some reduction in ray tracing performance. This mode is recommended
for dynamic content, such as animated characters.
A medium quality build uses a compromise between build quality and
ray tracing performance. This mode should be used by default.
Higher ray tracing performance can get achieved by using a high
quality build, but acceleration structure build performance might
be significantly reduced.
*/
typedef enum _ze_raytracing_build_quality_ext_t
{
ZE_RAYTRACING_BUILD_QUALITY_EXT_LOW = 0, ///< build low quality acceleration structure (fast)
ZE_RAYTRACING_BUILD_QUALITY_EXT_MEDIUM = 1, ///< build medium quality acceleration structure (slower)
ZE_RAYTRACING_BUILD_QUALITY_EXT_HIGH = 2, ///< build high quality acceleration structure (slow)
} ze_raytracing_build_quality_ext_t;
/**
\brief Flags for acceleration structure build.
These flags allow the application to tune the accelertion structure
build.
Using the ZE_RAYTRACING_BUILD_EXT_FLAG_COMPACT flag causes the
acceleration strucuture to create more compact acceleration
structures.
The acceleration structure build implementation might choose to use
spatial splitting to split large or long primitives into smaller
pieces. This results in any-hit shaders being invoked multiple
times for non-opaque primitives. If the application requires only a
single any-hit shader invokation per primitive, the
ZE_RAYTRACING_BUILD_EXT_FLAG_NO_DUPLICATE_ANYHIT_INVOCATION build flag
should get used.
Usage of any of these flags may reduce ray tracing performance.
*/
typedef uint32_t ze_raytracing_build_ext_flags_t;
typedef enum _ze_raytracing_build_ext_flag_t
{
ZE_RAYTRACING_BUILD_EXT_FLAG_NONE = 0, ///< default build flags
ZE_RAYTRACING_BUILD_EXT_FLAG_COMPACT = (1 << 0), ///< build more compact acceleration structure
ZE_RAYTRACING_BUILD_EXT_FLAG_NO_DUPLICATE_ANYHIT_INVOCATION = (1 << 1), ///< guarantees single any hit shader invokation per primitive
} ze_raytracing_build_ext_flag_t;
/**
\brief Returns information about acceleration structure size estimates
This structure is returned by zeRaytracingGetAccelSizeExt and
contains acceleration structure size estimates.
*/
typedef struct _ze_raytracing_accel_size_ext_properties_t
{
/** [in] type of this structure */
ze_structure_type_t stype;
/** [in,out][optional] must be null or a pointer to an extension-specific structure */
void* pNext;
/**
[out] The expected number of bytes required for the acceleration
structure. When using an acceleration structure buffer of that
size, the build is expected to succeed mostly, but it may fail
with ZE_RESULT_RAYTRACING_EXT_RETRY_BUILD_ACCEL.
*/
size_t accelBufferExpectedBytes;
/**
[out] The worst case number of bytes required for the acceleration
structure. When using an acceleration structure buffer of that
size, the build is guaranteed to not run out of memory.
*/
size_t accelBufferWorstCaseBytes;
/**
[out] The scratch buffer bytes required for the acceleration
structure build.
*/
size_t scratchBufferBytes;
} ze_raytracing_accel_size_ext_properties_t;
/**
\brief Argument structure passed to zeRaytracingBuildAccelExt function.
*/
typedef struct _ze_raytracing_build_accel_ext_desc_t
{
/** [in] type of this structure */
ze_structure_type_t stype;
/** [in,out][optional] must be null or a pointer to an extension-specific structure */
void* pNext;
/** [in] The device to build the acceleration structure for. The
* acceleration structure can also get used on other devices whose
* acceleration structure is compatible with the device specified
* here (see zeRaytracingAccelCompatibilityExt function). */
ze_device_handle_t hDevice;
/**
[in] Array of pointers to geometry descriptors. This array and
the geometry descriptors themselves have to be standard host
memory allocations. A pointer to a geometry descriptor can be
NULL, in which case the geometry is treated as empty.
*/
const ze_raytracing_geometry_ext_desc_t** geometries;
/**
[in] Number of geometries in geometry descriptor array.
*/
uint32_t numGeometries;
/**
[out] Destination buffer for acceleration structure. This has to
be a shared memory allocation aligned to
ZE_RAYTRACING_ACCELERATION_STRUCTURE_ALIGNMENT bytes and using
the ray tracing allocation descriptor
ze_raytracing_mem_alloc_ext_desc_t in the zeMemAllocShared
call.
*/
void* accelBuffer;
/**
[in] Number of allocated bytes of the acceleration structure
buffer. This can be 0 in which case the build implementation may
just return an improved accel buffer expected size estimate by
looking at the scene data.
*/
size_t accelBufferBytes;
/**
[scratch] Scratch space buffer to be used during accleration structure
construction. This buffer has to be a standard host memory allocation.
*/
void* scratchBuffer;
/**
[in] Number of allocated bytes of the scratch space buffer.
*/
size_t scratchBufferBytes;
/**
[in] Build quality to use (see ze_raytracing_build_quality_ext_t)
*/
ze_raytracing_build_quality_ext_t quality;
/**
[in] Some build flags for acceleration structure build (see ze_raytracing_build_ext_flags_t)
*/
ze_raytracing_build_ext_flags_t flags;
/**
[in][optional] When parallelOperation is NULL, the build is
executed sequentially on the current thread. If a
parallelOperation is specified, then the parallel operation gets
attached to the parallel build handle. This handle can then get
joined with worker threads to perform the parallel build
operation. Only a single build operation can be attached to a
parallel build operation at a given time.
*/
ze_raytracing_parallel_operation_ext_handle_t parallelOperation;
/**
[in,optional] A pointer passed to callbacks.
*/
void* buildUserPtr;
/**
[out][optional] When the pointer is NULL no data is
returned. When the build fails with
ZE_RESULT_RAYTRACING_EXT_RETRY_BUILD_ACCEL, this returns the new
expected acceleration structure bytes to be used for
re-build. When the build succeeds this returns the number of
bytes actually used in the acceleration structure buffer.
*/
size_t* accelBufferBytesOut;
/**
[out][optional] Destination address to write acceleration
structure bounds to. When set to NULL no data is returned.
*/
ze_raytracing_aabb_ext_t* boundsOut;
} ze_raytracing_build_accel_ext_desc_t;
/**
\brief Calculates size of buffers required for acceleration structure build.
The zeRaytracingGetAccelSize function calculates the size of buffers
required for the acceleration structure build. The function may look
at the number of geometries, the geometry descriptors (but not
referenced data), the existence of an acceleration structure to
link, the build quality, and build flags of the build operation.
\param args: Specifies the build operation to estimate the buffer sizes for.
\param pAccelSizeOut: A structure that is filled with the returned size information.
*/
ZE_APIEXPORT ze_result_t ZE_APICALL zeRaytracingGetAccelSizeExt( const ze_raytracing_build_accel_ext_desc_t* args, ze_raytracing_accel_size_ext_properties_t* pAccelSizeOut );
/**
\brief Builds a ray tracing acceleration structure
The zeRaytracingBuildAccelExt function builds an acceleration
structure of the scene consisting of the specified geometry
descriptors and writes the acceleration structure to the provided
destination buffer. All types of geometries can get freely mixed
inside a scene. Please see ze_raytracing_build_accel_ext_desc_t for
a description of all input arguments.
It is the users responsibility to manage the acceleration structure
buffer allocation, deallocation, and potential prefetching to the
device memory. The required size of the accleration structure
buffer can be queried with the zeRaytracingGetAccelSizeExt
function. The acceleration structure buffer must be a shared USM
allocation and should be present on the host at build time. The
referenced scene data (index and vertex buffers) can be standard
host allocations, and will not be referenced into by the build
acceleration structure.
Before an accleration structure is build, the user has to use the
zeRaytracingGetAccelSize function to query the size of the
acceleration structure and scratch space buffer to allocate. When
using the worst case size to allocate the acceleration structure
buffer, then the zeRaytracingBuildAccelExt function will never fail
with an out of memory error. When using the expected size for the
acceleration structure buffer, then the build may fail with
ZE_RESULT_RAYTRACING_EXT_RETRY_BUILD_ACCEL and should then get
re-tried with a larger amount of data. Using the
accelBufferBytesOut argument, the build itself returns an improved
size estimate which the user can use to re-try the build.
The acceleration structure build is executed on the host CPU and is
synchronous, thus after the function returns with ZE_RESULT_SUCCESS
the acceleration structure can get used. All provided data buffers
have to be accessible from the host, thus no device memory can get
passed. Unified shared memory has to get used for the acceleration
structure buffer, for the builder to be able to write to it and the
device to read from that buffer.
The constructed accleration structure is self contained, thus does
not require the provided build data to be present after the build
is done.
The constructed acceleration structure cannot get copied into a
different memory buffer as it may contain pointers.
The acceleration build operation can get parallelized by passing a
parallel operation and joining that parallel operation using the
zeRaytracingParallelOperationJoinExt call with user provided worker
threads. When a parallel operation is provided the
zeRaytracingGetAccelSizeExt function returns with result
ZE_RESULT_RAYTRACING_EXT_OPERATION_DEFERRED to indicate that the
build operation is still in progress. The return value of the
zeRaytracingParallelOperationJoinExt function determines the status
of the parallel acceleration structure build.
*/
ZE_APIEXPORT ze_result_t ZE_APICALL zeRaytracingBuildAccelExt( const ze_raytracing_build_accel_ext_desc_t* args );
/**
\brief Checks if the acceleration structure build for hDevice can be used on hDeviceOther.
\param hDevice: device the acceleration structure is build for
\param hDeviceOther: device to check acceleration structure compatibility with
If the acceleration structures are compatible the function returns
ZE_RESULT_SUCCESS, otherwise
ZE_RESULT_RAYTRACING_EXT_ACCEL_INCOMPATIBLE.
*/
ZE_APIEXPORT ze_result_t ZE_APICALL zeRaytracingAccelCompatibilityExt( const ze_device_handle_t hDevice, ze_device_handle_t hDeviceOther );
@@ -1,978 +0,0 @@
#include "../../sycl/rthwif_embree.h"
#include "../../sycl/rthwif_embree_builder.h"
#include "../rttrace/rthwif_internal.h"
#include "rthwif_embree_builder_ploc.h"
#include "qbvh6.h"
#include "../common/algorithms/parallel_reduce.h"
// === less than threshold, a single workgroup is used to perform all PLOC iterations in a single kernel launch ===
#define SINGLE_WG_SWITCH_THRESHOLD 4*1024
// === less than threshold, 40bits morton code + 24bits index are used, otherwise 64bit morton code + 32bit index ===
#define FAST_MC_NUM_PRIMS_THRESHOLD 1024*1024
// === max number of primitives fitting in 24bits ===
#define FAST_MC_MAX_NUM_PRIMS ((uint)1<<24)
// === less than threshold, a single workgroup is used for all radix sort iterations ===
#define SMALL_SORT_THRESHOLD 1024*4
// === maximum number of workgroups with 1024 elements, DG2/PVC perform best with 64 ===
#define MAX_LARGE_WGS 256
// === rebalance if BVH2 subtrees are degenerated ===
#define BVH2_REBALANCE 1
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
namespace embree
{
using namespace embree::isa;
__forceinline size_t estimateSizeInternalNodes(const size_t numQuads, const size_t numInstances, const size_t numProcedurals, const bool conservative)
{
const size_t N = numQuads + numInstances + numProcedurals;
// === conservative estimate ===
size_t numFatLeaves = 0;
if (conservative)
numFatLeaves = ceilf( (float)N/2 ) + ceilf( (float)numInstances/2 ); // FIXME : better upper bound for instance case
else
numFatLeaves = ceilf( (float)N/3 ) + ceilf( (float)numInstances/2 ); // FIXME : better upper bound for instance case
const size_t numInnerNodes = ceilf( (float)numFatLeaves/4 );
return gpu::alignTo(std::max( ((numFatLeaves + numInnerNodes) * 64) , N * 16),64);
}
__forceinline size_t estimateSizeLeafNodes(const size_t numQuads, const size_t numInstances, const size_t numProcedurals)
{
return (numQuads + numProcedurals + 2 * numInstances) * 64;
}
__forceinline size_t estimateAccelBufferSize(const size_t numQuads, const size_t numInstances, const size_t numProcedurals, const bool conservative)
{
const size_t header = 128;
const size_t node_size = estimateSizeInternalNodes(numQuads,numInstances,numProcedurals,conservative);
const size_t leaf_size = estimateSizeLeafNodes(numQuads,numInstances,numProcedurals);
const size_t totalSize = header + node_size + leaf_size;
return totalSize;
}
__forceinline size_t estimateScratchBufferSize(const size_t numPrimitives)
{
// === sizeof(size_t)*MAX_LARGE_WGS for prefix sums across large work groups ===
return sizeof(PLOCGlobals) + sizeof(size_t)*MAX_LARGE_WGS + numPrimitives * sizeof(LeafGenerationData);
}
uint getBVH2Depth(BVH2Ploc *bvh2, uint index, const uint numPrimitives)
{
if (BVH2Ploc::getIndex(index) < numPrimitives) //isLeaf
return 1;
else
return 1 + std::max(getBVH2Depth(bvh2,bvh2[index].leftIndex(),numPrimitives),getBVH2Depth(bvh2,bvh2[index].rightIndex(),numPrimitives));
}
uint getNumLeaves(BVH2Ploc *bvh2, uint index, const uint numPrimitives)
{
if (BVH2Ploc::getIndex(index) < numPrimitives) //isLeaf
return 1;
else
return getNumLeaves(bvh2,bvh2[index].leftIndex(),numPrimitives) + getNumLeaves(bvh2,bvh2[index].rightIndex(),numPrimitives);
}
uint getNumFatLeaves(BVH2Ploc *bvh2, uint index, const uint numPrimitives)
{
if (BVH2Ploc::isFatLeaf(index,numPrimitives)) //isLeaf
return 1;
else
return getNumFatLeaves(bvh2,bvh2[index].leftIndex(),numPrimitives) + getNumFatLeaves(bvh2,bvh2[index].rightIndex(),numPrimitives);
}
void printBVH2Path(BVH2Ploc *bvh2, uint index, const uint numPrimitives)
{
if (BVH2Ploc::getIndex(index) < numPrimitives) //isLeaf
{
PRINT2(index,"LEAF");
}
else
{
const uint depth = getBVH2Depth(bvh2,index,numPrimitives);
const uint leftIndex = bvh2[index].leftIndex();
const uint rightIndex = bvh2[index].rightIndex();
const bool isFatLeafLeft = BVH2Ploc::isFatLeaf(bvh2[index].left,numPrimitives);
const bool isFatLeafRight = BVH2Ploc::isFatLeaf(bvh2[index].right,numPrimitives);
const uint numLeavesLeft = getNumLeaves(bvh2,leftIndex,numPrimitives);
const uint numLeavesRight = getNumLeaves(bvh2,rightIndex,numPrimitives);
PRINT6(index,depth,leftIndex,rightIndex,isFatLeafLeft,isFatLeafRight);
PRINT2(leftIndex,numLeavesLeft);
PRINT2(rightIndex,numLeavesRight);
if (!isFatLeafLeft)
printBVH2Path(bvh2, leftIndex,numPrimitives);
if (!isFatLeafRight)
printBVH2Path(bvh2,rightIndex,numPrimitives);
}
}
void checkBVH2PlocHW(BVH2Ploc *bvh2, uint index,uint &nodes,uint &leaves,float &nodeSAH, float &leafSAH, uint &maxDepth,const uint numPrimitives, const uint bvh2_max_allocations, const uint depth)
{
if (bvh2[index].bounds.empty()) {
PRINT2(index,bvh2[index]);
FATAL("invalid bounds in BVH2");
}
if (!bvh2[index].bounds.checkNumericalBounds())
{
PRINT2(index,bvh2[index]);
FATAL("Numerical Bounds in BVH2");
}
if (BVH2Ploc::getIndex(index) < numPrimitives) //isLeaf
{
leaves++;
leafSAH += bvh2[index].bounds.area();
assert(bvh2[index].getLeafIndex() < numPrimitives);
}
else
{
maxDepth = max(maxDepth,depth+1);
uint indices[BVH_BRANCHING_FACTOR];
const uint numChildren = openBVH2MaxAreaSortChildren(BVH2Ploc::getIndex(index),indices,bvh2,numPrimitives);
for (uint i=0;i<numChildren;i++)
if (BVH2Ploc::getIndex(indices[i]) > bvh2_max_allocations)
FATAL("OPENING ERROR");
nodes++;
nodeSAH += bvh2[index].bounds.area();
if (!bvh2[index].bounds.encloses( bvh2[ bvh2[index].leftIndex() ].bounds )) PRINT2("ENCLOSING ERROR LEFT",index);
checkBVH2PlocHW(bvh2,bvh2[index].leftIndex(),nodes,leaves,nodeSAH,leafSAH,maxDepth,numPrimitives,bvh2_max_allocations,depth+1);
if (!bvh2[index].bounds.encloses( bvh2[ bvh2[index].rightIndex() ].bounds )) PRINT2("ENCLOSING ERROR RIGHT",index);
checkBVH2PlocHW(bvh2,bvh2[index].rightIndex(),nodes,leaves,nodeSAH,leafSAH,maxDepth,numPrimitives,bvh2_max_allocations,depth+1);
}
}
struct BuildTimer {
enum Type {
PRE_PROCESS = 0,
BUILD = 1,
POST_PROCESS = 2,
ALLOCATION = 3,
TOTAL = 4
};
double host_timers[TOTAL];
double device_timers[TOTAL];
double t0,t1;
inline void reset()
{
for (uint i=0;i<TOTAL;i++)
{
host_timers[i] = 0.0;
device_timers[i] = 0.0;
}
}
inline void start(const Type type)
{
t0 = getSeconds();
}
inline void stop(const Type type)
{
t1 = getSeconds();
host_timers[(int)type] += 1000.0*(t1-t0);
}
inline void add_to_device_timer(const Type type, double t)
{
device_timers[(int)type] += t;
}
inline float get_accum_device_timer(const Type type) { return device_timers[(int)type]; }
inline float get_accum_host_timer (const Type type) { return host_timers[(int)type]; }
inline float get_host_timer() { return 1000.0*(t1-t0); }
inline float get_total_device_time()
{
double sum = 0.0;
for (uint i=0;i<ALLOCATION;i++) sum += device_timers[i];
return sum;
}
inline float get_total_host_time()
{
double sum = 0.0;
for (uint i=0;i<ALLOCATION;i++) sum += host_timers[i];
return sum;
}
};
__forceinline uint32_t getNumPrimitives(const RTHWIF_GEOMETRY_DESC* geom)
{
switch (geom->geometryType) {
case RTHWIF_GEOMETRY_TYPE_TRIANGLES : return ((RTHWIF_GEOMETRY_TRIANGLES_DESC*) geom)->triangleCount;
case RTHWIF_GEOMETRY_TYPE_AABBS_FPTR : return ((RTHWIF_GEOMETRY_AABBS_FPTR_DESC*) geom)->primCount;
case RTHWIF_GEOMETRY_TYPE_QUADS : return ((RTHWIF_GEOMETRY_QUADS_DESC*) geom)->quadCount;
case RTHWIF_GEOMETRY_TYPE_INSTANCE : return 1;
default : return 0;
};
}
/* fill all arg members that app did not know of yet */
__forceinline RTHWIF_BUILD_ACCEL_ARGS rthwifPrepareBuildAccelArgs(const RTHWIF_BUILD_ACCEL_ARGS& args_i)
{
RTHWIF_BUILD_ACCEL_ARGS args;
memset(&args,0,sizeof(RTHWIF_BUILD_ACCEL_ARGS));
memcpy(&args,&args_i,std::min(sizeof(RTHWIF_BUILD_ACCEL_ARGS),args_i.structBytes));
args.structBytes = sizeof(RTHWIF_BUILD_ACCEL_ARGS);
return args;
}
__forceinline PrimitiveCounts countPrimitives(const RTHWIF_GEOMETRY_DESC** geometries, const uint numGeometries)
{
auto reduce = [&](const range<size_t>& r) -> PrimitiveCounts
{
PrimitiveCounts counts;
for (size_t geomID = r.begin(); geomID < r.end(); geomID++)
{
const RTHWIF_GEOMETRY_DESC* geom = geometries[geomID];
if (geom == nullptr) continue;
switch (geom->geometryType) {
case RTHWIF_GEOMETRY_TYPE_TRIANGLES :
{
counts.numTriangles += ((RTHWIF_GEOMETRY_TRIANGLES_DESC*) geom)->triangleCount;
counts.numQuadBlocks += (((RTHWIF_GEOMETRY_TRIANGLES_DESC *)geom)->triangleCount+TRIANGLE_QUAD_BLOCK_SIZE-1)/TRIANGLE_QUAD_BLOCK_SIZE;
break;
}
case RTHWIF_GEOMETRY_TYPE_QUADS :
{
counts.numQuads += ((RTHWIF_GEOMETRY_QUADS_DESC*) geom)->quadCount;
counts.numQuadBlocks += (((RTHWIF_GEOMETRY_QUADS_DESC *)geom)->quadCount+TRIANGLE_QUAD_BLOCK_SIZE-1)/TRIANGLE_QUAD_BLOCK_SIZE;
break;
}
case RTHWIF_GEOMETRY_TYPE_AABBS_FPTR : counts.numProcedurals += ((RTHWIF_GEOMETRY_AABBS_FPTR_DESC*) geom)->primCount; break;
case RTHWIF_GEOMETRY_TYPE_INSTANCE : counts.numInstances += 1; break;
default: assert(false); break;
};
};
return counts;
};
const uint COUNT_BLOCK_SIZE = 256;
const uint COUNT_PARALLEL_THRESHOLD = 256;
const PrimitiveCounts primCounts = parallel_reduce((uint)0, numGeometries, COUNT_BLOCK_SIZE, COUNT_PARALLEL_THRESHOLD, PrimitiveCounts(), reduce,
[&](const PrimitiveCounts& b0, const PrimitiveCounts& b1) -> PrimitiveCounts { return b0 + b1; });
return primCounts;
}
RTHWIF_ERROR createEmptyBVH(const RTHWIF_BUILD_ACCEL_ARGS& args, sycl::queue &gpu_queue)
{
sycl::event queue_event = gpu_queue.submit([&](sycl::handler &cgh) {
cgh.single_task([=]() {
QBVH6* qbvh = (QBVH6*)args.accelBuffer;
qbvh->bounds = BBox3f(empty);
qbvh->numPrims = 0;
qbvh->nodeDataStart = 2;
qbvh->nodeDataCur = 3;
qbvh->leafDataStart = 3;
qbvh->leafDataCur = 3;
new (qbvh->nodePtr(2)) QBVH6::InternalNode6(NODE_TYPE_INTERNAL);
});
});
gpu::waitOnEventAndCatchException(queue_event);
if (args.accelBufferBytesOut) *args.accelBufferBytesOut = 128+64;
if (args.boundsOut) { BBox3f geometryBounds (empty); *args.boundsOut = *(RTHWIF_AABB*)&geometryBounds; };
return RTHWIF_ERROR_NONE;
}
// =================================================================================================================================================================================
// =================================================================================================================================================================================
// =================================================================================================================================================================================
RTHWIF_API RTHWIF_ERROR rthwifGetAccelSizeGPU(const RTHWIF_BUILD_ACCEL_ARGS& args_i, RTHWIF_ACCEL_SIZE& size_o, void *sycl_queue, uint verbose_level=0)
{
double time0 = getSeconds();
RTHWIF_BUILD_ACCEL_ARGS args = rthwifPrepareBuildAccelArgs(args_i);
const RTHWIF_GEOMETRY_DESC** geometries = args.geometries;
const uint numGeometries = args.numGeometries;
sycl::queue &gpu_queue = *(sycl::queue*)sycl_queue;
// =============================================================================
// === GPU-based primitive count estimation including triangle quadification ===
// =============================================================================
const PrimitiveCounts primCounts = getEstimatedPrimitiveCounts(gpu_queue,geometries,numGeometries,verbose_level >= 2);
const uint numTriangles = primCounts.numTriangles; // === original number of triangles ===
const uint numMergedTrisQuads = primCounts.numMergedTrisQuads;
const uint numQuads = primCounts.numQuads;
const uint numProcedurals = primCounts.numProcedurals;
const uint numInstances = primCounts.numInstances;
const uint numPrimitives = numMergedTrisQuads + numProcedurals + numInstances;
// =============================================
// === allocation for empty scene is default ===
// =============================================
size_t expectedBytes = 3*64;
size_t worstCaseBytes = 4*64;
if (numPrimitives)
{
expectedBytes = estimateAccelBufferSize( numMergedTrisQuads, numInstances, numProcedurals, false);
worstCaseBytes = estimateAccelBufferSize(numQuads + numTriangles, numInstances, numProcedurals, true);
}
// ===============================================
// === estimate accel and scratch buffer sizes ===
// ===============================================
const size_t scratchBytes = estimateScratchBufferSize(std::max(numPrimitives,numGeometries));
if (verbose_level >= 2)
{
PRINT5(numMergedTrisQuads,numTriangles,numQuads,numProcedurals,numInstances);
PRINT3(expectedBytes,worstCaseBytes,scratchBytes);
}
/* return size to user */
RTHWIF_ACCEL_SIZE size;
memset(&size,0,sizeof(RTHWIF_ACCEL_SIZE));
size.accelBufferExpectedBytes = expectedBytes;
size.accelBufferWorstCaseBytes = worstCaseBytes;
size.scratchBufferBytes = scratchBytes;
size_t bytes_o = size_o.structBytes;
memset(&size_o,0,bytes_o);
memcpy(&size_o,&size,bytes_o);
size_o.structBytes = bytes_o;
double time1 = getSeconds();
if (verbose_level >= 1)
std::cout << "rthwifGetAccelSizeGPU time = " << (float)(time1-time0)*1000.0f << " ms" << std::endl;
return RTHWIF_ERROR_NONE;
}
RTHWIF_API RTHWIF_ERROR rthwifPrefetchAccelGPU(const RTHWIF_BUILD_ACCEL_ARGS& args, void *sycl_queue, uint verbose_level=0)
{
double time0 = getSeconds();
sycl::queue &gpu_queue = *(sycl::queue*)sycl_queue;
#if 0
const RTHWIF_GEOMETRY_DESC** geometries = args.geometries;
const uint numGeometries = args.numGeometries;
// ===================================
// === prefetch builder scene data ===
// ===================================
for (size_t geomID = 0; geomID < numGeometries; geomID++)
{
const RTHWIF_GEOMETRY_DESC* geom = geometries[geomID];
if (geom == nullptr) continue;
switch (geom->geometryType) {
case RTHWIF_GEOMETRY_TYPE_TRIANGLES :
{
RTHWIF_GEOMETRY_TRIANGLES_DESC *t = (RTHWIF_GEOMETRY_TRIANGLES_DESC*)geom;
if (t->vertexBuffer) gpu_queue.prefetch(t->vertexBuffer,t->vertexCount*t->vertexStride);
if (t->triangleBuffer) gpu_queue.prefetch(t->triangleBuffer,t->triangleCount*t->triangleStride);
gpu_queue.prefetch(t,sizeof(RTHWIF_GEOMETRY_TRIANGLES_DESC));
break;
}
case RTHWIF_GEOMETRY_TYPE_QUADS :
{
RTHWIF_GEOMETRY_QUADS_DESC *q = (RTHWIF_GEOMETRY_QUADS_DESC*)geom;
if (q->vertexBuffer) gpu_queue.prefetch(q->vertexBuffer,q->vertexCount*q->vertexStride);
if (q->quadBuffer) gpu_queue.prefetch(q->quadBuffer,q->quadCount*q->quadStride);
gpu_queue.prefetch(q,sizeof(RTHWIF_GEOMETRY_QUADS_DESC));
break;
}
case RTHWIF_GEOMETRY_TYPE_AABBS_FPTR :
{
RTHWIF_GEOMETRY_AABBS_FPTR_DESC *a = (RTHWIF_GEOMETRY_AABBS_FPTR_DESC*)geom;
gpu_queue.prefetch(a,sizeof(RTHWIF_GEOMETRY_AABBS_FPTR_DESC));
break;
}
case RTHWIF_GEOMETRY_TYPE_INSTANCE :
{
RTHWIF_GEOMETRY_INSTANCE_DESC *i = (RTHWIF_GEOMETRY_INSTANCE_DESC*)geom;
gpu_queue.prefetch(i->bounds,sizeof(RTHWIF_AABB));
gpu_queue.prefetch(i,sizeof(RTHWIF_GEOMETRY_INSTANCE_DESC));
break;
}
default: assert(false); break;
};
};
if (geometries) gpu_queue.prefetch(geometries,sizeof(RTHWIF_GEOMETRY_DESC*)*numGeometries);
if (args.accelBuffer) gpu_queue.prefetch(args.accelBuffer ,args.accelBufferBytes);
if (args.scratchBuffer) gpu_queue.prefetch(args.scratchBuffer,args.scratchBufferBytes);
#endif
// ======================================================
// === DUMMY KERNEL TO TRIGGER REMAINING USM TRANSFER ===
// ======================================================
sycl::event queue_event = gpu_queue.submit([&](sycl::handler &cgh) { cgh.single_task([=]() {}); });
gpu::waitOnEventAndCatchException(queue_event);
double time1 = getSeconds();
if (verbose_level >= 1)
std::cout << "rthwifPrefetchAccelGPU time = " << (float)(time1-time0)*1000.0f << " ms" << std::endl;
return RTHWIF_ERROR_NONE;
}
RTHWIF_API RTHWIF_ERROR rthwifBuildAccelGPU(const RTHWIF_BUILD_ACCEL_ARGS& args, void *sycl_queue, uint verbose_level=0)
{
BuildTimer timer;
timer.reset();
timer.start(BuildTimer::PRE_PROCESS);
// ================================
// === GPU device/queue/context ===
// ================================
sycl::queue &gpu_queue = *(sycl::queue*)sycl_queue;
const bool verbose1 = verbose_level >= 1;
const bool verbose2 = verbose_level >= 2;
const uint gpu_maxComputeUnits = gpu_queue.get_device().get_info<sycl::info::device::max_compute_units>();
const uint MAX_WGS = gpu_maxComputeUnits / 8;
uint *host_device_tasks = (uint*)sycl::aligned_alloc(64,HOST_DEVICE_COMM_BUFFER_SIZE,gpu_queue.get_device(),gpu_queue.get_context(),sycl::usm::alloc::host);
if (unlikely(verbose2))
{
const uint gpu_maxWorkGroupSize = gpu_queue.get_device().get_info<sycl::info::device::max_work_group_size>();
const uint gpu_maxLocalMemory = gpu_queue.get_device().get_info<sycl::info::device::local_mem_size>();
PRINT("PLOC++ GPU BVH BUILDER");
PRINT( gpu_queue.get_device().get_info<sycl::info::device::global_mem_size>() );
PRINT(gpu_maxWorkGroupSize);
PRINT(gpu_maxComputeUnits);
PRINT(gpu_maxLocalMemory);
}
// =============================
// === setup scratch pointer ===
// =============================
PLOCGlobals *globals = (PLOCGlobals *)args.scratchBuffer;
uint *const sync_mem = (uint*)((char*)args.scratchBuffer + sizeof(PLOCGlobals));
uint *const scratch = (uint*)((char*)args.scratchBuffer + sizeof(PLOCGlobals) + sizeof(uint)*MAX_LARGE_WGS);
// ======================
// ==== init globals ====
// ======================
{
sycl::event queue_event = gpu_queue.submit([&](sycl::handler &cgh) {
cgh.single_task([=]() {
globals->reset();
});
});
gpu::waitOnEventAndCatchException(queue_event);
if (unlikely(verbose1))
{
double dt = gpu::getDeviceExecutionTiming(queue_event);
timer.add_to_device_timer(BuildTimer::PRE_PROCESS,dt);
if (unlikely(verbose2)) std::cout << "=> Init Globals I: " << dt << " ms" << std::endl;
}
}
// ==============================================================================
// === get primitive type count from geometries, compute quad blocks per geom ===
// ==============================================================================
const RTHWIF_GEOMETRY_DESC** geometries = args.geometries;
uint numGeometries = args.numGeometries;
double device_prim_counts_time = 0.0f;
const PrimitiveCounts primCounts = countPrimitives(gpu_queue,geometries,numGeometries,globals,scratch,host_device_tasks,device_prim_counts_time,verbose1);
// ================================================
timer.stop(BuildTimer::PRE_PROCESS);
timer.add_to_device_timer(BuildTimer::PRE_PROCESS,device_prim_counts_time);
if (unlikely(verbose2)) std::cout << "=> Count Primitives from Geometries: " << timer.get_host_timer() << " ms (host) " << device_prim_counts_time << " ms (device) " << std::endl;
uint numQuads = primCounts.numQuads + primCounts.numTriangles; // no quadification taken into account at this point
uint numProcedurals = primCounts.numProcedurals;
uint numInstances = primCounts.numInstances;
const uint numQuadBlocks = primCounts.numQuadBlocks;
const uint expected_numPrimitives = numQuads + numProcedurals + numInstances;
// =================================================
// === empty scene before removing invalid prims ===
// =================================================
if (unlikely(expected_numPrimitives == 0)) createEmptyBVH(args,gpu_queue);
if (numQuads)
{
// ==================================================
// === compute correct quadification using blocks ===
// ==================================================
timer.start(BuildTimer::PRE_PROCESS);
double device_quadification_time = 0.0;
numQuads = countQuadsPerGeometryUsingBlocks(gpu_queue,globals,args.geometries,numGeometries,numQuadBlocks,scratch,scratch+numGeometries,host_device_tasks,device_quadification_time,verbose1);
timer.stop(BuildTimer::PRE_PROCESS);
timer.add_to_device_timer(BuildTimer::PRE_PROCESS,device_quadification_time);
if (unlikely(verbose2)) std::cout << "=> Count " << numQuads << " Quads " << timer.get_host_timer() << " ms (host) " << (float)device_quadification_time << " ms (device) " << std::endl;
}
// ================================
// === estimate size of the BVH ===
// ================================
size_t numPrimitives = numQuads + numInstances + numProcedurals; // actual #prims can be lower due to invalid instances or procedurals but quads count is accurate at this point
const size_t allocated_size = args.accelBufferBytes;
const size_t header = 128;
const size_t leaf_size = estimateSizeLeafNodes(numQuads,numInstances,numProcedurals);
const size_t node_size = (header + leaf_size) <= allocated_size ? allocated_size - leaf_size - header : 0;
const size_t node_data_start = header;
const size_t leaf_data_start = header + node_size;
// =================================================================
// === if allocated accel buffer is too small, return with error ===
// =================================================================
const uint required_size = header + estimateSizeInternalNodes(numQuads,numInstances,numProcedurals,false) + leaf_size;
if (unlikely(allocated_size < required_size))
{
if (unlikely(verbose2))
{
PRINT2(required_size,allocated_size);
PRINT2(node_size,estimateSizeInternalNodes(numQuads,numInstances,numProcedurals,false));
PRINT3("RETRY BVH BUILD DUE BECAUSE OF SMALL ACCEL BUFFER ALLOCATION!!!", args.accelBufferBytes,required_size );
}
if (args.accelBufferBytesOut) *args.accelBufferBytesOut = required_size;
if (host_device_tasks) sycl::free(host_device_tasks,gpu_queue.get_context());
return RTHWIF_ERROR_RETRY;
}
const size_t conv_mem_size = sizeof(numPrimitives)*numPrimitives;
const size_t NUM_ACTIVE_LARGE_WGS = min((numPrimitives+LARGE_WG_SIZE-1)/LARGE_WG_SIZE,(size_t)MAX_WGS);
// ===========================
// === set up all pointers ===
// ===========================
QBVH6* qbvh = (QBVH6*)args.accelBuffer;
char *bvh_mem = (char*)qbvh + header;
char *const leaf_mem = (char*)qbvh + leaf_data_start;
BVH2Ploc *const bvh2 = (BVH2Ploc*)(leaf_mem);
typedef gpu::MortonCodePrimitive64Bit_2x MCPrim;
MCPrim *const mc0 = (MCPrim*)(bvh2 + numPrimitives);
MCPrim *const mc1 = mc0 + numPrimitives;
MCPrim *const morton_codes[2] = { mc0, mc1 };
uint *const cluster_index = (uint*) (bvh_mem + 0 * numPrimitives * sizeof(uint)); // * 2
BVH2SubTreeState *const bvh2_subtree_size = (BVH2SubTreeState*) (bvh_mem + 2 * numPrimitives * sizeof(uint)); // * 2
uint *cluster_i[2] = { cluster_index + 0, cluster_index + numPrimitives };
uint *const cluster_index_source = cluster_i[0];
uint *const cluster_index_dest = cluster_i[1];
LeafGenerationData *leafGenData = (LeafGenerationData*)scratch;
// ==============================
// ==== init globals phase 2 ====
// ==============================
{
sycl::event queue_event = gpu_queue.submit([&](sycl::handler &cgh) {
cgh.single_task([=]() {
globals->numPrimitives = numPrimitives;
globals->node_mem_allocator_cur = node_data_start/64;
globals->node_mem_allocator_start = node_data_start/64;
globals->leaf_mem_allocator_cur = leaf_data_start/64;
globals->leaf_mem_allocator_start = leaf_data_start/64;
globals->bvh2_index_allocator = numPrimitives;
});
});
gpu::waitOnEventAndCatchException(queue_event);
if (unlikely(verbose1))
{
double dt = gpu::getDeviceExecutionTiming(queue_event);
timer.add_to_device_timer(BuildTimer::PRE_PROCESS,dt);
if (unlikely(verbose2)) std::cout << "=> Init Globals II: " << dt << " ms" << std::endl;
}
}
timer.start(BuildTimer::PRE_PROCESS);
double create_primref_time = 0.0f;
// ===================================================
// ==== merge triangles to quads, create primrefs ====
// ===================================================
if (numQuads)
createQuads_initPLOCPrimRefs(gpu_queue,globals,args.geometries,numGeometries,numQuadBlocks,scratch,bvh2,0,create_primref_time,verbose1);
// ====================================
// ==== create procedural primrefs ====
// ====================================
if (numProcedurals)
numProcedurals = createProcedurals_initPLOCPrimRefs(gpu_queue,args.geometries,numGeometries,sync_mem,NUM_ACTIVE_LARGE_WGS,bvh2,numQuads,host_device_tasks,create_primref_time,verbose1);
// ==================================
// ==== create instance primrefs ====
// ==================================
if (numInstances)
numInstances = createInstances_initPLOCPrimRefs(gpu_queue,args.geometries,numGeometries,sync_mem,NUM_ACTIVE_LARGE_WGS,bvh2,numQuads + numProcedurals,host_device_tasks,create_primref_time,verbose1);
// =================================================================================================
// === recompute actual number of primitives after quadification and removing of invalid entries ===
// =================================================================================================
numPrimitives = numQuads + numInstances + numProcedurals;
const GeometryTypeRanges geometryTypeRanges(numQuads,numProcedurals,numInstances);
if (unlikely(verbose2))
{
PRINT4(numPrimitives,numQuads,numInstances,numProcedurals);
PRINT3(node_size,leaf_size,args.accelBufferBytes);
PRINT2(node_size/64,leaf_size/64);
}
// =================================================================================
// === test for empty scene again after all final primitive counts are available ===
// =================================================================================
if (unlikely(numPrimitives == 0))
{
if (host_device_tasks) sycl::free(host_device_tasks,gpu_queue.get_context());
return createEmptyBVH(args,gpu_queue);
}
timer.stop(BuildTimer::PRE_PROCESS);
timer.add_to_device_timer(BuildTimer::PRE_PROCESS,create_primref_time);
if (unlikely(verbose2)) std::cout << "=> Create Quads/Procedurals/Instances etc, Init PrimRefs: " << timer.get_host_timer() << " ms (host) " << create_primref_time << " ms (device) " << std::endl;
// ==========================================
// ==== get centroid and geometry bounds ====
// ==========================================
timer.start(BuildTimer::PRE_PROCESS);
double device_compute_centroid_bounds_time = 0.0f;
computeCentroidGeometryBounds(gpu_queue, &globals->geometryBounds, &globals->centroidBounds, bvh2, numPrimitives, device_compute_centroid_bounds_time, verbose1);
timer.stop(BuildTimer::PRE_PROCESS);
timer.add_to_device_timer(BuildTimer::PRE_PROCESS,device_compute_centroid_bounds_time);
if (unlikely(verbose2))
std::cout << "=> Get Geometry and Centroid Bounds Phase: " << timer.get_host_timer() << " ms (host) " << device_compute_centroid_bounds_time << " ms (device) " << std::endl;
// ==============================
// ==== compute morton codes ====
// ==============================
const bool fastMCMode = numPrimitives < FAST_MC_NUM_PRIMS_THRESHOLD || (args.quality == RTHWIF_BUILD_QUALITY_LOW && numPrimitives < FAST_MC_MAX_NUM_PRIMS);
timer.start(BuildTimer::PRE_PROCESS);
double device_compute_mc_time = 0.0f;
if (!fastMCMode)
computeMortonCodes64Bit_SaveMSBBits(gpu_queue,&globals->centroidBounds,mc0,bvh2,(uint*)bvh2_subtree_size,numPrimitives,device_compute_mc_time,verbose1);
else
computeMortonCodes64Bit(gpu_queue,&globals->centroidBounds,(gpu::MortonCodePrimitive40x24Bits3D*)mc1,bvh2,numPrimitives,0,(uint64_t)-1,device_compute_mc_time,verbose1);
timer.stop(BuildTimer::PRE_PROCESS);
if (unlikely(verbose2))
std::cout << "=> Compute Morton Codes: " << timer.get_host_timer() << " ms (host) " << device_compute_mc_time << " ms (device) " << std::endl;
// ===========================
// ==== sort morton codes ====
// ===========================
timer.start(BuildTimer::PRE_PROCESS);
if (!fastMCMode) // fastMCMode == 32bit key + 32bit value pairs, !fastMode == 64bit key + 32bit value pairs
{
const uint scratchMemWGs = gpu::getNumWGsScratchSize(conv_mem_size);
const uint nextPowerOf2 = 1 << (32 - sycl::clz(numPrimitives) - 1);
const uint sortWGs = min(max(min((int)nextPowerOf2/8192,(int)gpu_maxComputeUnits/4),1),(int)scratchMemWGs);
sycl::event initial = sycl::event();
sycl::event block0 = gpu::radix_sort_Nx8Bit(gpu_queue, morton_codes[0], morton_codes[1], numPrimitives, (uint*)scratch, 4, 8, initial, sortWGs);
sycl::event restore = restoreMSBBits(gpu_queue,mc0,(uint*)bvh2_subtree_size,numPrimitives,block0,verbose1);
sycl::event block1 = gpu::radix_sort_Nx8Bit(gpu_queue, morton_codes[0], morton_codes[1], numPrimitives, (uint*)scratch, 4, 8, restore, sortWGs);
gpu::waitOnEventAndCatchException(block1);
}
else
{
if (numPrimitives < SMALL_SORT_THRESHOLD)
gpu::radix_sort_single_workgroup(gpu_queue, (uint64_t *)mc0, (uint64_t *)mc1, numPrimitives, 3,8);
else
{
const uint scratchMemWGs = gpu::getNumWGsScratchSize(conv_mem_size);
const uint nextPowerOf2 = 1 << (32 - sycl::clz(numPrimitives) - 1);
const uint sortWGs = min(max(min((int)nextPowerOf2/LARGE_WG_SIZE,(int)gpu_maxComputeUnits/4),1),(int)scratchMemWGs);
sycl::event initial = sycl::event();
sycl::event block0 = gpu::radix_sort_Nx8Bit(gpu_queue, (gpu::MortonCodePrimitive40x24Bits3D*)morton_codes[1], (gpu::MortonCodePrimitive40x24Bits3D*)morton_codes[0], numPrimitives, (uint*)scratch, 3, 8, initial, sortWGs);
gpu::waitOnEventAndCatchException(block0);
}
}
timer.stop(BuildTimer::PRE_PROCESS);
timer.add_to_device_timer(BuildTimer::PRE_PROCESS,timer.get_host_timer());
if (unlikely(verbose2))
std::cout << "=> Sort Morton Codes: " << timer.get_host_timer() << " ms (host and device)" << std::endl;
// ===========================
// ====== init clusters ======
// ===========================
timer.start(BuildTimer::PRE_PROCESS);
double device_init_clusters_time = 0.0f;
if (!fastMCMode)
initClusters(gpu_queue,mc0,bvh2,cluster_index,bvh2_subtree_size,numPrimitives,device_init_clusters_time,verbose1);
else
initClusters(gpu_queue,(gpu::MortonCodePrimitive40x24Bits3D*)mc0,bvh2,cluster_index,bvh2_subtree_size,numPrimitives,device_init_clusters_time,verbose1);
timer.stop(BuildTimer::PRE_PROCESS);
timer.add_to_device_timer(BuildTimer::PRE_PROCESS,device_init_clusters_time);
if (unlikely(verbose2))
std::cout << "=> Init Clusters: " << timer.get_host_timer() << " ms (host) " << device_init_clusters_time << " ms (device) " << std::endl;
uint numPrims = numPrimitives;
// ===================================================================================================================================================
// ===================================================================================================================================================
// ===================================================================================================================================================
// === 8 or 16-wide search radius dependening on compiler flags ===
const uint SEARCH_RADIUS_SHIFT = args.quality == RTHWIF_BUILD_QUALITY_LOW ? 3 : 4;
double device_ploc_iteration_time = 0.0f;
uint iteration = 0;
timer.start(BuildTimer::BUILD);
// ========================
// ==== clear sync mem ====
// ========================
clearScratchMem(gpu_queue,sync_mem,0,NUM_ACTIVE_LARGE_WGS,device_ploc_iteration_time,verbose1);
float ratio = 100.0f;
for (;numPrims>1;iteration++)
{
// ==================================================
// ==== single kernel path if #prims < threshold ====
// ==================================================
if (numPrims < SINGLE_WG_SWITCH_THRESHOLD)
{
double singleWG_time = 0.0f;
singleWGBuild(gpu_queue, globals, bvh2, cluster_index_source, cluster_index_dest, bvh2_subtree_size, numPrims, SEARCH_RADIUS_SHIFT, singleWG_time, verbose1);
timer.add_to_device_timer(BuildTimer::BUILD,singleWG_time);
numPrims = 1;
}
else
{
// ===================================================================================
// ==== nearest neighbor search, merge clusters and create bvh2 nodes (fast path) ====
// ===================================================================================
device_ploc_iteration_time = 0.0f;
iteratePLOC(gpu_queue,globals,bvh2,cluster_index_source,cluster_index_dest,bvh2_subtree_size,sync_mem,numPrims,NUM_ACTIVE_LARGE_WGS,host_device_tasks,SEARCH_RADIUS_SHIFT,device_ploc_iteration_time,ratio < BOTTOM_LEVEL_RATIO,verbose1);
timer.add_to_device_timer(BuildTimer::BUILD,device_ploc_iteration_time);
const uint new_numPrims = *host_device_tasks;
assert(new_numPrims < numPrims);
ratio = (float)(numPrims-new_numPrims) / numPrims * 100.0f;
numPrims = new_numPrims;
// ==========================
}
if (unlikely(verbose2))
PRINT5(iteration,numPrims,ratio,(float)device_ploc_iteration_time,(float)timer.get_accum_device_timer(BuildTimer::BUILD));
}
timer.stop(BuildTimer::BUILD);
if (unlikely(verbose2))
std::cout << "=> PLOC phase: " << timer.get_host_timer() << " ms (host) " << (float)timer.get_accum_device_timer(BuildTimer::BUILD) << " ms (device) " << std::endl;
#if BVH2_REBALANCE == 1
// ===============================================================================================================
// ========================================== rebalance BVH2 if degenerated ======================================
// ===============================================================================================================
#if 0
uint maxDepth = 0;
for (uint i=0;i<numPrims;i++)
{
const uint depth = getBVH2Depth(bvh2,cluster_index_source[i],numPrimitives);
maxDepth = max(maxDepth,depth);
}
PRINT(maxDepth);
#endif
double rebalanceBVH2_time = 0.0f;
rebalanceBVH2(gpu_queue,bvh2,bvh2_subtree_size,numPrimitives,rebalanceBVH2_time,verbose1);
if (unlikely(verbose2))
PRINT(rebalanceBVH2_time);
timer.add_to_device_timer(BuildTimer::BUILD,rebalanceBVH2_time);
#if 0
maxDepth = 0;
for (uint i=0;i<numPrims;i++)
{
const uint depth = getBVH2Depth(bvh2,cluster_index_source[i],numPrimitives);
maxDepth = max(maxDepth,depth);
}
PRINT(maxDepth);
#endif
// ===============================================================================================================
// ===============================================================================================================
// ===============================================================================================================
#endif
// =====================================
// === check and convert BVH2 (host) ===
// =====================================
if (unlikely(verbose2))
PRINT2(globals->bvh2_index_allocator,2*numPrimitives);
if (unlikely(verbose2))
{
PRINT2(globals->bvh2_index_allocator,2*numPrimitives);
if (globals->bvh2_index_allocator >= 2*numPrimitives)
FATAL("BVH2 construction, allocator");
PRINT(globals->rootIndex);
uint nodes = 0;
uint leaves = 0;
float nodeSAH = 0;
float leafSAH = 0;
uint maxDepth = 0;
checkBVH2PlocHW(bvh2,globals->rootIndex,nodes,leaves,nodeSAH,leafSAH,maxDepth,numPrimitives,globals->bvh2_index_allocator,0);
nodeSAH /= globals->geometryBounds.area();
leafSAH /= globals->geometryBounds.area();
PRINT5(nodes,leaves,nodeSAH,leafSAH,maxDepth);
/* --- dummy kernel to trigger USM transfer again to not screw up device timings --- */
sycl::event queue_event = gpu_queue.submit([&](sycl::handler &cgh) {
cgh.single_task([=]() {
});
});
gpu::waitOnEventAndCatchException(queue_event);
}
// =============================
// === convert BVH2 to QBVH6 ===
// =============================
timer.start(BuildTimer::PRE_PROCESS);
float conversion_device_time = 0.0f;
const bool convert_success = convertBVH2toQBVH6(gpu_queue,globals,host_device_tasks,args.geometries,qbvh,bvh2,leafGenData,numPrimitives,numInstances != 0,geometryTypeRanges,conversion_device_time,verbose1);
/* --- init final QBVH6 header --- */
{
sycl::event queue_event = gpu_queue.submit([&](sycl::handler &cgh) {
cgh.single_task([=]() {
/* init qbvh */
qbvh->bounds.lower.x = globals->geometryBounds.lower_x;
qbvh->bounds.lower.y = globals->geometryBounds.lower_y;
qbvh->bounds.lower.z = globals->geometryBounds.lower_z;
qbvh->bounds.upper.x = globals->geometryBounds.upper_x;
qbvh->bounds.upper.y = globals->geometryBounds.upper_y;
qbvh->bounds.upper.z = globals->geometryBounds.upper_z;
qbvh->numPrims = numPrimitives;
qbvh->nodeDataStart = globals->node_mem_allocator_start;
qbvh->nodeDataCur = globals->node_mem_allocator_cur;
qbvh->leafDataStart = globals->leaf_mem_allocator_start;
qbvh->leafDataCur = globals->leaf_mem_allocator_cur;
*(gpu::AABB3f*)host_device_tasks = globals->geometryBounds;
});
});
gpu::waitOnEventAndCatchException(queue_event);
}
if (args.boundsOut) *args.boundsOut = *(RTHWIF_AABB*)host_device_tasks;
timer.stop(BuildTimer::POST_PROCESS);
timer.add_to_device_timer(BuildTimer::POST_PROCESS,conversion_device_time);
if (unlikely(verbose2))
std::cout << "=> BVH2 -> QBVH6 Flattening: " << timer.get_host_timer() << " ms (host) " << conversion_device_time << " ms (device) " << std::endl;
// ==========================================================
// ==========================================================
// ==========================================================
if (unlikely(verbose2))
{
// === memory allocation and usage stats ===
const uint nodes_used = globals->node_mem_allocator_cur-globals->node_mem_allocator_start;
const uint leaves_used = globals->leaf_mem_allocator_cur-globals->leaf_mem_allocator_start;
const float nodes_util = 100.0f * (float)(globals->node_mem_allocator_cur-globals->node_mem_allocator_start) / (node_size/64);
const float leaves_util = 100.0f * (float)(globals->leaf_mem_allocator_cur-globals->leaf_mem_allocator_start) / (leaf_size/64);
PRINT4(globals->node_mem_allocator_start,globals->node_mem_allocator_cur,nodes_used,nodes_util);
PRINT4(globals->leaf_mem_allocator_start,globals->leaf_mem_allocator_cur,leaves_used,leaves_util);
PRINT(globals->numLeaves);
}
if (unlikely(convert_success == false))
{
if (args.accelBufferBytesOut) *args.accelBufferBytesOut = estimateAccelBufferSize(numQuads, numInstances, numProcedurals, true);
if (host_device_tasks) sycl::free(host_device_tasks,gpu_queue.get_context());
return RTHWIF_ERROR_RETRY;
}
#if defined(EMBREE_SYCL_ALLOC_DISPATCH_GLOBALS)
{
sycl::event queue_event = gpu_queue.submit([&](sycl::handler &cgh) {
cgh.single_task([=]() {
HWAccel* hwaccel = (HWAccel*)args.accelBuffer;
hwaccel->dispatchGlobalsPtr = (uint64_t)args.dispatchGlobalsPtr;
});
});
gpu::waitOnEventAndCatchException(queue_event);
}
#endif
if (args.accelBufferBytesOut)
*args.accelBufferBytesOut = args.accelBufferBytes;
#if 1
if (verbose2)
{
gpu::waitOnQueueAndCatchException(gpu_queue);
qbvh->print(std::cout,qbvh->root(),0,6);
BVHStatistics stats = qbvh->computeStatistics();
stats.print(std::cout);
stats.print_raw(std::cout);
PRINT("VERBOSE STATS DONE");
}
#endif
if (host_device_tasks) sycl::free(host_device_tasks,gpu_queue.get_context());
if (unlikely(verbose1))
std::cout << "=> BVH build time: host = " << timer.get_total_host_time() << " ms , device = " << timer.get_total_device_time() << " ms , numPrimitives (original) = " << expected_numPrimitives << " , numPrimitives (build) = " << numPrimitives << std::endl;
return RTHWIF_ERROR_NONE;
}
}
#endif
File diff suppressed because it is too large Load Diff
+1 -2
View File
@@ -74,8 +74,7 @@ namespace embree
cout << " numBuildPrimitivesPostSplit = " << numBuildPrimitivesPostSplit << std::endl;
cout << " primRefSplits = " << std::setprecision(2) << percent(numBuildPrimitivesPostSplit,numBuildPrimitives) << "%" << std::endl;
cout << " numBVHPrimitives = " << totalPrimitives << std::endl;
cout << " spatialSplits = " << std::setprecision(2) << percent(totalPrimitives,numScenePrimitives) << "%" << std::endl;
cout << " maxDepth = " << depth << std::endl;
cout << " spatialSplits = " << std::setprecision(2) << percent(totalPrimitives,numScenePrimitives) << "%" << std::endl;
cout << std::endl;
cout << " #nodes SAH total bytes used total b/node b/child b/prim #child fill" << std::endl;
+5 -2
View File
@@ -3,7 +3,11 @@
#pragma once
#if defined(ZE_RAYTRACING)
#include "sys/platform.h"
#else
#include "../../../common/sys/platform.h"
#endif
namespace embree
{
@@ -98,7 +102,7 @@ namespace embree
};
BVHStatistics ()
: numScenePrimitives(0), numBuildPrimitives(0), numBuildPrimitivesPostSplit(0), depth(1) {}
: numScenePrimitives(0), numBuildPrimitives(0), numBuildPrimitivesPostSplit(0) {}
void print (std::ostream& cout) const;
void print_raw(std::ostream& cout) const;
@@ -106,7 +110,6 @@ namespace embree
size_t numScenePrimitives;
size_t numBuildPrimitives;
size_t numBuildPrimitivesPostSplit;
size_t depth;
NodeStat internalNode;
LeafStat quadLeaf;
LeafStat proceduralLeaf;
+980
View File
@@ -0,0 +1,980 @@
// Copyright 2009-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#define ZE_RESULT_EXP_ERROR_OPERANDS_INCOMPATIBLE ((ze_result_t)0x7ff00004) ///< [Core, Experimental] operands of comparison are not compatible
#define ZE_STRUCTURE_TYPE_RTAS_BUILDER_EXP_DESC ((ze_structure_type_t)0x0002000E) ///< ::ze_rtas_builder_exp_desc_t
#define ZE_STRUCTURE_TYPE_RTAS_BUILDER_BUILD_OP_EXP_DESC ((ze_structure_type_t)0x0002000F) ///< ::ze_rtas_builder_build_op_exp_desc_t
#define ZE_STRUCTURE_TYPE_RTAS_BUILDER_EXP_PROPERTIES ((ze_structure_type_t)0x00020010) ///< ::ze_rtas_builder_exp_properties_t
#define ZE_STRUCTURE_TYPE_RTAS_PARALLEL_OPERATION_EXP_PROPERTIES ((ze_structure_type_t)0x00020011) ///< ::ze_rtas_parallel_operation_exp_properties_t
#define ZE_STRUCTURE_TYPE_RTAS_DEVICE_EXP_PROPERTIES ((ze_structure_type_t)0x00020012) ///< ::ze_rtas_device_exp_properties_t
#define ZE_STRUCTURE_TYPE_RTAS_GEOMETRY_AABBS_EXP_CB_PARAMS ((ze_structure_type_t)0x00020013) ///< ::ze_rtas_geometry_aabbs_exp_cb_params_t
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_builder_exp_desc_t
typedef struct _ze_rtas_builder_exp_desc_t ze_rtas_builder_exp_desc_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_builder_exp_properties_t
typedef struct _ze_rtas_builder_exp_properties_t ze_rtas_builder_exp_properties_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_parallel_operation_exp_properties_t
typedef struct _ze_rtas_parallel_operation_exp_properties_t ze_rtas_parallel_operation_exp_properties_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_device_exp_properties_t
typedef struct _ze_rtas_device_exp_properties_t ze_rtas_device_exp_properties_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_float3_exp_t
typedef struct _ze_rtas_float3_exp_t ze_rtas_float3_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_transform_float3x4_column_major_exp_t
typedef struct _ze_rtas_transform_float3x4_column_major_exp_t ze_rtas_transform_float3x4_column_major_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_transform_float3x4_aligned_column_major_exp_t
typedef struct _ze_rtas_transform_float3x4_aligned_column_major_exp_t ze_rtas_transform_float3x4_aligned_column_major_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_transform_float3x4_row_major_exp_t
typedef struct _ze_rtas_transform_float3x4_row_major_exp_t ze_rtas_transform_float3x4_row_major_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_aabb_exp_t
typedef struct _ze_rtas_aabb_exp_t ze_rtas_aabb_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_triangle_indices_uint32_exp_t
typedef struct _ze_rtas_triangle_indices_uint32_exp_t ze_rtas_triangle_indices_uint32_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_quad_indices_uint32_exp_t
typedef struct _ze_rtas_quad_indices_uint32_exp_t ze_rtas_quad_indices_uint32_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_builder_geometry_info_exp_t
typedef struct _ze_rtas_builder_geometry_info_exp_t ze_rtas_builder_geometry_info_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_builder_triangles_geometry_info_exp_t
typedef struct _ze_rtas_builder_triangles_geometry_info_exp_t ze_rtas_builder_triangles_geometry_info_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_builder_quads_geometry_info_exp_t
typedef struct _ze_rtas_builder_quads_geometry_info_exp_t ze_rtas_builder_quads_geometry_info_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_geometry_aabbs_exp_cb_params_t
typedef struct _ze_rtas_geometry_aabbs_exp_cb_params_t ze_rtas_geometry_aabbs_exp_cb_params_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_builder_procedural_geometry_info_exp_t
typedef struct _ze_rtas_builder_procedural_geometry_info_exp_t ze_rtas_builder_procedural_geometry_info_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_builder_instance_geometry_info_exp_t
typedef struct _ze_rtas_builder_instance_geometry_info_exp_t ze_rtas_builder_instance_geometry_info_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Forward-declare ze_rtas_builder_build_op_exp_desc_t
typedef struct _ze_rtas_builder_build_op_exp_desc_t ze_rtas_builder_build_op_exp_desc_t;
// Intel 'oneAPI' Level-Zero Extension for supporting ray tracing acceleration structure builder.
#if !defined(__GNUC__)
#pragma region RTASBuilder
#endif
///////////////////////////////////////////////////////////////////////////////
#ifndef ZE_RTAS_BUILDER_EXP_NAME
/// @brief Ray Tracing Acceleration Structure Builder Extension Name
#define ZE_RTAS_BUILDER_EXP_NAME "ZE_experimental_rtas_builder"
#endif // ZE_RTAS_BUILDER_EXP_NAME
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray Tracing Acceleration Structure Builder Extension Version(s)
typedef enum _ze_rtas_builder_exp_version_t
{
ZE_RTAS_BUILDER_EXP_VERSION_1_0 = ZE_MAKE_VERSION( 1, 0 ), ///< version 1.0
ZE_RTAS_BUILDER_EXP_VERSION_CURRENT = ZE_MAKE_VERSION( 1, 0 ), ///< latest known version
ZE_RTAS_BUILDER_EXP_VERSION_FORCE_UINT32 = 0x7fffffff
} ze_rtas_builder_exp_version_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure device flags
typedef uint32_t ze_rtas_device_exp_flags_t;
typedef enum _ze_rtas_device_exp_flag_t
{
ZE_RTAS_DEVICE_EXP_FLAG_RESERVED = ZE_BIT(0), ///< reserved for future use
ZE_RTAS_DEVICE_EXP_FLAG_FORCE_UINT32 = 0x7fffffff
} ze_rtas_device_exp_flag_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure format
///
/// @details
/// - This is an opaque ray tracing acceleration structure format
/// identifier.
typedef enum _ze_rtas_format_exp_t
{
ZE_RTAS_FORMAT_EXP_INVALID = 0, ///< Invalid acceleration structure format
ZE_RTAS_FORMAT_EXP_FORCE_UINT32 = 0x7fffffff
} ze_rtas_format_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure builder flags
typedef uint32_t ze_rtas_builder_exp_flags_t;
typedef enum _ze_rtas_builder_exp_flag_t
{
ZE_RTAS_BUILDER_EXP_FLAG_RESERVED = ZE_BIT(0), ///< Reserved for future use
ZE_RTAS_BUILDER_EXP_FLAG_FORCE_UINT32 = 0x7fffffff
} ze_rtas_builder_exp_flag_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure builder parallel operation flags
typedef uint32_t ze_rtas_parallel_operation_exp_flags_t;
typedef enum _ze_rtas_parallel_operation_exp_flag_t
{
ZE_RTAS_PARALLEL_OPERATION_EXP_FLAG_RESERVED = ZE_BIT(0), ///< Reserved for future use
ZE_RTAS_PARALLEL_OPERATION_EXP_FLAG_FORCE_UINT32 = 0x7fffffff
} ze_rtas_parallel_operation_exp_flag_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure builder geometry flags
typedef uint32_t ze_rtas_builder_geometry_exp_flags_t;
typedef enum _ze_rtas_builder_geometry_exp_flag_t
{
ZE_RTAS_BUILDER_GEOMETRY_EXP_FLAG_NON_OPAQUE = ZE_BIT(0), ///< non-opaque geometries invoke an any-hit shader
ZE_RTAS_BUILDER_GEOMETRY_EXP_FLAG_FORCE_UINT32 = 0x7fffffff
} ze_rtas_builder_geometry_exp_flag_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Packed ray tracing acceleration structure builder geometry flags (see
/// ::ze_rtas_builder_geometry_exp_flags_t)
typedef uint8_t ze_rtas_builder_packed_geometry_exp_flags_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure builder instance flags
typedef uint32_t ze_rtas_builder_instance_exp_flags_t;
typedef enum _ze_rtas_builder_instance_exp_flag_t
{
ZE_RTAS_BUILDER_INSTANCE_EXP_FLAG_TRIANGLE_CULL_DISABLE = ZE_BIT(0),///< disables culling of front-facing and back-facing triangles
ZE_RTAS_BUILDER_INSTANCE_EXP_FLAG_TRIANGLE_FRONT_COUNTERCLOCKWISE = ZE_BIT(1), ///< reverses front and back face of triangles
ZE_RTAS_BUILDER_INSTANCE_EXP_FLAG_TRIANGLE_FORCE_OPAQUE = ZE_BIT(2),///< forces instanced geometry to be opaque, unless ray flag forces it to
///< be non-opaque
ZE_RTAS_BUILDER_INSTANCE_EXP_FLAG_TRIANGLE_FORCE_NON_OPAQUE = ZE_BIT(3),///< forces instanced geometry to be non-opaque, unless ray flag forces it
///< to be opaque
ZE_RTAS_BUILDER_INSTANCE_EXP_FLAG_FORCE_UINT32 = 0x7fffffff
} ze_rtas_builder_instance_exp_flag_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Packed ray tracing acceleration structure builder instance flags (see
/// ::ze_rtas_builder_instance_exp_flags_t)
typedef uint8_t ze_rtas_builder_packed_instance_exp_flags_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure builder build operation flags
///
/// @details
/// - These flags allow the application to tune the acceleration structure
/// build operation.
/// - The acceleration structure builder implementation might choose to use
/// spatial splitting to split large or long primitives into smaller
/// pieces. This may result in any-hit shaders being invoked multiple
/// times for non-opaque primitives, unless
/// ::ZE_RTAS_BUILDER_BUILD_OP_EXP_FLAG_NO_DUPLICATE_ANYHIT_INVOCATION is specified.
/// - Usage of any of these flags may reduce ray tracing performance.
typedef uint32_t ze_rtas_builder_build_op_exp_flags_t;
typedef enum _ze_rtas_builder_build_op_exp_flag_t
{
ZE_RTAS_BUILDER_BUILD_OP_EXP_FLAG_COMPACT = ZE_BIT(0), ///< build more compact acceleration structure
ZE_RTAS_BUILDER_BUILD_OP_EXP_FLAG_NO_DUPLICATE_ANYHIT_INVOCATION = ZE_BIT(1), ///< guarantees single any-hit shader invocation per primitive
ZE_RTAS_BUILDER_BUILD_OP_EXP_FLAG_FORCE_UINT32 = 0x7fffffff
} ze_rtas_builder_build_op_exp_flag_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure builder build quality hint
///
/// @details
/// - Depending on use case different quality modes for acceleration
/// structure build are supported.
/// - A low-quality build builds an acceleration structure fast, but at the
/// cost of some reduction in ray tracing performance. This mode is
/// recommended for dynamic content, such as animated characters.
/// - A medium-quality build uses a compromise between build quality and ray
/// tracing performance. This mode should be used by default.
/// - Higher ray tracing performance can be achieved by using a high-quality
/// build, but acceleration structure build performance might be
/// significantly reduced.
typedef enum _ze_rtas_builder_build_quality_hint_exp_t
{
ZE_RTAS_BUILDER_BUILD_QUALITY_HINT_EXP_LOW = 0, ///< build low-quality acceleration structure (fast)
ZE_RTAS_BUILDER_BUILD_QUALITY_HINT_EXP_MEDIUM = 1, ///< build medium-quality acceleration structure (slower)
ZE_RTAS_BUILDER_BUILD_QUALITY_HINT_EXP_HIGH = 2,///< build high-quality acceleration structure (slow)
ZE_RTAS_BUILDER_BUILD_QUALITY_HINT_EXP_FORCE_UINT32 = 0x7fffffff
} ze_rtas_builder_build_quality_hint_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure builder geometry type
typedef enum _ze_rtas_builder_geometry_type_exp_t
{
ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_TRIANGLES = 0,///< triangle mesh geometry type
ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_QUADS = 1, ///< quad mesh geometry type
ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL = 2, ///< procedural geometry type
ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_INSTANCE = 3, ///< instance geometry type
ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_FORCE_UINT32 = 0x7fffffff
} ze_rtas_builder_geometry_type_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Packed ray tracing acceleration structure builder geometry type (see
/// ::ze_rtas_builder_geometry_type_exp_t)
typedef uint8_t ze_rtas_builder_packed_geometry_type_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure data buffer element format
///
/// @details
/// - Specifies the format of data buffer elements.
/// - Data buffers may contain instancing transform matrices, triangle/quad
/// vertex indices, etc...
typedef enum _ze_rtas_builder_input_data_format_exp_t
{
ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3 = 0, ///< 3-component float vector (see ::ze_rtas_float3_exp_t)
ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3X4_COLUMN_MAJOR = 1,///< 3x4 affine transformation in column-major format (see
///< ::ze_rtas_transform_float3x4_column_major_exp_t)
ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3X4_ALIGNED_COLUMN_MAJOR = 2,///< 3x4 affine transformation in column-major format (see
///< ::ze_rtas_transform_float3x4_aligned_column_major_exp_t)
ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3X4_ROW_MAJOR = 3, ///< 3x4 affine transformation in row-major format (see
///< ::ze_rtas_transform_float3x4_row_major_exp_t)
ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_AABB = 4, ///< 3-dimensional axis-aligned bounding-box (see ::ze_rtas_aabb_exp_t)
ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_TRIANGLE_INDICES_UINT32 = 5, ///< Unsigned 32-bit triangle indices (see
///< ::ze_rtas_triangle_indices_uint32_exp_t)
ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_QUAD_INDICES_UINT32 = 6, ///< Unsigned 32-bit quad indices (see ::ze_rtas_quad_indices_uint32_exp_t)
ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FORCE_UINT32 = 0x7fffffff
} ze_rtas_builder_input_data_format_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Packed ray tracing acceleration structure data buffer element format
/// (see ::ze_rtas_builder_input_data_format_exp_t)
typedef uint8_t ze_rtas_builder_packed_input_data_format_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Handle of ray tracing acceleration structure builder object
typedef struct _ze_rtas_builder_exp_handle_t *ze_rtas_builder_exp_handle_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Handle of ray tracing acceleration structure builder parallel
/// operation object
typedef struct _ze_rtas_parallel_operation_exp_handle_t *ze_rtas_parallel_operation_exp_handle_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure builder descriptor
typedef struct _ze_rtas_builder_exp_desc_t
{
ze_structure_type_t stype; ///< [in] type of this structure
const void* pNext; ///< [in][optional] must be null or a pointer to an extension-specific
///< structure (i.e. contains sType and pNext).
ze_rtas_builder_exp_version_t builderVersion; ///< [in] ray tracing acceleration structure builder version
} ze_rtas_builder_exp_desc_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure builder properties
typedef struct _ze_rtas_builder_exp_properties_t
{
ze_structure_type_t stype; ///< [in] type of this structure
void* pNext; ///< [in,out][optional] must be null or a pointer to an extension-specific
///< structure (i.e. contains sType and pNext).
ze_rtas_builder_exp_flags_t flags; ///< [out] ray tracing acceleration structure builder flags
size_t rtasBufferSizeBytesExpected; ///< [out] expected size (in bytes) required for acceleration structure buffer
///< - When using an acceleration structure buffer of this size, the
///< build is expected to succeed; however, it is possible that the build
///< may fail with ::ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY
size_t rtasBufferSizeBytesMaxRequired; ///< [out] worst-case size (in bytes) required for acceleration structure buffer
///< - When using an acceleration structure buffer of this size, the
///< build is guaranteed to not run out of memory.
size_t scratchBufferSizeBytes; ///< [out] scratch buffer size (in bytes) required for acceleration
///< structure build.
} ze_rtas_builder_exp_properties_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure builder parallel operation
/// properties
typedef struct _ze_rtas_parallel_operation_exp_properties_t
{
ze_structure_type_t stype; ///< [in] type of this structure
void* pNext; ///< [in,out][optional] must be null or a pointer to an extension-specific
///< structure (i.e. contains sType and pNext).
ze_rtas_parallel_operation_exp_flags_t flags; ///< [out] ray tracing acceleration structure builder parallel operation
///< flags
uint32_t maxConcurrency; ///< [out] maximum number of threads that may join the parallel operation
} ze_rtas_parallel_operation_exp_properties_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure device properties
///
/// @details
/// - This structure may be passed to ::zeDeviceGetProperties, via `pNext`
/// member of ::ze_device_properties_t.
/// - The implementation shall populate `format` with a value other than
/// ::ZE_RTAS_FORMAT_EXP_INVALID when the device supports ray tracing.
typedef struct _ze_rtas_device_exp_properties_t
{
ze_structure_type_t stype; ///< [in] type of this structure
void* pNext; ///< [in,out][optional] must be null or a pointer to an extension-specific
///< structure (i.e. contains sType and pNext).
ze_rtas_device_exp_flags_t flags; ///< [out] ray tracing acceleration structure device flags
ze_rtas_format_exp_t rtasFormat; ///< [out] ray tracing acceleration structure format
uint32_t rtasBufferAlignment; ///< [out] required alignment of acceleration structure buffer
} ze_rtas_device_exp_properties_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief A 3-component vector type
typedef struct _ze_rtas_float3_exp_t
{
float x; ///< [in] x-coordinate of float3 vector
float y; ///< [in] y-coordinate of float3 vector
float z; ///< [in] z-coordinate of float3 vector
} ze_rtas_float3_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief 3x4 affine transformation in column-major layout
///
/// @details
/// - A 3x4 affine transformation in column major layout, consisting of vectors
/// - vx=(vx_x, vx_y, vx_z),
/// - vy=(vy_x, vy_y, vy_z),
/// - vz=(vz_x, vz_y, vz_z), and
/// - p=(p_x, p_y, p_z)
/// - The transformation transforms a point (x, y, z) to: `x*vx + y*vy +
/// z*vz + p`.
typedef struct _ze_rtas_transform_float3x4_column_major_exp_t
{
float vx_x; ///< [in] element 0 of column 0 of 3x4 matrix
float vx_y; ///< [in] element 1 of column 0 of 3x4 matrix
float vx_z; ///< [in] element 2 of column 0 of 3x4 matrix
float vy_x; ///< [in] element 0 of column 1 of 3x4 matrix
float vy_y; ///< [in] element 1 of column 1 of 3x4 matrix
float vy_z; ///< [in] element 2 of column 1 of 3x4 matrix
float vz_x; ///< [in] element 0 of column 2 of 3x4 matrix
float vz_y; ///< [in] element 1 of column 2 of 3x4 matrix
float vz_z; ///< [in] element 2 of column 2 of 3x4 matrix
float p_x; ///< [in] element 0 of column 3 of 3x4 matrix
float p_y; ///< [in] element 1 of column 3 of 3x4 matrix
float p_z; ///< [in] element 2 of column 3 of 3x4 matrix
} ze_rtas_transform_float3x4_column_major_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief 3x4 affine transformation in column-major layout with aligned column
/// vectors
///
/// @details
/// - A 3x4 affine transformation in column major layout, consisting of vectors
/// - vx=(vx_x, vx_y, vx_z),
/// - vy=(vy_x, vy_y, vy_z),
/// - vz=(vz_x, vz_y, vz_z), and
/// - p=(p_x, p_y, p_z)
/// - The transformation transforms a point (x, y, z) to: `x*vx + y*vy +
/// z*vz + p`.
/// - The column vectors are aligned to 16-bytes and pad members are
/// ignored.
typedef struct _ze_rtas_transform_float3x4_aligned_column_major_exp_t
{
float vx_x; ///< [in] element 0 of column 0 of 3x4 matrix
float vx_y; ///< [in] element 1 of column 0 of 3x4 matrix
float vx_z; ///< [in] element 2 of column 0 of 3x4 matrix
float pad0; ///< [in] ignored padding
float vy_x; ///< [in] element 0 of column 1 of 3x4 matrix
float vy_y; ///< [in] element 1 of column 1 of 3x4 matrix
float vy_z; ///< [in] element 2 of column 1 of 3x4 matrix
float pad1; ///< [in] ignored padding
float vz_x; ///< [in] element 0 of column 2 of 3x4 matrix
float vz_y; ///< [in] element 1 of column 2 of 3x4 matrix
float vz_z; ///< [in] element 2 of column 2 of 3x4 matrix
float pad2; ///< [in] ignored padding
float p_x; ///< [in] element 0 of column 3 of 3x4 matrix
float p_y; ///< [in] element 1 of column 3 of 3x4 matrix
float p_z; ///< [in] element 2 of column 3 of 3x4 matrix
float pad3; ///< [in] ignored padding
} ze_rtas_transform_float3x4_aligned_column_major_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief 3x4 affine transformation in row-major layout
///
/// @details
/// - A 3x4 affine transformation in row-major layout, consisting of vectors
/// - vx=(vx_x, vx_y, vx_z),
/// - vy=(vy_x, vy_y, vy_z),
/// - vz=(vz_x, vz_y, vz_z), and
/// - p=(p_x, p_y, p_z)
/// - The transformation transforms a point (x, y, z) to: `x*vx + y*vy +
/// z*vz + p`.
typedef struct _ze_rtas_transform_float3x4_row_major_exp_t
{
float vx_x; ///< [in] element 0 of row 0 of 3x4 matrix
float vy_x; ///< [in] element 1 of row 0 of 3x4 matrix
float vz_x; ///< [in] element 2 of row 0 of 3x4 matrix
float p_x; ///< [in] element 3 of row 0 of 3x4 matrix
float vx_y; ///< [in] element 0 of row 1 of 3x4 matrix
float vy_y; ///< [in] element 1 of row 1 of 3x4 matrix
float vz_y; ///< [in] element 2 of row 1 of 3x4 matrix
float p_y; ///< [in] element 3 of row 1 of 3x4 matrix
float vx_z; ///< [in] element 0 of row 2 of 3x4 matrix
float vy_z; ///< [in] element 1 of row 2 of 3x4 matrix
float vz_z; ///< [in] element 2 of row 2 of 3x4 matrix
float p_z; ///< [in] element 3 of row 2 of 3x4 matrix
} ze_rtas_transform_float3x4_row_major_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief A 3-dimensional axis-aligned bounding-box with lower and upper bounds
/// in each dimension
typedef struct _ze_rtas_aabb_exp_t
{
ze_rtas_float3_exp_t lower; ///< [in] lower bounds of AABB
ze_rtas_float3_exp_t upper; ///< [in] upper bounds of AABB
} ze_rtas_aabb_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Triangle represented using 3 vertex indices
///
/// @details
/// - Represents a triangle using 3 vertex indices that index into a vertex
/// array that needs to be provided together with the index array.
/// - The linear barycentric u/v parametrization of the triangle is defined as:
/// - (u=0, v=0) at v0,
/// - (u=1, v=0) at v1, and
/// - (u=0, v=1) at v2
typedef struct _ze_rtas_triangle_indices_uint32_exp_t
{
uint32_t v0; ///< [in] first index pointing to the first triangle vertex in vertex array
uint32_t v1; ///< [in] second index pointing to the second triangle vertex in vertex
///< array
uint32_t v2; ///< [in] third index pointing to the third triangle vertex in vertex array
} ze_rtas_triangle_indices_uint32_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Quad represented using 4 vertex indices
///
/// @details
/// - Represents a quad composed of 4 indices that index into a vertex array
/// that needs to be provided together with the index array.
/// - A quad is a triangle pair represented using 4 vertex indices v0, v1,
/// v2, v3.
/// The first triangle is made out of indices v0, v1, v3 and the second triangle
/// from indices v2, v3, v1. The piecewise linear barycentric u/v parametrization
/// of the quad is defined as:
/// - (u=0, v=0) at v0,
/// - (u=1, v=0) at v1,
/// - (u=0, v=1) at v3, and
/// - (u=1, v=1) at v2
/// This is achieved by correcting the u'/v' coordinates of the second
/// triangle by
/// *u = 1-u'* and *v = 1-v'*, yielding a piecewise linear parametrization.
typedef struct _ze_rtas_quad_indices_uint32_exp_t
{
uint32_t v0; ///< [in] first index pointing to the first quad vertex in vertex array
uint32_t v1; ///< [in] second index pointing to the second quad vertex in vertex array
uint32_t v2; ///< [in] third index pointing to the third quad vertex in vertex array
uint32_t v3; ///< [in] fourth index pointing to the fourth quad vertex in vertex array
} ze_rtas_quad_indices_uint32_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure builder geometry info
typedef struct _ze_rtas_builder_geometry_info_exp_t
{
ze_rtas_builder_packed_geometry_type_exp_t geometryType;///< [in] geometry type
} ze_rtas_builder_geometry_info_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure builder triangle mesh geometry info
///
/// @details
/// - The linear barycentric u/v parametrization of the triangle is defined as:
/// - (u=0, v=0) at v0,
/// - (u=1, v=0) at v1, and
/// - (u=0, v=1) at v2
typedef struct _ze_rtas_builder_triangles_geometry_info_exp_t
{
ze_rtas_builder_packed_geometry_type_exp_t geometryType;///< [in] geometry type, must be
///< ::ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_TRIANGLES
ze_rtas_builder_packed_geometry_exp_flags_t geometryFlags; ///< [in] 0 or some combination of ::ze_rtas_builder_geometry_exp_flag_t
///< bits representing the geometry flags for all primitives of this
///< geometry
uint8_t geometryMask; ///< [in] 8-bit geometry mask for ray masking
uint8_t reserved0; ///< [in] reserved for future use
uint8_t reserved1; ///< [in] reserved for future use
uint8_t reserved2; ///< [in] reserved for future use
ze_rtas_builder_packed_input_data_format_exp_t triangleFormat; ///< [in] format of triangle buffer data, must be
///< ::ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_TRIANGLE_INDICES_UINT32
ze_rtas_builder_packed_input_data_format_exp_t vertexFormat;///< [in] format of vertex buffer data, must be
///< ::ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3
uint32_t triangleCount; ///< [in] number of triangles in triangle buffer
uint32_t vertexCount; ///< [in] number of vertices in vertex buffer
uint32_t triangleStride; ///< [in] stride (in bytes) of triangles in triangle buffer
uint32_t vertexStride; ///< [in] stride (in bytes) of vertices in vertex buffer
void* pTriangleBuffer; ///< [in] pointer to array of triangle indices in specified format
void* pVertexBuffer; ///< [in] pointer to array of triangle vertices in specified format
} ze_rtas_builder_triangles_geometry_info_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure builder quad mesh geometry info
///
/// @details
/// - A quad is a triangle pair represented using 4 vertex indices v0, v1,
/// v2, v3.
/// The first triangle is made out of indices v0, v1, v3 and the second triangle
/// from indices v2, v3, v1. The piecewise linear barycentric u/v parametrization
/// of the quad is defined as:
/// - (u=0, v=0) at v0,
/// - (u=1, v=0) at v1,
/// - (u=0, v=1) at v3, and
/// - (u=1, v=1) at v2
/// This is achieved by correcting the u'/v' coordinates of the second
/// triangle by
/// *u = 1-u'* and *v = 1-v'*, yielding a piecewise linear parametrization.
typedef struct _ze_rtas_builder_quads_geometry_info_exp_t
{
ze_rtas_builder_packed_geometry_type_exp_t geometryType;///< [in] geometry type, must be ::ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_QUADS
ze_rtas_builder_packed_geometry_exp_flags_t geometryFlags; ///< [in] 0 or some combination of ::ze_rtas_builder_geometry_exp_flag_t
///< bits representing the geometry flags for all primitives of this
///< geometry
uint8_t geometryMask; ///< [in] 8-bit geometry mask for ray masking
uint8_t reserved0; ///< [in] reserved for future use
uint8_t reserved1; ///< [in] reserved for future use
uint8_t reserved2; ///< [in] reserved for future use
ze_rtas_builder_packed_input_data_format_exp_t quadFormat; ///< [in] format of quad buffer data, must be
///< ::ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_QUAD_INDICES_UINT32
ze_rtas_builder_packed_input_data_format_exp_t vertexFormat;///< [in] format of vertex buffer data, must be
///< ::ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3
uint32_t quadCount; ///< [in] number of quads in quad buffer
uint32_t vertexCount; ///< [in] number of vertices in vertex buffer
uint32_t quadStride; ///< [in] stride (in bytes) of quads in quad buffer
uint32_t vertexStride; ///< [in] stride (in bytes) of vertices in vertex buffer
void* pQuadBuffer; ///< [in] pointer to array of quad indices in specified format
void* pVertexBuffer; ///< [in] pointer to array of quad vertices in specified format
} ze_rtas_builder_quads_geometry_info_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief AABB callback function parameters
typedef struct _ze_rtas_geometry_aabbs_exp_cb_params_t
{
ze_structure_type_t stype; ///< [in] type of this structure
void* pNext; ///< [in,out][optional] must be null or a pointer to an extension-specific
///< structure (i.e. contains sType and pNext).
uint32_t primID; ///< [in] first primitive to return bounds for
uint32_t primIDCount; ///< [in] number of primitives to return bounds for
void* pGeomUserPtr; ///< [in] pointer provided through geometry descriptor
void* pBuildUserPtr; ///< [in] pointer provided through ::zeRTASBuilderBuildExp function
ze_rtas_aabb_exp_t* pBoundsOut; ///< [out] destination buffer to write AABB bounds to
} ze_rtas_geometry_aabbs_exp_cb_params_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Callback function pointer type to return AABBs for a range of
/// procedural primitives
typedef void (*ze_rtas_geometry_aabbs_cb_exp_t)(
ze_rtas_geometry_aabbs_exp_cb_params_t* params ///< [in] callback function parameters structure
);
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure builder procedural primitives
/// geometry info
///
/// @details
/// - A host-side bounds callback function is invoked by the acceleration
/// structure builder to query the bounds of procedural primitives on
/// demand. The callback is passed some `pGeomUserPtr` that can point to
/// an application-side representation of the procedural primitives.
/// Further, a second `pBuildUserPtr`, which is set by a parameter to
/// ::zeRTASBuilderBuildExp, is passed to the callback. This allows the
/// build to change the bounds of the procedural geometry, for example, to
/// build a BVH only over a short time range to implement multi-segment
/// motion blur.
typedef struct _ze_rtas_builder_procedural_geometry_info_exp_t
{
ze_rtas_builder_packed_geometry_type_exp_t geometryType;///< [in] geometry type, must be
///< ::ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL
ze_rtas_builder_packed_geometry_exp_flags_t geometryFlags; ///< [in] 0 or some combination of ::ze_rtas_builder_geometry_exp_flag_t
///< bits representing the geometry flags for all primitives of this
///< geometry
uint8_t geometryMask; ///< [in] 8-bit geometry mask for ray masking
uint8_t reserved; ///< [in] reserved for future use
uint32_t primCount; ///< [in] number of primitives in geometry
ze_rtas_geometry_aabbs_cb_exp_t pfnGetBoundsCb; ///< [in] pointer to callback function to get the axis-aligned bounding-box
///< for a range of primitives
void* pGeomUserPtr; ///< [in] user data pointer passed to callback
} ze_rtas_builder_procedural_geometry_info_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Ray tracing acceleration structure builder instance geometry info
typedef struct _ze_rtas_builder_instance_geometry_info_exp_t
{
ze_rtas_builder_packed_geometry_type_exp_t geometryType;///< [in] geometry type, must be
///< ::ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_INSTANCE
ze_rtas_builder_packed_instance_exp_flags_t instanceFlags; ///< [in] 0 or some combination of ::ze_rtas_builder_geometry_exp_flag_t
///< bits representing the geometry flags for all primitives of this
///< geometry
uint8_t geometryMask; ///< [in] 8-bit geometry mask for ray masking
ze_rtas_builder_packed_input_data_format_exp_t transformFormat; ///< [in] format of the specified transformation
uint32_t instanceUserID; ///< [in] user-specified identifier for the instance
void* pTransform; ///< [in] object-to-world instance transformation in specified format
ze_rtas_aabb_exp_t* pBounds; ///< [in] object-space axis-aligned bounding-box of the instanced
///< acceleration structure
void* pAccelerationStructure; ///< [in] pointer to acceleration structure to instantiate
} ze_rtas_builder_instance_geometry_info_exp_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief
typedef struct _ze_rtas_builder_build_op_exp_desc_t
{
ze_structure_type_t stype; ///< [in] type of this structure
const void* pNext; ///< [in][optional] must be null or a pointer to an extension-specific
///< structure (i.e. contains sType and pNext).
ze_rtas_format_exp_t rtasFormat; ///< [in] ray tracing acceleration structure format
ze_rtas_builder_build_quality_hint_exp_t buildQuality; ///< [in] acceleration structure build quality hint
ze_rtas_builder_build_op_exp_flags_t buildFlags;///< [in] 0 or some combination of ::ze_rtas_builder_build_op_exp_flag_t
///< flags
const ze_rtas_builder_geometry_info_exp_t** ppGeometries; ///< [in][optional][range(0, `numGeometries`)] NULL or a valid array of
///< pointers to geometry infos
uint32_t numGeometries; ///< [in] number of geometries in geometry infos array, can be zero when
///< `ppGeometries` is NULL
/* for debugging purposes use only */
#if defined(EMBREE_SYCL_ALLOC_DISPATCH_GLOBALS)
void* dispatchGlobalsPtr;
#endif
} ze_rtas_builder_build_op_exp_desc_t;
///////////////////////////////////////////////////////////////////////////////
/// @brief Creates a ray tracing acceleration structure builder object
///
/// @details
/// - The application may call this function from simultaneous threads.
/// - The implementation of this function must be thread-safe.
/// - The implementation must support ::ZE_experimental_rtas_builder
/// extension.
///
/// @returns
/// - ::ZE_RESULT_SUCCESS
/// - ::ZE_RESULT_ERROR_UNINITIALIZED
/// - ::ZE_RESULT_ERROR_DEVICE_LOST
/// - ::ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY
/// - ::ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY
/// - ::ZE_RESULT_ERROR_INVALID_NULL_HANDLE
/// + `nullptr == hDriver`
/// - ::ZE_RESULT_ERROR_INVALID_NULL_POINTER
/// + `nullptr == pDescriptor`
/// + `nullptr == phBuilder`
/// - ::ZE_RESULT_ERROR_INVALID_ENUMERATION
/// + `::ZE_RTAS_BUILDER_EXP_VERSION_CURRENT < pDescriptor->builderVersion`
ZE_APIEXPORT ze_result_t ZE_APICALL
zeRTASBuilderCreateExp(
ze_driver_handle_t hDriver, ///< [in] handle of driver object
const ze_rtas_builder_exp_desc_t* pDescriptor, ///< [in] pointer to builder descriptor
ze_rtas_builder_exp_handle_t* phBuilder ///< [out] handle of builder object
);
///////////////////////////////////////////////////////////////////////////////
/// @brief Retrieves ray tracing acceleration structure builder properties
///
/// @details
/// - The application may call this function from simultaneous threads.
/// - The implementation of this function must be thread-safe.
///
/// @returns
/// - ::ZE_RESULT_SUCCESS
/// - ::ZE_RESULT_ERROR_UNINITIALIZED
/// - ::ZE_RESULT_ERROR_DEVICE_LOST
/// - ::ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY
/// - ::ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY
/// - ::ZE_RESULT_ERROR_INVALID_NULL_HANDLE
/// + `nullptr == hBuilder`
/// - ::ZE_RESULT_ERROR_INVALID_NULL_POINTER
/// + `nullptr == pBuildOpDescriptor`
/// + `nullptr == pProperties`
/// - ::ZE_RESULT_ERROR_INVALID_ENUMERATION
/// + `::ZE_RTAS_FORMAT_EXP_INVALID < pBuildOpDescriptor->rtasFormat`
/// + `::ZE_RTAS_BUILDER_BUILD_QUALITY_HINT_EXP_HIGH < pBuildOpDescriptor->buildQuality`
/// + `0x3 < pBuildOpDescriptor->buildFlags`
ZE_APIEXPORT ze_result_t ZE_APICALL
zeRTASBuilderGetBuildPropertiesExp(
ze_rtas_builder_exp_handle_t hBuilder, ///< [in] handle of builder object
const ze_rtas_builder_build_op_exp_desc_t* pBuildOpDescriptor, ///< [in] pointer to build operation descriptor
ze_rtas_builder_exp_properties_t* pProperties ///< [in,out] query result for builder properties
);
///////////////////////////////////////////////////////////////////////////////
/// @brief Checks ray tracing acceleration structure format compatibility
///
/// @details
/// - The application may call this function from simultaneous threads.
/// - The implementation of this function must be thread-safe.
///
/// @returns
/// - ::ZE_RESULT_SUCCESS
/// - ::ZE_RESULT_ERROR_UNINITIALIZED
/// - ::ZE_RESULT_ERROR_DEVICE_LOST
/// - ::ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY
/// - ::ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY
/// - ::ZE_RESULT_ERROR_INVALID_NULL_HANDLE
/// + `nullptr == hBuilder`
/// - ::ZE_RESULT_ERROR_INVALID_ENUMERATION
/// + `::ZE_RTAS_FORMAT_EXP_INVALID < rtasFormatA`
/// + `::ZE_RTAS_FORMAT_EXP_INVALID < rtasFormatB`
/// - ::ZE_RESULT_SUCCESS
/// + An acceleration structure built with `rtasFormatA` is compatible with devices that report `rtasFormatB`.
/// - ::ZE_RESULT_EXP_ERROR_OPERANDS_INCOMPATIBLE
/// + An acceleration structure built with `rtasFormatA` is **not** compatible with devices that report `rtasFormatB`.
ZE_APIEXPORT ze_result_t ZE_APICALL
zeRTASBuilderFormatCompatibilityCheckExp(
ze_rtas_builder_exp_handle_t hBuilder, ///< [in] handle of builder object
ze_rtas_format_exp_t rtasFormatA, ///< [in] operand A
ze_rtas_format_exp_t rtasFormatB ///< [in] operand B
);
///////////////////////////////////////////////////////////////////////////////
/// @brief Build ray tracing acceleration structure
///
/// @details
/// - This function builds an acceleration structure of the scene consisting
/// of the specified geometry information and writes the acceleration
/// structure to the provided destination buffer. All types of geometries
/// can get freely mixed inside a scene.
/// - It is the user's responsibility to manage the acceleration structure
/// buffer allocation, de-allocation, and potential prefetching to the
/// device memory. The required size of the acceleration structure buffer
/// can be queried with the ::zeRTASBuilderGetPropertiesExp function. The
/// acceleration structure buffer must be a shared USM allocation and
/// should be present on the host at build time. The referenced scene data
/// (index- and vertex- buffers) can be standard host allocations, and
/// will not be referenced into by the build acceleration structure.
/// - Before an acceleration structure can be built, the user must allocate
/// the memory for the acceleration structure buffer and scratch buffer
/// using sizes based on a query for the estimated size properties.
/// - When using the "worst-case" size for the acceleration structure
/// buffer, the acceleration structure construction will never fail with
/// an out-of-memory error.
/// - When using the "expected" size for the acceleration structure buffer,
/// the acceleration structure construction may fail with
/// ::ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY. If this happens, the user may
/// resize their acceleration structure buffer using the
/// `*pRtasBufferSizeBytes` value, which will be updated with an improved
/// size estimate that will likely result in a successful build.
/// - The acceleration structure construction is run on the host and is
/// synchronous, thus after the function returns with a successful result,
/// the acceleration structure may be used.
/// - All provided data buffers must be host-accessible.
/// - The acceleration structure buffer must be a USM allocation.
/// - A successfully constructed acceleration structure is entirely
/// self-contained. There is no requirement for input data to persist
/// beyond build completion.
/// - A successfully constructed acceleration structure is non-copyable.
/// - Acceleration structure construction may be parallelized by passing a
/// valid handle to a parallel operation object and joining that parallel
/// operation using ::zeRTASParallelOperationJoinExp with user-provided
/// worker threads.
/// - **Additional Notes**
/// - "The geometry infos array, geometry infos, and scratch buffer must
/// all be standard host memory allocations."
/// - "A pointer to a geometry info can be a null pointer, in which case
/// the geometry is treated as empty."
/// - "If no parallel operation handle is provided, the build is run
/// sequentially on the current thread."
/// - "A parallel operation object may only be associated with a single
/// acceleration structure build at a time."
///
/// @returns
/// - ::ZE_RESULT_SUCCESS
/// - ::ZE_RESULT_ERROR_UNINITIALIZED
/// - ::ZE_RESULT_ERROR_DEVICE_LOST
/// - ::ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY
/// - ::ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY
/// - ::ZE_RESULT_ERROR_INVALID_NULL_HANDLE
/// + `nullptr == hBuilder`
/// - ::ZE_RESULT_ERROR_INVALID_NULL_POINTER
/// + `nullptr == pBuildOpDescriptor`
/// + `nullptr == pScratchBuffer`
/// + `nullptr == pRtasBuffer`
/// - ::ZE_RESULT_ERROR_INVALID_ENUMERATION
/// + `::ZE_RTAS_FORMAT_EXP_INVALID < pBuildOpDescriptor->rtasFormat`
/// + `::ZE_RTAS_BUILDER_BUILD_QUALITY_HINT_EXP_HIGH < pBuildOpDescriptor->buildQuality`
/// + `0x3 < pBuildOpDescriptor->buildFlags`
/// - ::ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY
/// + Acceleration structure build failed due to insufficient resources
/// - ::ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE
/// + Acceleration structure build failed due to parallel operation object participation in another build operation.
ZE_APIEXPORT ze_result_t ZE_APICALL
zeRTASBuilderBuildExp(
ze_rtas_builder_exp_handle_t hBuilder, ///< [in] handle of builder object
const ze_rtas_builder_build_op_exp_desc_t* pBuildOpDescriptor, ///< [in] pointer to build operation descriptor
void* pScratchBuffer, ///< [in][range(0, `scratchBufferSizeBytes`)] scratch buffer to be used
///< during acceleration structure construction
size_t scratchBufferSizeBytes, ///< [in] size of scratch buffer, in bytes
void* pRtasBuffer, ///< [in] pointer to destination buffer
size_t rtasBufferSizeBytes, ///< [in] destination buffer size, in bytes
ze_rtas_parallel_operation_exp_handle_t hParallelOperation, ///< [in][optional] handle to parallel operation object
void* pBuildUserPtr, ///< [in][optional] pointer passed to callbacks
ze_rtas_aabb_exp_t* pBounds, ///< [in,out][optional] pointer to destination address for acceleration
///< structure bounds
size_t* pRtasBufferSizeBytes ///< [out][optional] updated acceleration structure size requirement, in
///< bytes
);
///////////////////////////////////////////////////////////////////////////////
/// @brief Destroys a ray tracing acceleration structure builder object
///
/// @details
/// - The application must destroy all the parallel operation handles
/// created from the builder before destroying the builder itself.
/// - The implementation of this function may immediately release any
/// internal Host and Device resources associated with this builder.
/// - The application must **not** call this function from simultaneous
/// threads with the same builder handle.
/// - The implementation of this function must be thread-safe.
///
/// @returns
/// - ::ZE_RESULT_SUCCESS
/// - ::ZE_RESULT_ERROR_UNINITIALIZED
/// - ::ZE_RESULT_ERROR_DEVICE_LOST
/// - ::ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY
/// - ::ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY
/// - ::ZE_RESULT_ERROR_INVALID_NULL_HANDLE
/// + `nullptr == hBuilder`
/// - ::ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE
ZE_APIEXPORT ze_result_t ZE_APICALL
zeRTASBuilderDestroyExp(
ze_rtas_builder_exp_handle_t hBuilder ///< [in][release] handle of builder object to destroy
);
///////////////////////////////////////////////////////////////////////////////
/// @brief Creates a ray tracing acceleration structure builder parallel
/// operation object
///
/// @details
/// - The application may call this function from simultaneous threads.
/// - The implementation of this function must be thread-safe.
/// - The implementation must support ::ZE_experimental_rtas_builder
/// extension.
///
/// @returns
/// - ::ZE_RESULT_SUCCESS
/// - ::ZE_RESULT_ERROR_UNINITIALIZED
/// - ::ZE_RESULT_ERROR_DEVICE_LOST
/// - ::ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY
/// - ::ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY
/// - ::ZE_RESULT_ERROR_INVALID_NULL_HANDLE
/// + `nullptr == hDriver`
/// - ::ZE_RESULT_ERROR_INVALID_NULL_POINTER
/// + `nullptr == phParallelOperation`
ZE_APIEXPORT ze_result_t ZE_APICALL
zeRTASParallelOperationCreateExp(
ze_driver_handle_t hDriver, ///< [in] handle of driver object
ze_rtas_parallel_operation_exp_handle_t* phParallelOperation///< [out] handle of parallel operation object
);
///////////////////////////////////////////////////////////////////////////////
/// @brief Retrieves ray tracing acceleration structure builder parallel
/// operation properties
///
/// @details
/// - The application may call this function from simultaneous threads.
/// - The implementation of this function must be thread-safe.
///
/// @returns
/// - ::ZE_RESULT_SUCCESS
/// - ::ZE_RESULT_ERROR_UNINITIALIZED
/// - ::ZE_RESULT_ERROR_DEVICE_LOST
/// - ::ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY
/// - ::ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY
/// - ::ZE_RESULT_ERROR_INVALID_NULL_HANDLE
/// + `nullptr == hParallelOperation`
/// - ::ZE_RESULT_ERROR_INVALID_NULL_POINTER
/// + `nullptr == pProperties`
ZE_APIEXPORT ze_result_t ZE_APICALL
zeRTASParallelOperationGetPropertiesExp(
ze_rtas_parallel_operation_exp_handle_t hParallelOperation, ///< [in] handle of parallel operation object
ze_rtas_parallel_operation_exp_properties_t* pProperties///< [in,out] query result for parallel operation properties
);
///////////////////////////////////////////////////////////////////////////////
/// @brief Joins a parallel build operation
///
/// @details
/// - All worker threads return the same error code for the parallel build
/// operation upon build completion
///
/// @returns
/// - ::ZE_RESULT_SUCCESS
/// - ::ZE_RESULT_ERROR_UNINITIALIZED
/// - ::ZE_RESULT_ERROR_DEVICE_LOST
/// - ::ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY
/// - ::ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY
/// - ::ZE_RESULT_ERROR_INVALID_NULL_HANDLE
/// + `nullptr == hParallelOperation`
ZE_APIEXPORT ze_result_t ZE_APICALL
zeRTASParallelOperationJoinExp(
ze_rtas_parallel_operation_exp_handle_t hParallelOperation ///< [in] handle of parallel operation object
);
///////////////////////////////////////////////////////////////////////////////
/// @brief Destroys a ray tracing acceleration structure builder parallel
/// operation object
///
/// @details
/// - The implementation of this function may immediately release any
/// internal Host and Device resources associated with this parallel
/// operation.
/// - The application must **not** call this function from simultaneous
/// threads with the same parallel operation handle.
/// - The implementation of this function must be thread-safe.
///
/// @returns
/// - ::ZE_RESULT_SUCCESS
/// - ::ZE_RESULT_ERROR_UNINITIALIZED
/// - ::ZE_RESULT_ERROR_DEVICE_LOST
/// - ::ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY
/// - ::ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY
/// - ::ZE_RESULT_ERROR_INVALID_NULL_HANDLE
/// + `nullptr == hParallelOperation`
ZE_APIEXPORT ze_result_t ZE_APICALL
zeRTASParallelOperationDestroyExp(
ze_rtas_parallel_operation_exp_handle_t hParallelOperation ///< [in][release] handle of parallel operation object to destroy
);
#if !defined(__GNUC__)
#pragma endregion
#endif
File diff suppressed because it is too large Load Diff
@@ -3,6 +3,10 @@
#pragma once
#if defined(EMBREE_SYCL_RT_VALIDATION_API)
# include "rttrace_validation.h"
#else
#include <cstdint>
#pragma clang diagnostic push
@@ -255,3 +259,4 @@ inline bool intel_has_committed_hit( intel_ray_query_t query ) { return false; }
#pragma clang diagnostic pop
#endif
@@ -1,8 +1,7 @@
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#include "rthwif_production.h"
#include "rthwif_internal.h"
#include "rttrace_validation.h"
#define sizeof_QBVH6_InternalNode6 64
#define QBVH6_rootNodeOffset 128
@@ -3,7 +3,7 @@
#pragma once
#include "rthwif_internal.h"
#include "rttrace_internal.h"
enum intel_ray_flags_t
{
+4 -27
View File
@@ -14,18 +14,6 @@ IF (NOT DEFINED EMBREE_SYCL_IMPLICIT_DISPATCH_GLOBALS)
OPTION(EMBREE_SYCL_IMPLICIT_DISPATCH_GLOBALS "Using L0 allocated Dispatch Globals" ON)
ENDIF()
IF (NOT EMBREE_SYCL_IMPLICIT_DISPATCH_GLOBALS)
ADD_DEFINITIONS("-DEMBREE_SYCL_ALLOC_DISPATCH_GLOBALS")
ENDIF()
#ADD_EXECUTABLE(rthwif_cornell_box rthwif_cornell_box.cpp ../rthwif_production.cpp)
#SET_PROPERTY(TARGET rthwif_cornell_box APPEND PROPERTY COMPILE_FLAGS "-fsycl -fsycl-targets=spir64 -DEMBREE_SYCL_SUPPORT")
#SET_PROPERTY(TARGET rthwif_cornell_box APPEND PROPERTY LINK_FLAGS "-fsycl -lze_loader")
#ADD_EXECUTABLE(rthwif_test rthwif_test.cpp ../rthwif_production.cpp)
#TARGET_LINK_LIBRARIES(rthwif_test embree_rthwif sys tbb)
#TARGET_LINK_LIBRARIES(rthwif_test embree_rthwif_gpu sys tbb)
IF (NOT DEFINED EMBREE_SYCL_RT_VALIDATION_API)
OPTION(EMBREE_SYCL_RT_VALIDATION_API "Use rt_validation API instead of IGC provided rt_production API" OFF)
ENDIF()
@@ -34,6 +22,10 @@ IF (EMBREE_SYCL_RT_VALIDATION_API)
ADD_DEFINITIONS("-DEMBREE_SYCL_RT_VALIDATION_API")
ENDIF()
IF (EMBREE_SYCL_RT_VALIDATION_API AND NOT EMBREE_SYCL_IMPLICIT_DISPATCH_GLOBALS)
ADD_DEFINITIONS("-DEMBREE_SYCL_ALLOC_DISPATCH_GLOBALS")
ENDIF()
IF (EMBREE_SYCL_RT_SIMULATION)
SET(RT_SIM_LIBRARY rtcore)
ENDIF()
@@ -43,21 +35,8 @@ TARGET_LINK_LIBRARIES(embree_rthwif_cornell_box embree_rthwif sys simd ${TBB_TAR
SET_PROPERTY(TARGET embree_rthwif_cornell_box APPEND PROPERTY COMPILE_FLAGS "-fsycl -fsycl-targets=spir64 -DEMBREE_SYCL_SUPPORT")
SET_PROPERTY(TARGET embree_rthwif_cornell_box APPEND PROPERTY LINK_FLAGS "-fsycl -lze_loader -fsycl-targets=spir64 -Xsycl-target-backend=spir64 \" -cl-intel-greater-than-4GB-buffer-required \"")
#ADD_EXECUTABLE(rthwif_test rthwif_test.cpp)
#TARGET_LINK_LIBRARIES(rthwif_test embree_rthwif sys simd tbb)
#IF (EMBREE_SYCL_GPU_BVH_BUILDER)
#TARGET_LINK_LIBRARIES(rthwif_test embree_rthwif_gpu sys tbb)
#ENDIF()
#SET_PROPERTY(TARGET rthwif_test APPEND PROPERTY COMPILE_FLAGS "-fsycl -fsycl-targets=spir64 -DEMBREE_SYCL_SUPPORT")
#SET_PROPERTY(TARGET rthwif_test APPEND PROPERTY LINK_FLAGS "-fsycl -lze_loader -fsycl-targets=spir64 -Xsycl-target-backend=spir64 \" -cl-intel-greater-than-4GB-buffer-required \"")
ADD_EXECUTABLE(embree_rthwif_test rthwif_test.cpp)
TARGET_LINK_LIBRARIES(embree_rthwif_test embree_rthwif sys simd ${TBB_TARGET} ${RT_SIM_LIBRARY})
IF (EMBREE_SYCL_GPU_BVH_BUILDER)
TARGET_LINK_LIBRARIES(embree_rthwif_test embree_rthwif_gpu sys tbb)
ENDIF()
SET_PROPERTY(TARGET embree_rthwif_test APPEND PROPERTY COMPILE_FLAGS "-fsycl -fsycl-targets=spir64 -DEMBREE_SYCL_SUPPORT")
SET_PROPERTY(TARGET embree_rthwif_test APPEND PROPERTY LINK_FLAGS "-fsycl -lze_loader -fsycl-targets=spir64 -Xsycl-target-backend=spir64 \" -cl-intel-greater-than-4GB-buffer-required \"")
@@ -72,7 +51,6 @@ IF (NOT DEFINED EMBREE_SYCL_RT_VALIDATION_API OR EMBREE_SYCL_IMPLICIT_DISPATCH_G
ADD_TEST(NAME rthwif_cornell_box
COMMAND embree_rthwif_cornell_box --compare "${CORNELL_BOX_REFERENCE}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
ENDIF()
ADD_TEST(NAME rthwif_test_builder_triangles_expected COMMAND embree_rthwif_test --build_test_triangles --build_mode_expected)
@@ -105,4 +83,3 @@ ADD_TEST(NAME rthwif_test_swinstancing_triangles_potential_hit COMMAND em
ADD_TEST(NAME rthwif_test_swinstancing_triangles_anyhit_shader_commit COMMAND embree_rthwif_test --sw-instancing --triangles-anyhit-shader-commit)
ADD_TEST(NAME rthwif_test_swinstancing_triangles_anyhit_shader_reject COMMAND embree_rthwif_test --sw-instancing --triangles-anyhit-shader-reject)
ADD_TEST(NAME rthwif_test_swinstancing_procedurals_committed_hit COMMAND embree_rthwif_test --sw-instancing --procedurals-committed-hit)
+257 -189
View File
@@ -2,23 +2,14 @@
// SPDX-License-Identifier: Apache-2.0
#include <CL/sycl.hpp>
#include "tbb/tbb.h"
#if defined(EMBREE_SYCL_RT_VALIDATION_API)
# include "../rttrace/rthwif_production.h"
#else
# include "../rttrace/rthwif_production_igc.h"
#endif
#include "../rtbuild/rthwif_builder.h"
#include <level_zero/ze_api.h>
#include "../rttrace/rttrace.h"
#include "../rtbuild/rtbuild.h"
#include <vector>
#include <iostream>
#if !defined(_unused)
#define _unused(x) ((void)(x))
#endif
void exception_handler(sycl::exception_list exceptions)
{
for (std::exception_ptr const& e : exceptions) {
@@ -93,13 +84,19 @@ bool compareTga(const std::string& fileNameA, const std::string& fileNameB)
return dataA == dataB;
}
/* Properly allocates an acceleration structure buffer using ze_raytracing_mem_alloc_ext_desc_t property. */
void* alloc_accel_buffer(size_t bytes, sycl::device device, sycl::context context)
{
ze_context_handle_t hContext = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(context);
ze_device_handle_t hDevice = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(device);
ze_rtas_device_exp_properties_t rtasProp = { ZE_STRUCTURE_TYPE_RTAS_DEVICE_EXP_PROPERTIES };
ze_result_t err = zeDeviceGetRTASPropertiesExp(hDevice, &rtasProp );
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("get rtas device properties failed");
ze_raytracing_mem_alloc_ext_desc_t rt_desc;
rt_desc.stype = ZE_STRUCTURE_TYPE_DEVICE_RAYTRACING_EXT_PROPERTIES;
rt_desc.stype = ZE_STRUCTURE_TYPE_RAYTRACING_MEM_ALLOC_EXT_DESC;
rt_desc.pNext = nullptr;
rt_desc.flags = 0;
@@ -115,9 +112,10 @@ void* alloc_accel_buffer(size_t bytes, sycl::device device, sycl::context contex
host_desc.flags = ZE_HOST_MEM_ALLOC_FLAG_BIAS_CACHED;
void* ptr = nullptr;
ze_result_t result = zeMemAllocShared(hContext,&device_desc,&host_desc,bytes,RTHWIF_ACCELERATION_STRUCTURE_ALIGNMENT,hDevice,&ptr);
assert(result == ZE_RESULT_SUCCESS);
_unused(result);
ze_result_t result = zeMemAllocShared(hContext,&device_desc,&host_desc,bytes,rtasProp.rtasBufferAlignment,hDevice,&ptr);
if (result != ZE_RESULT_SUCCESS)
throw std::runtime_error("acceleration buffer allocation failed");
return ptr;
}
@@ -125,173 +123,237 @@ void free_accel_buffer(void* ptr, sycl::context context)
{
ze_context_handle_t hContext = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(context);
ze_result_t result = zeMemFree(hContext,ptr);
assert(result == ZE_RESULT_SUCCESS);
_unused(result);
if (result != ZE_RESULT_SUCCESS)
throw std::runtime_error("acceleration buffer free failed");
}
#define bvh_bytes 4992
const unsigned char bvh_data[bvh_bytes] = {
0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x44,0x33,0x33,0x09,0x44,0xcd,0xcc,0x0b,0x44,
0x02,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x4e,0x00,0x00,0x00,0x4e,0x00,0x00,0x00,0x4e,0x00,0x00,0x00,0x4e,0x00,0x00,0x00,
0x06,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0xce,0x74,0x2f,0x7f,0x00,0x00,
0xcd,0xcc,0x8b,0xb8,0xcd,0xcc,0x8b,0xb8,0xcd,0xcc,0x8b,0xb8,0x01,0x00,0x00,0x00,0x00,0x00,0x0a,0x0a,0x0a,0xff,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x89,0x42,0x00,
0x42,0x14,0x8c,0x8c,0x6a,0x8c,0x77,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x8a,0x8a,0x53,0x8a,0x53,0x2a,0x8b,0x00,0x3d,0x00,0x3d,0x10,0x8c,0x8c,0x4b,0x8c,0x73,0x45,
0xcd,0xcc,0x8b,0xb8,0xcd,0xcc,0x8b,0xb8,0xcc,0xcc,0x0b,0x44,0x1a,0x00,0x00,0x00,0x04,0x00,0x0a,0x0a,0xf4,0xff,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,
0x80,0x80,0x8c,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x8a,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,
0x65,0x66,0x09,0x44,0xcd,0xcc,0x8b,0xb8,0xcd,0xcc,0x8b,0xb8,0x1b,0x00,0x00,0x00,0x04,0x00,0x03,0x0a,0x0a,0xff,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x66,0x80,0x80,
0x80,0x80,0xcd,0xcd,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x8a,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x8c,0x8c,0x00,0x00,0x00,0x00,
0xfe,0x7f,0x84,0x43,0x00,0x80,0x53,0xb8,0xfd,0xff,0x76,0x43,0x1c,0x00,0x00,0x00,0x04,0x00,0x08,0x09,0x06,0xff,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,
0x80,0x80,0x9f,0x9f,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0xa6,0xa6,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0xc5,0xc5,0x00,0x00,0x00,0x00,
0xcd,0xcc,0x8b,0xb8,0xcd,0xcc,0x8b,0xb8,0xcd,0xcc,0x8b,0xb8,0x1d,0x00,0x00,0x00,0x04,0x00,0x0a,0x0a,0x0a,0xff,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x8c,0x8c,0x8b,0x8b,0x01,0x01,0x89,0x89,0x00,0x00,0x00,0x00,0x8a,0x8a,0x01,0x01,0x8a,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,
0xfe,0x7f,0x84,0x43,0x00,0x00,0x6c,0xb8,0xfc,0xff,0x76,0x43,0x02,0x00,0x00,0x00,0x00,0x00,0x08,0x09,0x08,0xff,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x31,0x80,0x80,
0x80,0x80,0xd0,0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0xa6,0xa6,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0xd2,0xd2,0x00,0x00,0x00,0x00,
0xfb,0xff,0xa3,0x42,0x00,0x00,0x11,0xb8,0xfb,0xff,0x81,0x42,0x03,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x08,0xff,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x30,0x80,
0x80,0x80,0x9f,0xd1,0xd1,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0xa6,0xa6,0xa6,0x00,0x00,0x00,0xa0,0x00,0x00,0x80,0x80,0x80,0xd0,0xd0,0xd0,0x00,0x00,0x00,
0xfe,0x7f,0x84,0x43,0x00,0x00,0x6c,0xb8,0xfc,0xff,0x76,0x43,0x20,0x00,0x00,0x00,0x04,0x00,0x08,0x09,0x08,0xff,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
0x00,0x80,0x32,0x32,0xd0,0x9f,0xd0,0x00,0x00,0x00,0x00,0xa5,0x00,0x80,0xa6,0xa6,0x01,0xa6,0x01,0x00,0x31,0x31,0x31,0x00,0x00,0x80,0xd2,0xd2,0xd2,0xd2,0xa0,0x00,
0xfe,0xff,0x9c,0x43,0x00,0x00,0x6c,0xb8,0xfc,0xff,0x76,0x43,0x24,0x00,0x00,0x00,0x04,0x00,0x08,0x09,0x08,0xff,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x6d,0x6d,
0x00,0x80,0x9f,0x9f,0x9f,0x9f,0x9f,0x00,0x00,0x00,0x00,0x00,0xa5,0x80,0xa6,0xa6,0xa6,0xa6,0xa6,0x00,0x9f,0x9f,0x00,0x00,0x00,0x80,0xd2,0xd2,0xa0,0xa0,0xd2,0x00,
0xfc,0xff,0xa3,0x42,0x00,0x00,0x08,0xb8,0xfe,0xff,0x60,0x43,0x28,0x00,0x00,0x00,0x04,0x00,0x08,0x08,0x06,0xff,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,
0x80,0x80,0x9f,0x9f,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0xa6,0xa6,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0xbd,0xbd,0x00,0x00,0x00,0x00,
0xfb,0xff,0xa3,0x42,0x00,0x00,0x11,0xb8,0xfb,0xff,0x81,0x42,0x29,0x00,0x00,0x00,0x04,0x00,0x08,0x08,0x08,0xff,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
0x00,0x80,0x31,0x31,0xd1,0xd1,0x9f,0x00,0x00,0x00,0x00,0x00,0xa5,0x80,0xa6,0xa6,0x01,0x01,0xa6,0x00,0x00,0x00,0x00,0x31,0x00,0x80,0xa1,0xa1,0xa1,0xd0,0xd0,0x00,
0xfe,0xff,0x01,0x43,0x00,0x00,0x11,0xb8,0xfb,0xff,0x81,0x42,0x2d,0x00,0x00,0x00,0x04,0x00,0x08,0x08,0x08,0xff,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x6e,0x6e,
0x00,0x80,0xa1,0xa1,0xa1,0xa1,0xa1,0x00,0x00,0x00,0x00,0x00,0xa5,0x80,0xa6,0xa6,0xa6,0xa6,0xa6,0x00,0x00,0x00,0x31,0x31,0x00,0x80,0x32,0x32,0xd0,0xd0,0xd0,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x02,0x00,0x00,0xff,0x02,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x66,0x66,0x09,0x44,0x00,0x00,0x00,0x00,0xcd,0xcc,0x0b,0x44,0x00,0x00,0x00,0x00,
0x33,0x33,0x09,0x44,0xcd,0xcc,0x0b,0x44,0x00,0x00,0x0b,0x44,0x33,0x33,0x09,0x44,0xcd,0xcc,0x0b,0x44,0x00,0x00,0x0b,0x44,0x33,0x33,0x09,0x44,0xcd,0xcc,0x0b,0x44,
0x02,0x00,0x00,0xff,0x02,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x66,0x66,0x09,0x44,0x00,0x00,0x00,0x00,0xcd,0xcc,0x0b,0x44,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xcd,0xcc,0x0b,0x44,0x00,0x00,0x00,0x00,0x33,0x33,0x09,0x44,0xcd,0xcc,0x0b,0x44,0x00,0x00,0x00,0x00,0x33,0x33,0x09,0x44,0xcd,0xcc,0x0b,0x44,
0x04,0x00,0x00,0xff,0x04,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x33,0x33,0x0a,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x09,0x44,
0x00,0x00,0x00,0x00,0xcd,0xcc,0x0b,0x44,0x00,0x00,0x0b,0x44,0x33,0x33,0x09,0x44,0xcd,0xcc,0x0b,0x44,0x00,0x00,0x0b,0x44,0x33,0x33,0x09,0x44,0xcd,0xcc,0x0b,0x44,
0x04,0x00,0x00,0xff,0x04,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x33,0x33,0x0a,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x44,
0x33,0x33,0x09,0x44,0xcd,0xcc,0x0b,0x44,0x00,0x00,0x0b,0x44,0x33,0x33,0x09,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x44,0x33,0x33,0x09,0x44,0x00,0x00,0x00,0x00,
0x07,0x00,0x00,0xff,0x07,0x00,0x00,0x40,0x07,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x80,0x84,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x43,0x00,0x80,0xd3,0x43,
0x00,0x00,0xa5,0x43,0x00,0x00,0x77,0x43,0x00,0x80,0xd3,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x77,0x43,0x00,0x80,0xd3,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x77,0x43,
0x07,0x00,0x00,0xff,0x07,0x00,0x00,0x40,0x06,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x80,0x84,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x43,0x00,0x80,0x84,0x43,
0x00,0x00,0xa5,0x43,0x00,0x00,0x94,0x43,0x00,0x80,0xd3,0x43,0x00,0x00,0xa5,0x43,0x00,0x00,0x77,0x43,0x00,0x80,0xd3,0x43,0x00,0x00,0xa5,0x43,0x00,0x00,0x77,0x43,
0x01,0x00,0x00,0xff,0x01,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x0b,0x44,0x33,0x33,0x09,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x33,0x33,0x09,0x44,0xcd,0xcc,0x0b,0x44,0x00,0x00,0x00,0x00,0x33,0x33,0x09,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x33,0x09,0x44,0x00,0x00,0x00,0x00,
0x01,0x00,0x00,0xff,0x01,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x0b,0x44,0x33,0x33,0x09,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x44,
0x33,0x33,0x09,0x44,0xcd,0xcc,0x0b,0x44,0x00,0x00,0x00,0x00,0x33,0x33,0x09,0x44,0xcd,0xcc,0x0b,0x44,0x00,0x00,0x00,0x00,0x33,0x33,0x09,0x44,0xcd,0xcc,0x0b,0x44,
0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x33,0x33,0x0a,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcd,0xcc,0x0b,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcd,0xcc,0x0b,0x44,
0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x33,0x33,0x0a,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xcd,0xcc,0x0b,0x44,0x66,0x66,0x09,0x44,0x00,0x00,0x00,0x00,0xcd,0xcc,0x0b,0x44,0x66,0x66,0x09,0x44,0x00,0x00,0x00,0x00,0xcd,0xcc,0x0b,0x44,
0x03,0x00,0x00,0xff,0x03,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcd,0xcc,0x0b,0x44,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x33,0x09,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x33,0x09,0x44,0x00,0x00,0x00,0x00,
0x03,0x00,0x00,0xff,0x03,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcd,0xcc,0x0b,0x44,0x00,0x00,0x00,0x00,
0x33,0x33,0x09,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x33,0x09,0x44,0xcd,0xcc,0x0b,0x44,0x00,0x00,0x00,0x00,0x33,0x33,0x09,0x44,0xcd,0xcc,0x0b,0x44,
0x07,0x00,0x00,0xff,0x07,0x00,0x00,0x40,0x05,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x9d,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x43,0x00,0x80,0x84,0x43,
0x00,0x00,0xa5,0x43,0x00,0x00,0x94,0x43,0x00,0x80,0x84,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x43,0x00,0x80,0x84,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x43,
0x07,0x00,0x00,0xff,0x07,0x00,0x00,0x40,0x04,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x9d,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x43,0x00,0x00,0x9d,0x43,
0x00,0x00,0xa5,0x43,0x00,0x00,0xe4,0x43,0x00,0x80,0x84,0x43,0x00,0x00,0xa5,0x43,0x00,0x00,0x94,0x43,0x00,0x80,0x84,0x43,0x00,0x00,0xa5,0x43,0x00,0x00,0x94,0x43,
0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x40,0x04,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0xec,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xcb,0x43,0x00,0x00,0x9d,0x43,
0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x43,0x00,0x80,0x84,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x43,0x00,0x80,0x84,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x43,
0x06,0x00,0x00,0xff,0x06,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x80,0xd3,0x43,0x00,0x00,0xa5,0x43,0x00,0x00,0x77,0x43,0x00,0x80,0x84,0x43,
0x00,0x00,0xa5,0x43,0x00,0x00,0x94,0x43,0x00,0x00,0x9d,0x43,0x00,0x00,0xa5,0x43,0x00,0x00,0xe4,0x43,0x00,0x00,0x9d,0x43,0x00,0x00,0xa5,0x43,0x00,0x00,0xe4,0x43,
0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x40,0x05,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0xec,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xcb,0x43,0x00,0x80,0x84,0x43,
0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x43,0x00,0x80,0xd3,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x77,0x43,0x00,0x80,0xd3,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x77,0x43,
0x07,0x00,0x00,0xff,0x07,0x00,0x00,0x40,0x02,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0xec,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xcb,0x43,0x00,0x00,0xec,0x43,
0x00,0x00,0xa5,0x43,0x00,0x00,0xcb,0x43,0x00,0x00,0x9d,0x43,0x00,0x00,0xa5,0x43,0x00,0x00,0xe4,0x43,0x00,0x00,0x9d,0x43,0x00,0x00,0xa5,0x43,0x00,0x00,0xe4,0x43,
0x07,0x00,0x00,0xff,0x07,0x00,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0xec,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xcb,0x43,0x00,0x00,0x9d,0x43,
0x00,0x00,0xa5,0x43,0x00,0x00,0xe4,0x43,0x00,0x00,0x9d,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x43,0x00,0x00,0x9d,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x43,
0x07,0x00,0x00,0xff,0x07,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x80,0xd3,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x77,0x43,0x00,0x80,0xd3,0x43,
0x00,0x00,0xa5,0x43,0x00,0x00,0x77,0x43,0x00,0x00,0xec,0x43,0x00,0x00,0xa5,0x43,0x00,0x00,0xcb,0x43,0x00,0x00,0xec,0x43,0x00,0x00,0xa5,0x43,0x00,0x00,0xcb,0x43,
0x07,0x00,0x00,0xff,0x07,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x80,0xd3,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x77,0x43,0x00,0x00,0xec,0x43,
0x00,0x00,0xa5,0x43,0x00,0x00,0xcb,0x43,0x00,0x00,0xec,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xcb,0x43,0x00,0x00,0xec,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xcb,0x43,
0x06,0x00,0x00,0xff,0x06,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x80,0xd3,0x43,0x00,0x00,0xa5,0x43,0x00,0x00,0x77,0x43,0x00,0x00,0x9d,0x43,
0x00,0x00,0xa5,0x43,0x00,0x00,0xe4,0x43,0x00,0x00,0xec,0x43,0x00,0x00,0xa5,0x43,0x00,0x00,0xcb,0x43,0x00,0x00,0xec,0x43,0x00,0x00,0xa5,0x43,0x00,0x00,0xcb,0x43,
0x05,0x00,0x00,0xff,0x05,0x00,0x00,0x40,0x08,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x70,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x43,0x00,0x00,0x70,0x43,
0x00,0x00,0x25,0x43,0x00,0x00,0x88,0x43,0x00,0x00,0xa4,0x42,0x00,0x00,0x25,0x43,0x00,0x00,0x61,0x43,0x00,0x00,0xa4,0x42,0x00,0x00,0x25,0x43,0x00,0x00,0x61,0x43,
0x05,0x00,0x00,0xff,0x05,0x00,0x00,0x40,0x09,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x70,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x43,0x00,0x00,0xa4,0x42,
0x00,0x00,0x25,0x43,0x00,0x00,0x61,0x43,0x00,0x00,0xa4,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x43,0x00,0x00,0xa4,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x43,
0x05,0x00,0x00,0xff,0x05,0x00,0x00,0x40,0x06,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0xa4,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x43,0x00,0x00,0xa4,0x42,
0x00,0x00,0x25,0x43,0x00,0x00,0x61,0x43,0x00,0x00,0x02,0x43,0x00,0x00,0x25,0x43,0x00,0x00,0x82,0x42,0x00,0x00,0x02,0x43,0x00,0x00,0x25,0x43,0x00,0x00,0x82,0x42,
0x05,0x00,0x00,0xff,0x05,0x00,0x00,0x40,0x07,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0xa4,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x43,0x00,0x00,0x02,0x43,
0x00,0x00,0x25,0x43,0x00,0x00,0x82,0x42,0x00,0x00,0x02,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x42,0x00,0x00,0x02,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x42,
0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x91,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x42,0x00,0x00,0xa4,0x42,
0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x43,0x00,0x00,0x02,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x42,0x00,0x00,0x02,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x42,
0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x40,0x02,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x91,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x42,0x00,0x00,0x70,0x43,
0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x43,0x00,0x00,0xa4,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x43,0x00,0x00,0xa4,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x43,
0x05,0x00,0x00,0xff,0x05,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x43,0x00,0x00,0x25,0x43,0x00,0x00,0x82,0x42,0x00,0x00,0xa4,0x42,
0x00,0x00,0x25,0x43,0x00,0x00,0x61,0x43,0x00,0x00,0x70,0x43,0x00,0x00,0x25,0x43,0x00,0x00,0x88,0x43,0x00,0x00,0x70,0x43,0x00,0x00,0x25,0x43,0x00,0x00,0x88,0x43,
0x05,0x00,0x00,0xff,0x05,0x00,0x00,0x40,0x05,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x42,0x00,0x00,0x91,0x43,
0x00,0x00,0x25,0x43,0x00,0x00,0xe4,0x42,0x00,0x00,0x91,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x42,0x00,0x00,0x91,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x42,
0x05,0x00,0x00,0xff,0x05,0x00,0x00,0x40,0x04,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x42,0x00,0x00,0x02,0x43,
0x00,0x00,0x25,0x43,0x00,0x00,0x82,0x42,0x00,0x00,0x91,0x43,0x00,0x00,0x25,0x43,0x00,0x00,0xe4,0x42,0x00,0x00,0x91,0x43,0x00,0x00,0x25,0x43,0x00,0x00,0xe4,0x42,
0x05,0x00,0x00,0xff,0x05,0x00,0x00,0x40,0x02,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x91,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x42,0x00,0x00,0x91,0x43,
0x00,0x00,0x25,0x43,0x00,0x00,0xe4,0x42,0x00,0x00,0x70,0x43,0x00,0x00,0x25,0x43,0x00,0x00,0x88,0x43,0x00,0x00,0x70,0x43,0x00,0x00,0x25,0x43,0x00,0x00,0x88,0x43,
0x05,0x00,0x00,0xff,0x05,0x00,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x91,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x42,0x00,0x00,0x70,0x43,
0x00,0x00,0x25,0x43,0x00,0x00,0x88,0x43,0x00,0x00,0x70,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x43,0x00,0x00,0x70,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x43,
0x05,0x00,0x00,0xff,0x05,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x43,0x00,0x00,0x25,0x43,0x00,0x00,0x82,0x42,0x00,0x00,0x70,0x43,
0x00,0x00,0x25,0x43,0x00,0x00,0x88,0x43,0x00,0x00,0x91,0x43,0x00,0x00,0x25,0x43,0x00,0x00,0xe4,0x42,0x00,0x00,0x91,0x43,0x00,0x00,0x25,0x43,0x00,0x00,0xe4,0x42,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
/* vertex indices for cornell_box model */
ze_rtas_triangle_indices_uint32_exp_t indices[] = {
{ 0, 1, 2 },
{ 0, 2, 3 },
{ 4, 5, 6 },
{ 4, 6, 7 },
{ 8, 9, 10 },
{ 8, 10, 11 },
{ 12, 13, 14 },
{ 12, 14, 15 },
{ 16, 17, 18 },
{ 16, 18, 19 },
{ 20, 21, 22 },
{ 20, 22, 23 },
{ 24, 25, 26 },
{ 24, 26, 27 },
{ 28, 29, 30 },
{ 28, 30, 31 },
{ 32, 33, 34 },
{ 32, 34, 35 },
{ 36, 37, 38 },
{ 36, 38, 39 },
{ 40, 41, 42 },
{ 40, 42, 43 },
{ 44, 45, 46 },
{ 44, 46, 47 },
{ 48, 49, 50 },
{ 48, 50, 51 },
{ 52, 53, 54 },
{ 52, 54, 55 },
{ 56, 57, 58 },
{ 56, 58, 59 },
{ 60, 61, 62 },
{ 60, 62, 63 },
{ 64, 65, 66 },
{ 64, 66, 67 }
};
/* vertex positions for cornell_box model */
ze_rtas_float3_exp_t vertices[] = {
{ 552.8, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 559.2 },
{ 549.6, 0, 559.2 },
{ 290, 0, 114 },
{ 240, 0, 272 },
{ 82, 0, 225 },
{ 130, 0, 65 },
{ 472, 0, 406 },
{ 314, 0, 456 },
{ 265, 0, 296 },
{ 423, 0, 247 },
{ 556, 548.8, 0 },
{ 556, 548.8, 559.2 },
{ 0, 548.8, 559.2 },
{ 0, 548.8, 0 },
{ 549.6, 0, 559.2 },
{ 0, 0, 559.2 },
{ 0, 548.8, 559.2 },
{ 556, 548.8, 559.2 },
{ 0, 0, 559.2 },
{ 0, 0, 0 },
{ 0, 548.8, 0 },
{ 0, 548.8, 559.2 },
{ 552.8, 0, 0 },
{ 549.6, 0, 559.2 },
{ 556, 548.8, 559.2 },
{ 556, 548.8, 0 },
{ 130, 165, 65 },
{ 82, 165, 225 },
{ 240, 165, 272 },
{ 290, 165, 114 },
{ 290, 0, 114 },
{ 290, 165, 114 },
{ 240, 165, 272 },
{ 240, 0, 272 },
{ 130, 0, 65 },
{ 130, 165, 65 },
{ 290, 165, 114 },
{ 290, 0, 114 },
{ 82, 0, 225 },
{ 82, 165, 225 },
{ 130, 165, 65 },
{ 130, 0, 65 },
{ 240, 0, 272 },
{ 240, 165, 272 },
{ 82, 165, 225 },
{ 82, 0, 225 },
{ 423, 330, 247 },
{ 265, 330, 296 },
{ 314, 330, 456 },
{ 472, 330, 406 },
{ 423, 0, 247 },
{ 423, 330, 247 },
{ 472, 330, 406 },
{ 472, 0, 406 },
{ 472, 0, 406 },
{ 472, 330, 406 },
{ 314, 330, 456 },
{ 314, 0, 456 },
{ 314, 0, 456 },
{ 314, 330, 456 },
{ 265, 330, 296 },
{ 265, 0, 296 },
{ 265, 0, 296 },
{ 265, 330, 296 },
{ 423, 330, 247 },
{ 423, 0, 247 },
};
/* builds acceleration structure */
void* build_rtas(sycl::device device, sycl::context context)
{
/* get L0 handles */
ze_driver_handle_t hDriver = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(device.get_platform());
ze_device_handle_t hDevice = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(device);
/* create rtas builder object */
ze_rtas_builder_exp_desc_t builderDesc = { ZE_STRUCTURE_TYPE_RTAS_BUILDER_EXP_DESC };
ze_rtas_builder_exp_handle_t hBuilder = nullptr;
ze_result_t err = zeRTASBuilderCreateExp(hDriver, &builderDesc, &hBuilder);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("ze_rtas_builder creation failed");
/* create geometry descriptor for single triangle mesh */
ze_rtas_builder_triangles_geometry_info_exp_t mesh = {};
mesh.geometryType = ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_TRIANGLES;
mesh.geometryFlags = 0;
mesh.geometryMask = 0xFF;
mesh.triangleFormat = ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_TRIANGLE_INDICES_UINT32;
mesh.triangleCount = sizeof(indices)/sizeof(ze_rtas_triangle_indices_uint32_exp_t);
mesh.triangleStride = sizeof(ze_rtas_triangle_indices_uint32_exp_t);
mesh.pTriangleBuffer = indices;
mesh.vertexFormat = ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3;
mesh.vertexCount = sizeof(vertices)/sizeof(ze_rtas_float3_exp_t);
mesh.vertexStride = sizeof(ze_rtas_float3_exp_t);
mesh.pVertexBuffer = vertices;
/* fill geometry descriptor array with pointer to single geometry descriptor */
std::vector<ze_rtas_builder_geometry_info_exp_t*> descs;
descs.push_back((ze_rtas_builder_geometry_info_exp_t*)&mesh);
/* get acceleration structure format for this device */
ze_rtas_device_exp_properties_t rtasProp = { ZE_STRUCTURE_TYPE_RTAS_DEVICE_EXP_PROPERTIES };
err = zeDeviceGetRTASPropertiesExp(hDevice, &rtasProp );
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("get rtas device properties failed");
/* create parallel operation for parallel build */
ze_rtas_parallel_operation_exp_handle_t hParallelOperation = nullptr;
err = zeRTASParallelOperationCreateExp(hDriver, &hParallelOperation);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("zeRTASParallelOperationCreateExp failed");
/* create descriptor of build operation */
size_t accelBufferBytesOut = 0;
ze_rtas_aabb_exp_t bounds;
ze_rtas_builder_build_op_exp_desc_t buildOp = {};
buildOp.stype = ZE_STRUCTURE_TYPE_RTAS_BUILDER_BUILD_OP_EXP_DESC;
buildOp.pNext = nullptr;
buildOp.rtasFormat = rtasProp.rtasFormat;
buildOp.buildQuality = ZE_RTAS_BUILDER_BUILD_QUALITY_HINT_EXP_MEDIUM;
buildOp.buildFlags = 0;
buildOp.ppGeometries = (const ze_rtas_builder_geometry_info_exp_t **) descs.data();
buildOp.numGeometries = descs.size();
#if defined(EMBREE_SYCL_ALLOC_DISPATCH_GLOBALS)
buildOp.dispatchGlobalsPtr = dispatchGlobalsPtr;
#endif
/* query required buffer sizes */
ze_rtas_builder_exp_properties_t buildProps = { ZE_STRUCTURE_TYPE_RTAS_BUILDER_EXP_PROPERTIES };
err = zeRTASBuilderGetBuildPropertiesExp(hBuilder,&buildOp,&buildProps);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("zeRTASBuilderGetBuildPropertiesExp failed");
/* allocate scratch buffer */
std::vector<char> scratchBuffer(buildProps.scratchBufferSizeBytes);
memset(scratchBuffer.data(),0,scratchBuffer.size());
/* allocate acceleration structure buffer */
size_t accelBytes = buildProps.rtasBufferSizeBytesMaxRequired;
void* accel = alloc_accel_buffer(accelBytes,device,context);
memset(accel,0,accelBytes); // optional
/* build acceleration strucuture multi threaded */
err = zeRTASBuilderBuildExp(hBuilder,&buildOp,
scratchBuffer.data(),scratchBuffer.size(),
accel, accelBytes,
hParallelOperation,
nullptr, &bounds, &accelBufferBytesOut);
if (err != ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE)
throw std::runtime_error("zeRTASBuilderBuildExp failed");
/* after the build is started one can query number of threads to use for the build */
ze_rtas_parallel_operation_exp_properties_t prop = { ZE_STRUCTURE_TYPE_RTAS_PARALLEL_OPERATION_EXP_PROPERTIES };
err = zeRTASParallelOperationGetPropertiesExp(hParallelOperation,&prop);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("zeRTASParallelOperationGetPropertiesExp failed");
/* build in parallel using maximal number of build threads */
tbb::parallel_for(0u, prop.maxConcurrency, 1u, [&](uint32_t) {
err = zeRTASParallelOperationJoinExp(hParallelOperation);
});
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("zeRTASParallelOperationJoinExp failed");
/* destroy parallel operation again */
err = zeRTASParallelOperationDestroyExp(hParallelOperation);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("zeRTASParallelOperationDestroyExp failed");
/* destroy rtas builder again */
err = zeRTASBuilderDestroyExp(hBuilder);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("zeRTASBuilderDestroyExp failed");
return accel;
}
/* render using simple UV shading */
void render(unsigned int x, unsigned int y, void* bvh, unsigned int* pixels, unsigned int width, unsigned int height)
{
/* write zero image if ray tracing extension is not supported */
intel_raytracing_ext_flag_t flags = intel_get_raytracing_ext_flag();
if (!(flags & intel_raytracing_ext_flag_ray_query)) {
pixels[y*width+x] = 0;
@@ -337,29 +399,29 @@ void render(unsigned int x, unsigned int y, void* bvh, unsigned int* pixels, uns
int main(int argc, char* argv[])
{
/* use can specify reference image to compare against */
char* reference_img = NULL;
if (argc > 2 && std::string(argv[1]) == std::string("--compare"))
{
reference_img = argv[2];
}
else
{
reference_img = (char*)"cornell_box_reference.tga";
}
/* create SYCL objects */
sycl::device device = sycl::device(sycl::gpu_selector_v);
sycl::queue queue = sycl::queue(device,exception_handler);
sycl::context context = queue.get_context();
void* bvh = alloc_accel_buffer(bvh_bytes,device,context);
memcpy(bvh, bvh_data, bvh_bytes);
/* initialize L0 ray tracing extension */
zeRTASInitExp();
/* build acceleration structure */
void* bvh = build_rtas(device,context);
/* creates framebuffer */
static const int width = 512;
static const int height = 512;
unsigned int* pixels = (unsigned int*) sycl::aligned_alloc(64,width*height*sizeof(unsigned int),device,context,sycl::usm::alloc::shared);
memset(pixels, 0, width*height*sizeof(uint32_t));
for (int i=0; i<10; i++) {
/* renders image on device */
queue.submit([&](sycl::handler& cgh) {
const sycl::range<2> range(width,height);
cgh.parallel_for(range, [=](sycl::item<2> item) {
@@ -369,13 +431,19 @@ int main(int argc, char* argv[])
});
});
queue.wait_and_throw();
}
/* free acceleration structure again */
free_accel_buffer(bvh,context);
storeTga(pixels,width,height,"cornell_box.tga");
const bool ok = compareTga("cornell_box.tga", reference_img);
/* cleanup L0 ray tracing extension */
zeRTASExitExp();
/* store image to disk */
storeTga(pixels,width,height,"cornell_box.tga");
if (!reference_img) return 0;
/* compare to reference image */
const bool ok = compareTga("cornell_box.tga", reference_img);
std::cout << "cornell_box ";
if (ok) std::cout << "[PASSED]" << std::endl;
else std::cout << "[FAILED]" << std::endl;
+234 -225
View File
@@ -13,22 +13,13 @@
#define _USE_MATH_DEFINES
#include <math.h>
#if defined(EMBREE_SYCL_RT_VALIDATION_API)
# include "../rttrace/rthwif_production.h"
#else
# include "../rttrace/rthwif_production_igc.h"
#endif
#include "../rtbuild/rthwif_builder.h"
#include <level_zero/ze_api.h>
#include "../rttrace/rttrace.h"
#include "../rtbuild/rtbuild.h"
#include <vector>
#include <map>
#include <iostream>
#define VERBOSE 0
namespace embree {
double getSeconds();
}
@@ -150,7 +141,8 @@ sycl::float3 RandomSampler_getFloat3(RandomSampler& self)
RandomSampler rng;
volatile RTHWIF_PARALLEL_OPERATION parallelOperation = nullptr;
ze_rtas_builder_exp_handle_t hBuilder = nullptr;
ze_rtas_parallel_operation_exp_handle_t parallelOperation = nullptr;
enum class InstancingType
{
@@ -418,7 +410,7 @@ struct Bounds3f
return { sycl::float3(INFINITY), sycl::float3(-INFINITY) };
}
operator RTHWIF_AABB () const {
operator ze_rtas_aabb_exp_t () const {
return { { lower.x(), lower.y(), lower.z() }, { upper.x(), upper.y(), upper.z() } };
}
@@ -503,17 +495,17 @@ struct Hit
};
struct GEOMETRY_INSTANCE_DESC : RTHWIF_GEOMETRY_INSTANCE_DESC
struct GEOMETRY_INSTANCE_DESC : ze_rtas_builder_instance_geometry_info_exp_t
{
RTHWIF_TRANSFORM_FLOAT4X4_COLUMN_MAJOR xfmdata;
ze_rtas_transform_float3x4_aligned_column_major_exp_t xfmdata;
};
typedef union GEOMETRY_DESC
{
RTHWIF_GEOMETRY_TYPE geometryType;
RTHWIF_GEOMETRY_TRIANGLES_DESC Triangles;
RTHWIF_GEOMETRY_QUADS_DESC Quads;
RTHWIF_GEOMETRY_AABBS_FPTR_DESC AABBs;
ze_rtas_builder_geometry_type_exp_t geometryType;
ze_rtas_builder_triangles_geometry_info_exp_t Triangles;
ze_rtas_builder_quads_geometry_info_exp_t Quads;
ze_rtas_builder_procedural_geometry_info_exp_t AABBs;
GEOMETRY_INSTANCE_DESC Instance;
} GEOMETRY_DESC;
@@ -534,7 +526,7 @@ struct Geometry
throw std::runtime_error("Geometry::transform not implemented");
}
virtual void buildAccel(sycl::device& device, sycl::context& context, BuildMode buildMode, RTHWIF_BUILD_QUALITY quality) {
virtual void buildAccel(sycl::device& device, sycl::context& context, BuildMode buildMode, ze_rtas_builder_build_quality_hint_exp_t quality) {
};
virtual void buildTriMap(Transform local_to_world, std::vector<uint32_t> id_stack, uint32_t instUserID, bool procedural_instance, std::vector<Hit>& tri_map) = 0;
@@ -548,7 +540,7 @@ struct TriangleMesh : public Geometry
{
public:
TriangleMesh (RTHWIF_GEOMETRY_FLAGS gflags = RTHWIF_GEOMETRY_FLAG_OPAQUE, bool procedural = false)
TriangleMesh (ze_rtas_builder_geometry_exp_flags_t gflags = 0, bool procedural = false)
: Geometry(Type::TRIANGLE_MESH),
gflags(gflags), procedural(procedural),
triangles_alloc(context,device,sycl::ext::oneapi::property::usm::device_read_only()), triangles(0,triangles_alloc),
@@ -573,14 +565,16 @@ public:
vertices[i] = xfmPoint(xfm,vertices[i]);
}
static void getBoundsCallback (const uint32_t primIDStart, const uint32_t primIDCount, void* geomUserPtr, void* buildUserPtr, RTHWIF_AABB* boundsOut)
static void getBoundsCallback (ze_rtas_geometry_aabbs_exp_cb_params_t* params)
{
const TriangleMesh* mesh = (TriangleMesh*) geomUserPtr;
assert(params->stype == ZE_STRUCTURE_TYPE_RTAS_GEOMETRY_AABBS_EXP_CB_PARAMS);
const TriangleMesh* mesh = (TriangleMesh*) params->pGeomUserPtr;
for (uint32_t i=0; i<primIDCount; i++)
for (uint32_t i=0; i<params->primIDCount; i++)
{
const uint32_t primID = primIDStart+i;
const uint32_t primID = params->primID+i;
const Bounds3f bounds = mesh->getBounds(primID);
ze_rtas_aabb_exp_t* boundsOut = params->pBoundsOut;
boundsOut[i].lower.x = bounds.lower.x();
boundsOut[i].lower.y = bounds.lower.y();
boundsOut[i].lower.z = bounds.lower.z();
@@ -594,26 +588,28 @@ public:
{
if (procedural)
{
RTHWIF_GEOMETRY_AABBS_FPTR_DESC& out = desc->AABBs;
ze_rtas_builder_procedural_geometry_info_exp_t& out = desc->AABBs;
memset(&out,0,sizeof(out));
out.geometryType = RTHWIF_GEOMETRY_TYPE_AABBS_FPTR;
out.geometryType = ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL;
out.geometryFlags = gflags;
out.geometryMask = 0xFF;
out.primCount = triangles.size();
out.getBounds = TriangleMesh::getBoundsCallback;
out.geomUserPtr = this;
out.pfnGetBoundsCb = TriangleMesh::getBoundsCallback;
out.pGeomUserPtr = this;
}
else
{
RTHWIF_GEOMETRY_TRIANGLES_DESC& out = desc->Triangles;
ze_rtas_builder_triangles_geometry_info_exp_t& out = desc->Triangles;
memset(&out,0,sizeof(out));
out.geometryType = RTHWIF_GEOMETRY_TYPE_TRIANGLES;
out.geometryType = ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_TRIANGLES;
out.geometryFlags = gflags;
out.geometryMask = 0xFF;
out.triangleBuffer = (RTHWIF_TRIANGLE_INDICES*) triangles.data();
out.triangleFormat = ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_TRIANGLE_INDICES_UINT32;
out.vertexFormat = ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3;
out.pTriangleBuffer = (ze_rtas_triangle_indices_uint32_exp_t*) triangles.data();
out.triangleCount = triangles.size();
out.triangleStride = sizeof(sycl::int4);
out.vertexBuffer = (RTHWIF_FLOAT3*) vertices.data();
out.pVertexBuffer = (ze_rtas_float3_exp_t*) vertices.data();
out.vertexCount = vertices.size();
out.vertexStride = sizeof(sycl::float3);
}
@@ -765,7 +761,7 @@ public:
public:
RTHWIF_GEOMETRY_FLAGS gflags = RTHWIF_GEOMETRY_FLAG_OPAQUE;
ze_rtas_builder_geometry_exp_flags_t gflags = 0;
bool procedural = false;
typedef sycl::usm_allocator<sycl::int4, sycl::usm::alloc::shared> triangles_alloc_ty;
@@ -794,14 +790,15 @@ struct InstanceGeometryT : public Geometry
sycl::free(ptr,context);
}
static void getBoundsCallback (const uint32_t primIDStart, const uint32_t primIDCount, void* geomUserPtr, void* buildUserPtr, RTHWIF_AABB* boundsOut)
static void getBoundsCallback (ze_rtas_geometry_aabbs_exp_cb_params_t* params)
{
assert(primIDStart == 0);
assert(primIDCount == 1);
const InstanceGeometryT* inst = (InstanceGeometryT*) geomUserPtr;
assert(params->stype == ZE_STRUCTURE_TYPE_RTAS_GEOMETRY_AABBS_EXP_CB_PARAMS);
assert(params->primID == 0);
assert(params->primIDCount == 1);
const InstanceGeometryT* inst = (InstanceGeometryT*) params->pGeomUserPtr;
const Bounds3f scene_bounds = inst->scene->getBounds();
const Bounds3f bounds = xfmBounds(inst->local2world, scene_bounds);
ze_rtas_aabb_exp_t* boundsOut = params->pBoundsOut;
boundsOut->lower.x = bounds.lower.x();
boundsOut->lower.y = bounds.lower.y();
boundsOut->lower.z = bounds.lower.z();
@@ -814,25 +811,25 @@ struct InstanceGeometryT : public Geometry
{
if (procedural)
{
RTHWIF_GEOMETRY_AABBS_FPTR_DESC& out = desc->AABBs;
ze_rtas_builder_procedural_geometry_info_exp_t& out = desc->AABBs;
memset(&out,0,sizeof(out));
out.geometryType = RTHWIF_GEOMETRY_TYPE_AABBS_FPTR;
out.geometryFlags = RTHWIF_GEOMETRY_FLAG_NONE;
out.geometryType = ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL;
out.geometryFlags = 0;
out.geometryMask = 0xFF;
out.primCount = 1;
out.getBounds = InstanceGeometryT::getBoundsCallback;
out.geomUserPtr = this;
out.pfnGetBoundsCb = InstanceGeometryT::getBoundsCallback;
out.pGeomUserPtr = this;
}
else
{
GEOMETRY_INSTANCE_DESC& out = desc->Instance;
memset(&out,0,sizeof(GEOMETRY_INSTANCE_DESC));
out.geometryType = RTHWIF_GEOMETRY_TYPE_INSTANCE;
out.instanceFlags = RTHWIF_INSTANCE_FLAG_NONE;
out.geometryType = ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_INSTANCE;
out.instanceFlags = 0;
out.geometryMask = 0xFF;
out.instanceUserID = instUserID;
out.transformFormat = RTHWIF_TRANSFORM_FORMAT_FLOAT4X4_COLUMN_MAJOR;
out.transform = (float*)&out.xfmdata;
out.transformFormat = ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3X4_ALIGNED_COLUMN_MAJOR;
out.pTransform = (float*)&out.xfmdata;
out.xfmdata.vx_x = local2world.vx.x();
out.xfmdata.vx_y = local2world.vx.y();
out.xfmdata.vx_z = local2world.vx.z();
@@ -849,12 +846,12 @@ struct InstanceGeometryT : public Geometry
out.xfmdata.p_y = local2world.p.y();
out.xfmdata.p_z = local2world.p.z();
out.xfmdata.pad3 = 0.0f;
out.bounds = &scene->bounds;
out.accel = scene->getAccel();
out.pBounds = &scene->bounds;
out.pAccelerationStructure = scene->getAccel();
}
}
virtual void buildAccel(sycl::device& device, sycl::context& context, BuildMode buildMode, RTHWIF_BUILD_QUALITY quality) override {
virtual void buildAccel(sycl::device& device, sycl::context& context, BuildMode buildMode, ze_rtas_builder_build_quality_hint_exp_t quality) override {
scene->buildAccel(device,context,buildMode);
}
@@ -900,18 +897,18 @@ std::shared_ptr<TriangleMesh> createTrianglePlane (const sycl::float3& p0, const
return mesh;
}
void* alloc_accel_buffer(size_t bytes, sycl::device device, sycl::context context)
void* alloc_accel_buffer_internal(size_t bytes, sycl::device device, sycl::context context)
{
#if 1
return sycl::aligned_alloc_shared(RTHWIF_ACCELERATION_STRUCTURE_ALIGNMENT,bytes,device,context,sycl::ext::oneapi::property::usm::device_read_only());
#else // FIXME: enable this
ze_context_handle_t hContext = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(context);
ze_device_handle_t hDevice = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(device);
ze_rtas_device_exp_properties_t rtasProp = { ZE_STRUCTURE_TYPE_RTAS_DEVICE_EXP_PROPERTIES };
ze_result_t err = zeDeviceGetRTASPropertiesExp(hDevice, &rtasProp );
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("get rtas device properties failed");
ze_raytracing_mem_alloc_ext_desc_t rt_desc;
rt_desc.stype = ZE_STRUCTURE_TYPE_DEVICE_RAYTRACING_EXT_PROPERTIES;
rt_desc.stype = ZE_STRUCTURE_TYPE_RAYTRACING_MEM_ALLOC_EXT_DESC;
rt_desc.pNext = nullptr;
rt_desc.flags = 0;
@@ -927,38 +924,73 @@ void* alloc_accel_buffer(size_t bytes, sycl::device device, sycl::context contex
host_desc.flags = ZE_HOST_MEM_ALLOC_FLAG_BIAS_CACHED;
void* ptr = nullptr;
ze_result_t result = zeMemAllocShared(hContext,&device_desc,&host_desc,bytes,RTHWIF_ACCELERATION_STRUCTURE_ALIGNMENT,hDevice,&ptr);
assert(result == ZE_RESULT_SUCCESS);
ze_result_t result = zeMemAllocShared(hContext,&device_desc,&host_desc,bytes,rtasProp.rtasBufferAlignment,hDevice,&ptr);
if (result != ZE_RESULT_SUCCESS)
throw std::runtime_error("accel allocation failed");
return ptr;
}
void free_accel_buffer_internal(void* ptr, sycl::context context)
{
if (ptr == nullptr) return;
ze_context_handle_t hContext = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(context);
ze_result_t result = zeMemFree(hContext,ptr);
if (result != ZE_RESULT_SUCCESS)
throw std::runtime_error("accel free failed");
}
struct Block {
Block (size_t bytes, sycl::device device, sycl::context context)
: base((char*)alloc_accel_buffer_internal(bytes,device,context)), total(bytes), cur(0) {}
~Block() {
free_accel_buffer_internal((void*)base,context);
}
void* alloc(size_t bytes) {
bytes &= -128;
if (cur+bytes > total) return nullptr;
void* ptr = &base[cur];
cur += bytes;
return ptr;
}
char* base = nullptr;
size_t total = 0;
size_t cur = 0;
};
bool g_use_accel_blocks = true;
std::vector<std::shared_ptr<Block>> g_blocks;
void* alloc_accel_buffer(size_t bytes, sycl::device device, sycl::context context)
{
if (!g_use_accel_blocks)
return alloc_accel_buffer_internal(bytes,device,context);
if (g_blocks.size() == 0)
g_blocks.push_back(std::shared_ptr<Block>(new Block(1024*1024,device,context)));
if (bytes > 1024*1024) {
g_blocks.push_back(std::shared_ptr<Block>(new Block(bytes,device,context)));
void* ptr = g_blocks.back()->alloc(bytes);
assert(ptr);
return ptr;
}
void* ptr = g_blocks.back()->alloc(bytes);
if (ptr) return ptr;
g_blocks.push_back(std::shared_ptr<Block>(new Block(1024*1024,device,context)));
ptr = g_blocks.back()->alloc(bytes);
assert(ptr);
return ptr;
#endif
}
void free_accel_buffer(void* ptr, sycl::context context)
{
#if 1
sycl::free(ptr,context);
#else // FIXME: enable this
if (ptr == nullptr) return;
ze_context_handle_t hContext = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(context);
ze_result_t result = zeMemFree(hContext,ptr);
assert(result == ZE_RESULT_SUCCESS);
#endif
if (!g_use_accel_blocks)
return free_accel_buffer_internal(ptr,context);
}
void exception_handler(sycl::exception_list exceptions)
{
for (std::exception_ptr const& e : exceptions) {
try {
std::rethrow_exception(e);
} catch(sycl::exception const& e) {
std::cout << "Caught asynchronous SYCL exception: " << e.what() << std::endl;
}
}
};
struct Scene
{
typedef InstanceGeometryT<Scene> InstanceGeometry;
@@ -970,7 +1002,7 @@ struct Scene
: geometries_alloc(context,device,sycl::ext::oneapi::property::usm::device_read_only()), geometries(0,geometries_alloc), bounds(Bounds3f::empty()), accel(nullptr)
{
std::shared_ptr<TriangleMesh> plane = createTrianglePlane(sycl::float3(0,0,0), sycl::float3(width,0,0), sycl::float3(0,height,0), width, height);
plane->gflags = opaque ? RTHWIF_GEOMETRY_FLAG_OPAQUE : RTHWIF_GEOMETRY_FLAG_NONE;
plane->gflags = opaque ? (ze_rtas_builder_geometry_exp_flag_t) 0 : ZE_RTAS_BUILDER_GEOMETRY_EXP_FLAG_NON_OPAQUE;
plane->procedural = procedural;
geometries.push_back(plane);
}
@@ -1088,7 +1120,7 @@ struct Scene
geometries[j]->transform(world2local);
scene->geometries.push_back(geometries[j]);
}
//std::shared_ptr<InstanceGeometry> instance = std::make_shared<InstanceGeometry>(local2world,scene,procedural);
uint32_t instUserID = RandomSampler_getUInt(rng);
std::shared_ptr<InstanceGeometry> instance(new InstanceGeometry(local2world,scene,procedural,instUserID));
@@ -1116,22 +1148,14 @@ struct Scene
std::swap(geometries[g],geometries[k]);
}
}
void buildAccel(sycl::device& device, sycl::context& context, BuildMode buildMode, bool benchmark = false)
{
RTHWIF_BUILD_QUALITY quality = (RTHWIF_BUILD_QUALITY) (RandomSampler_getUInt(rng) % 3);
ze_rtas_builder_build_quality_hint_exp_t quality = (ze_rtas_builder_build_quality_hint_exp_t) (RandomSampler_getUInt(rng) % 3);
/* fill geometry descriptor buffer */
const size_t numGeometries = size();
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
sycl::queue queue(device, exception_handler);
GEOMETRY_DESC *desc = (GEOMETRY_DESC*)sycl::aligned_alloc(64,sizeof(GEOMETRY_DESC)*numGeometries,device,context,sycl::usm::alloc::shared);
RTHWIF_GEOMETRY_DESC **geom = (RTHWIF_GEOMETRY_DESC**)sycl::aligned_alloc(64,numGeometries*sizeof(RTHWIF_GEOMETRY_DESC*),device,context,sycl::usm::alloc::shared);
#else
std::vector<GEOMETRY_DESC> desc(size());
std::vector<const RTHWIF_GEOMETRY_DESC*> geom(size());
#endif
std::vector<const ze_rtas_builder_geometry_info_exp_t*> geom(size());
size_t numPrimitives = 0;
for (size_t geomID=0; geomID<size(); geomID++)
{
@@ -1146,69 +1170,45 @@ struct Scene
numPrimitives += g->getNumPrimitives();
g->buildAccel(device,context,buildMode,quality);
g->getDesc(&desc[geomID]);
geom[geomID] = (RTHWIF_GEOMETRY_DESC*) &desc[geomID];
geom[geomID] = (const ze_rtas_builder_geometry_info_exp_t*) &desc[geomID];
}
ze_device_handle_t hDevice = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(device);
ze_rtas_device_exp_properties_t rtasProp = { ZE_STRUCTURE_TYPE_RTAS_DEVICE_EXP_PROPERTIES };
ze_result_t err = zeDeviceGetRTASPropertiesExp(hDevice, &rtasProp );
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("get rtas device properties failed");
/* estimate accel size */
size_t accelBufferBytesOut = 0;
RTHWIF_AABB bounds;
RTHWIF_BUILD_ACCEL_ARGS args;
ze_rtas_aabb_exp_t bounds;
ze_rtas_builder_build_op_exp_desc_t args;
memset(&args,0,sizeof(args));
args.structBytes = sizeof(args);
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
args.geometries = (const RTHWIF_GEOMETRY_DESC**) geom;
#else
args.geometries = (const RTHWIF_GEOMETRY_DESC**) geom.data();
#endif
args.numGeometries = numGeometries; //geom.size();
args.accelBuffer = nullptr;
args.accelBufferBytes = 0;
args.scratchBuffer = nullptr;
args.scratchBufferBytes = 0;
args.quality = quality;
args.flags = RTHWIF_BUILD_FLAG_NONE;
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
args.parallelOperation = nullptr;
#else
args.parallelOperation = parallelOperation;
#endif
args.boundsOut = &bounds;
args.accelBufferBytesOut = &accelBufferBytesOut;
args.buildUserPtr = nullptr;
args.stype = ZE_STRUCTURE_TYPE_RTAS_BUILDER_BUILD_OP_EXP_DESC;
args.pNext = nullptr;
args.rtasFormat = rtasProp.rtasFormat;
args.buildQuality = quality;
args.buildFlags = 0;
args.ppGeometries = (const ze_rtas_builder_geometry_info_exp_t**) geom.data();
args.numGeometries = geom.size();
#if defined(EMBREE_SYCL_ALLOC_DISPATCH_GLOBALS)
args.dispatchGlobalsPtr = dispatchGlobalsPtr;
#endif
RTHWIF_ACCEL_SIZE size;
memset(&size,0,sizeof(RTHWIF_ACCEL_SIZE));
size.structBytes = sizeof(RTHWIF_ACCEL_SIZE);
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
RTHWIF_ERROR err = rthwifGetAccelSizeGPU(args,size,&queue,VERBOSE);
#else
RTHWIF_ERROR err = rthwifGetAccelSize(args,size);
#endif
if (err != RTHWIF_ERROR_NONE)
ze_rtas_builder_exp_properties_t size = { ZE_STRUCTURE_TYPE_RTAS_BUILDER_EXP_PROPERTIES };
err = zeRTASBuilderGetBuildPropertiesExp(hBuilder,&args,&size);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("BVH size estimate failed");
if (size.accelBufferExpectedBytes > size.accelBufferWorstCaseBytes)
if (size.rtasBufferSizeBytesExpected > size.rtasBufferSizeBytesMaxRequired)
throw std::runtime_error("expected larger than worst case");
/* allocate scratch buffer */
size_t sentinelBytes = 1024; // add that many zero bytes to catch buffer overruns
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
// === scratch buffer ===
char *scratchBuffer = (char*)sycl::aligned_alloc(64,size.scratchBufferBytes+sentinelBytes,device,context,sycl::usm::alloc::shared);
assert(scratchBuffer);
memset(scratchBuffer,0,size.scratchBufferBytes+sentinelBytes);
args.scratchBuffer = scratchBuffer;
args.scratchBufferBytes = size.scratchBufferBytes;
#else
std::vector<char> scratchBuffer(size.scratchBufferBytes+sentinelBytes);
std::vector<char> scratchBuffer(size.scratchBufferSizeBytes+sentinelBytes);
memset(scratchBuffer.data(),0,scratchBuffer.size());
args.scratchBuffer = scratchBuffer.data();
args.scratchBufferBytes = size.scratchBufferBytes;
#endif
accel = nullptr;
size_t accelBytes = 0;
@@ -1217,42 +1217,37 @@ struct Scene
{
case BuildMode::BUILD_WORST_CASE_SIZE: {
accelBytes = size.accelBufferWorstCaseBytes;
accelBytes = size.rtasBufferSizeBytesMaxRequired;
accel = alloc_accel_buffer(accelBytes+sentinelBytes,device,context);
memset(accel,0,accelBytes+sentinelBytes);
size_t numIterations = benchmark ? 16 : 1;
args.numGeometries = numGeometries; //geom.size();
args.accelBuffer = accel;
args.accelBufferBytes = size.accelBufferWorstCaseBytes;
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
rthwifPrefetchAccelGPU(args,&queue,VERBOSE);
#endif
/* build accel */
double t0 = embree::getSeconds();
size_t numIterations = benchmark ? 16 : 1;
for (size_t i=0; i<numIterations; i++)
{
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
err = rthwifBuildAccelGPU(args,&queue,VERBOSE);
#else
err = rthwifBuildAccel(args);
#endif
err = zeRTASBuilderBuildExp(hBuilder,&args,
scratchBuffer.data(),scratchBuffer.size(),
accel, accelBytes,
parallelOperation,
nullptr, &bounds, &accelBufferBytesOut);
if (args.parallelOperation) {
assert(err == RTHWIF_ERROR_PARALLEL_OPERATION);
uint32_t maxThreads = rthwifGetParallelOperationMaxConcurrency(parallelOperation);
tbb::parallel_for(0u, maxThreads, 1u, [&](uint32_t) {
err = rthwifJoinParallelOperation(parallelOperation);
});
if (parallelOperation)
{
assert(err == ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE);
ze_rtas_parallel_operation_exp_properties_t prop = { ZE_STRUCTURE_TYPE_RTAS_PARALLEL_OPERATION_EXP_PROPERTIES };
err = zeRTASParallelOperationGetPropertiesExp(parallelOperation,&prop);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("get max concurrency failed");
tbb::parallel_for(0u, prop.maxConcurrency, 1u, [&](uint32_t) {
err = zeRTASParallelOperationJoinExp(parallelOperation);
});
}
if (err != RTHWIF_ERROR_NONE)
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("build error");
}
double t1 = embree::getSeconds();
@@ -1265,7 +1260,7 @@ struct Scene
}
case BuildMode::BUILD_EXPECTED_SIZE: {
size_t bytes = size.accelBufferExpectedBytes;
size_t bytes = size.rtasBufferSizeBytesExpected;
for (size_t i=0; i<=16; i++) // FIXME: reduce worst cast iteration number
{
if (i == 16)
@@ -1278,40 +1273,36 @@ struct Scene
memset(accel,0,accelBytes+sentinelBytes);
/* build accel */
args.numGeometries = numGeometries; //geom.size();
args.accelBuffer = accel;
args.accelBufferBytes = accelBytes;
err = zeRTASBuilderBuildExp(hBuilder,&args,
scratchBuffer.data(),scratchBuffer.size(),
accel, accelBytes,
parallelOperation,
nullptr, &bounds, &accelBufferBytesOut);
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
err = rthwifBuildAccelGPU(args,&queue,VERBOSE);
#else
err = rthwifBuildAccel(args);
#endif
if (args.parallelOperation) {
assert(err == RTHWIF_ERROR_PARALLEL_OPERATION);
uint32_t maxThreads = rthwifGetParallelOperationMaxConcurrency(parallelOperation);
tbb::parallel_for(0u, maxThreads, 1u, [&](uint32_t) {
err = rthwifJoinParallelOperation(parallelOperation);
});
if (parallelOperation)
{
assert(err == ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE);
ze_rtas_parallel_operation_exp_properties_t prop = { ZE_STRUCTURE_TYPE_RTAS_PARALLEL_OPERATION_EXP_PROPERTIES };
err = zeRTASParallelOperationGetPropertiesExp(parallelOperation,&prop);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("get max concurrency failed");
tbb::parallel_for(0u, prop.maxConcurrency, 1u, [&](uint32_t) {
err = zeRTASParallelOperationJoinExp(parallelOperation);
});
}
if (err != RTHWIF_ERROR_RETRY)
if (err != ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY)
break;
// PRINT(accelBufferBytesOut);
// PRINT(bytes);
// PRINT(size.accelBufferExpectedBytes);
// PRINT(size.accelBufferWorstCaseBytes);
// PRINT(accelBufferBytesOut);
if (accelBufferBytesOut < bytes || size.accelBufferWorstCaseBytes < accelBufferBytesOut )
if (accelBufferBytesOut < bytes || size.rtasBufferSizeBytesMaxRequired < accelBufferBytesOut )
throw std::runtime_error("failed build returned wrong new estimate");
bytes = accelBufferBytesOut;
}
if (err != RTHWIF_ERROR_NONE)
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("build error");
break;
@@ -1323,27 +1314,21 @@ struct Scene
if (!benchmark)
{
/* scratch buffer bounds check */
for (size_t i=size.scratchBufferBytes; i<size.scratchBufferBytes+sentinelBytes; i++) {
if (((char*)args.scratchBuffer)[i] == 0x00) continue;
for (size_t i=size.scratchBufferSizeBytes; i<size.scratchBufferSizeBytes+sentinelBytes; i++) {
if (scratchBuffer[i] == 0x00) continue;
throw std::runtime_error("scratch buffer bounds check failed");
}
/* acceleration structure bounds check */
for (size_t i=accelBytes; i<accelBytes+sentinelBytes; i++) {
if (((char*)args.accelBuffer)[i] == 0x00) continue;
if (((char*)accel)[i] == 0x00) continue;
throw std::runtime_error("acceleration buffer bounds check failed");
}
/* check if returned size of acceleration structure is correct */
for (size_t i=accelBufferBytesOut; i<accelBytes; i++) {
if (((char*)args.accelBuffer)[i] == 0x00) continue;
if (((char*)accel)[i] == 0x00) continue;
throw std::runtime_error("wrong acceleration structure size returned");
}
}
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
sycl::free(scratchBuffer,context);
sycl::free(geom ,context);
sycl::free(desc ,context);
#endif
}
void buildTriMap(Transform local_to_world, std::vector<uint32_t> id_stack, uint32_t instUserID, bool procedural_instance, std::vector<Hit>& tri_map)
@@ -1380,10 +1365,21 @@ struct Scene
geometries_alloc_ty geometries_alloc;
std::vector<std::shared_ptr<Geometry>, geometries_alloc_ty> geometries;
RTHWIF_AABB bounds;
ze_rtas_aabb_exp_t bounds;
void* accel;
};
void exception_handler(sycl::exception_list exceptions)
{
for (std::exception_ptr const& e : exceptions) {
try {
std::rethrow_exception(e);
} catch(sycl::exception const& e) {
std::cout << "Caught asynchronous SYCL exception: " << e.what() << std::endl;
}
}
};
void render(uint32_t i, const TestInput& in, TestOutput& out, intel_raytracing_acceleration_structure_t accel)
{
intel_raytracing_ext_flag_t flags = intel_get_raytracing_ext_flag();
@@ -1614,7 +1610,7 @@ void render_loop(uint32_t i, const TestInput& in, TestOutput& out, size_t scene_
const float V = sycl::dot(cross(e1,v0+v1),D);
const float W = sycl::dot(cross(e2,v1+v2),D);
const float UVW = U+V+W;
bool valid = (std::min(U,std::min(V,W)) >= -0.0f) | (std::max(U,std::max(V,W)) <= 0.0f);
bool valid = (std::min(U,std::min(V,W)) >= -0.0f) || (std::max(U,std::max(V,W)) <= 0.0f);
/* calculate geometry normal and denominator */
const sycl::float3 Ng = sycl::cross(e2,e1);
@@ -1848,6 +1844,7 @@ uint32_t executeTest(sycl::device& device, sycl::queue& queue, sycl::context& co
scene->createInstances(scene->size(),3, inst == InstancingType::SW_INSTANCING);
scene->addNullGeometries(16);
scene->buildAccel(device,context,BuildMode::BUILD_EXPECTED_SIZE,false);
/* calculate test input and expected output */
@@ -1973,9 +1970,6 @@ uint32_t executeBuildTest(sycl::device& device, sycl::queue& queue, sycl::contex
const uint32_t numPrimitives = i>10 ? i*i : i;
std::cout << "testing " << numPrimitives << " primitives" << std::endl;
numErrors += executeBuildTest(device,queue,context,test,buildMode,numPrimitives,i);
if (VERBOSE)
if (numErrors)
exit(1);
}
return numErrors;
}
@@ -2030,13 +2024,9 @@ void* allocDispatchGlobals(sycl::device device, sycl::context context)
size_t num_rtstacks = 1<<17; // this is sufficiently large also for PVC
size_t dispatchGlobalSize = 128+num_rtstacks*rtstack_bytes;
//dispatchGlobalsPtr = this->malloc(dispatchGlobalSize, 64);
void* dispatchGlobalsPtr = sycl::aligned_alloc(64,dispatchGlobalSize,device,context,sycl::usm::alloc::shared);
void* dispatchGlobalsPtr = alloc_accel_buffer(dispatchGlobalSize,device,context);
memset(dispatchGlobalsPtr, 0, dispatchGlobalSize);
if (((size_t)dispatchGlobalsPtr & 0xFFFF000000000000ull) != 0)
throw std::runtime_error("internal error in RTStack allocation");
DispatchGlobals* dg = (DispatchGlobals*) dispatchGlobalsPtr;
dg->rtMemBasePtr = (uint64_t) dispatchGlobalsPtr + dispatchGlobalSize;
dg->callStackHandlerKSP = 0;
@@ -2052,7 +2042,7 @@ void* allocDispatchGlobals(sycl::device device, sycl::context context)
int main(int argc, char* argv[])
{
rthwifInit();
zeRTASInitExp();
TestType test = TestType::TRIANGLES_COMMITTED_HIT;
InstancingType inst = InstancingType::NONE;
@@ -2139,33 +2129,52 @@ int main(int argc, char* argv[])
/* initialize SYCL device */
device = sycl::device(sycl::gpu_selector_v);
sycl::queue queue = sycl::queue(device, exception_handler);
sycl::queue queue = sycl::queue(device,exception_handler);
context = queue.get_context();
#if defined(EMBREE_SYCL_ALLOC_DISPATCH_GLOBALS)
dispatchGlobalsPtr = allocDispatchGlobals(device,context);
#endif
/* execute test */
RandomSampler_init(rng,0x56FE238A);
parallelOperation = rthwifNewParallelOperation();
sycl::platform platform = device.get_platform();
ze_driver_handle_t hDriver = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(platform);
/* create L0 builder object */
ze_rtas_builder_exp_desc_t builderDesc = { ZE_STRUCTURE_TYPE_RTAS_BUILDER_EXP_DESC };
ze_result_t err = zeRTASBuilderCreateExp(hDriver, &builderDesc, &hBuilder);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("ze_rtas_builder creation failed");
err = zeRTASParallelOperationCreateExp(hDriver,&parallelOperation);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("parallel operation creation failed");
uint32_t numErrors = 0;
if (test >= TestType::BENCHMARK_TRIANGLES)
{
numErrors = executeBenchmark(device,queue,context,test);
}
else if (test >= TestType::BUILD_TEST_TRIANGLES)
{
numErrors = executeBuildTest(device,queue,context,test,buildMode);
}
else
{
numErrors = executeTest(device,queue,context,inst,test);
}
sycl::free(dispatchGlobalsPtr, context);
err = zeRTASParallelOperationDestroyExp(parallelOperation);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("parallel operation destruction failed");
rthwifExit();
/* destroy rtas builder again */
err = zeRTASBuilderDestroyExp(hBuilder);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("ze_rtas_builder destruction failed");
#if defined(EMBREE_SYCL_ALLOC_DISPATCH_GLOBALS)
free_accel_buffer(dispatchGlobalsPtr, context);
#endif
zeRTASExitExp();
return numErrors ? 1 : 0;
}
+7 -7
View File
@@ -32,7 +32,7 @@ RTC_API_EXTERN_C RTCDevice rtcNewSYCLDevice(sycl::context context, const char* c
#if defined(EMBREE_SYCL_SUPPORT) && (defined(__SYCL_DEVICE_ONLY__) || defined(EMBREE_SYCL_RT_SIMULATION))
SYCL_EXTERNAL void rtcIntersect1(RTCScene hscene, struct RTCRayHit* rayhit, struct RTCIntersectArguments* args)
SYCL_EXTERNAL __attribute__((always_inline)) void rtcIntersect1(RTCScene hscene, struct RTCRayHit* rayhit, struct RTCIntersectArguments* args)
{
RTCIntersectArguments default_args;
if (args == nullptr) {
@@ -50,7 +50,7 @@ SYCL_EXTERNAL void rtcIntersect1(RTCScene hscene, struct RTCRayHit* rayhit, stru
rtcIntersectRTHW(hscene, context, rayhit, args);
}
SYCL_EXTERNAL void rtcForwardIntersect1(const RTCIntersectFunctionNArguments* args_, RTCScene scene, struct RTCRay* iray, unsigned int instID)
SYCL_EXTERNAL __attribute__((always_inline)) void rtcForwardIntersect1(const RTCIntersectFunctionNArguments* args_, RTCScene scene, struct RTCRay* iray, unsigned int instID)
{
IntersectFunctionNArguments* args = (IntersectFunctionNArguments*) args_;
assert(args->N == 1);
@@ -67,7 +67,7 @@ SYCL_EXTERNAL void rtcForwardIntersect1(const RTCIntersectFunctionNArguments* ar
instance_id_stack::push(args->context, instID);
}
SYCL_EXTERNAL void rtcOccluded1(RTCScene hscene, struct RTCRay* ray, struct RTCOccludedArguments* args)
SYCL_EXTERNAL __attribute__((always_inline)) void rtcOccluded1(RTCScene hscene, struct RTCRay* ray, struct RTCOccludedArguments* args)
{
RTCOccludedArguments default_args;
if (args == nullptr) {
@@ -85,7 +85,7 @@ SYCL_EXTERNAL void rtcOccluded1(RTCScene hscene, struct RTCRay* ray, struct RTCO
rtcOccludedRTHW(hscene, context, ray, args);
}
SYCL_EXTERNAL void rtcForwardOccluded1(const RTCOccludedFunctionNArguments* args_, RTCScene scene, struct RTCRay* iray, unsigned int instID)
SYCL_EXTERNAL __attribute__((always_inline)) void rtcForwardOccluded1(const RTCOccludedFunctionNArguments* args_, RTCScene scene, struct RTCRay* iray, unsigned int instID)
{
OccludedFunctionNArguments* args = (OccludedFunctionNArguments*) args_;
assert(args->N == 1);
@@ -102,7 +102,7 @@ SYCL_EXTERNAL void rtcForwardOccluded1(const RTCOccludedFunctionNArguments* args
instance_id_stack::push(args->context, instID);
}
SYCL_EXTERNAL void* rtcGetGeometryUserDataFromScene (RTCScene hscene, unsigned int geomID)
SYCL_EXTERNAL __attribute__((always_inline)) void* rtcGetGeometryUserDataFromScene (RTCScene hscene, unsigned int geomID)
{
Scene* scene = (Scene*) hscene;
//RTC_CATCH_BEGIN;
@@ -117,7 +117,7 @@ SYCL_EXTERNAL void* rtcGetGeometryUserDataFromScene (RTCScene hscene, unsigned i
//return nullptr;
}
SYCL_EXTERNAL void rtcInvokeIntersectFilterFromGeometry(const RTCIntersectFunctionNArguments* args_i, const RTCFilterFunctionNArguments* filter_args)
SYCL_EXTERNAL __attribute__((always_inline)) void rtcInvokeIntersectFilterFromGeometry(const RTCIntersectFunctionNArguments* args_i, const RTCFilterFunctionNArguments* filter_args)
{
#if EMBREE_SYCL_GEOMETRY_CALLBACK
IntersectFunctionNArguments* args = (IntersectFunctionNArguments*) args_i;
@@ -126,7 +126,7 @@ SYCL_EXTERNAL void rtcInvokeIntersectFilterFromGeometry(const RTCIntersectFuncti
#endif
}
SYCL_EXTERNAL void rtcInvokeOccludedFilterFromGeometry(const RTCOccludedFunctionNArguments* args_i, const RTCFilterFunctionNArguments* filter_args)
SYCL_EXTERNAL __attribute__((always_inline)) void rtcInvokeOccludedFilterFromGeometry(const RTCOccludedFunctionNArguments* args_i, const RTCFilterFunctionNArguments* filter_args)
{
#if EMBREE_SYCL_GEOMETRY_CALLBACK
OccludedFunctionNArguments* args = (OccludedFunctionNArguments*) args_i;
+15 -20
View File
@@ -22,12 +22,7 @@
#include "../geometry/triangle_intersector_pluecker.h"
#include "rthwif_embree.h"
#if defined(EMBREE_SYCL_RT_VALIDATION_API)
# include "../rthwif/rttrace/rthwif_production.h"
#else
# include "../rthwif/rttrace/rthwif_production_igc.h"
#endif
#include "../rthwif/rttrace/rttrace.h"
using namespace embree;
@@ -68,7 +63,7 @@ const constexpr uint32_t TRAV_LOOP_FEATURES =
void use_rthwif_embree() {
}
Vec3f intel_get_hit_triangle_normal(intel_ray_query_t& query, intel_hit_type_t hit_type)
__forceinline Vec3f intel_get_hit_triangle_normal(intel_ray_query_t& query, intel_hit_type_t hit_type)
{
intel_float3 v[3]; intel_get_hit_triangle_vertices(query, v, hit_type);
const Vec3f v0(v[0].x, v[0].y, v[0].z);
@@ -77,7 +72,7 @@ Vec3f intel_get_hit_triangle_normal(intel_ray_query_t& query, intel_hit_type_t h
return cross(v1-v0, v2-v0);
}
bool intersect_user_geometry(intel_ray_query_t& query, RayHit& ray, UserGeometry* geom, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr<RayQueryContext> context, uint32_t geomID, uint32_t primID)
__forceinline bool intersect_user_geometry(intel_ray_query_t& query, RayHit& ray, UserGeometry* geom, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr<RayQueryContext> context, uint32_t geomID, uint32_t primID)
{
/* perform ray mask test */
#if defined(EMBREE_RAY_MASK)
@@ -118,7 +113,7 @@ bool intersect_user_geometry(intel_ray_query_t& query, RayHit& ray, UserGeometry
return false;
}
bool intersect_user_geometry(intel_ray_query_t& query, Ray& ray, UserGeometry* geom, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr<RayQueryContext> context, uint32_t geomID, uint32_t primID)
__forceinline bool intersect_user_geometry(intel_ray_query_t& query, Ray& ray, UserGeometry* geom, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr<RayQueryContext> context, uint32_t geomID, uint32_t primID)
{
/* perform ray mask test */
#if defined(EMBREE_RAY_MASK)
@@ -160,10 +155,10 @@ bool intersect_user_geometry(intel_ray_query_t& query, Ray& ray, UserGeometry* g
}
template<typename Ray>
bool intersect_instance(intel_ray_query_t& query, Ray& ray, Instance* instance, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr<RayQueryContext> context, uint32_t geomID, uint32_t primID);
__forceinline bool intersect_instance(intel_ray_query_t& query, Ray& ray, Instance* instance, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr<RayQueryContext> context, uint32_t geomID, uint32_t primID);
template<>
bool intersect_instance(intel_ray_query_t& query, RayHit& ray, Instance* instance, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr<RayQueryContext> context, uint32_t geomID, uint32_t primID)
__forceinline bool intersect_instance(intel_ray_query_t& query, RayHit& ray, Instance* instance, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr<RayQueryContext> context, uint32_t geomID, uint32_t primID)
{
/* perform ray mask test */
#if defined(EMBREE_RAY_MASK)
@@ -214,7 +209,7 @@ bool intersect_instance(intel_ray_query_t& query, RayHit& ray, Instance* instanc
}
template<>
bool intersect_instance(intel_ray_query_t& query, Ray& ray, Instance* instance, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr<RayQueryContext> context, uint32_t geomID, uint32_t primID)
__forceinline bool intersect_instance(intel_ray_query_t& query, Ray& ray, Instance* instance, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr<RayQueryContext> context, uint32_t geomID, uint32_t primID)
{
/* perform ray mask test */
#if defined(EMBREE_RAY_MASK)
@@ -265,7 +260,7 @@ bool intersect_instance(intel_ray_query_t& query, Ray& ray, Instance* instance,
}
template<typename Ray>
bool intersect_primitive(intel_ray_query_t& query, Ray& ray, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], Geometry* geom, sycl::private_ptr<RayQueryContext> context, uint32_t geomID, uint32_t primID, const RTCFeatureFlags feature_mask)
__forceinline bool intersect_primitive(intel_ray_query_t& query, Ray& ray, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], Geometry* geom, sycl::private_ptr<RayQueryContext> context, uint32_t geomID, uint32_t primID, const RTCFeatureFlags feature_mask)
{
#if defined(EMBREE_SYCL_SUPPORT) && defined(__SYCL_DEVICE_ONLY__)
bool filter = feature_mask & (RTC_FEATURE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS | RTC_FEATURE_FLAG_FILTER_FUNCTION_IN_GEOMETRY);
@@ -465,7 +460,7 @@ bool intersect_primitive(intel_ray_query_t& query, Ray& ray, Scene* scenes[RTC_M
return false;
}
bool invokeTriangleIntersectionFilter(intel_ray_query_t& query, Geometry* geom, uint32_t bvh_level, RayHit& ray, Hit& hit, sycl::private_ptr<RayQueryContext> context, const RTCFeatureFlags feature_mask)
__forceinline bool invokeTriangleIntersectionFilter(intel_ray_query_t& query, Geometry* geom, uint32_t bvh_level, RayHit& ray, Hit& hit, sycl::private_ptr<RayQueryContext> context, const RTCFeatureFlags feature_mask)
{
#if defined(EMBREE_FILTER_FUNCTION)
if (!(feature_mask & RTC_FEATURE_FLAG_FILTER_FUNCTION) || runIntersectionFilter1SYCL(geom, ray, context, hit))
@@ -479,7 +474,7 @@ bool invokeTriangleIntersectionFilter(intel_ray_query_t& query, Geometry* geom,
return false;
}
bool invokeTriangleIntersectionFilter(intel_ray_query_t& query, Geometry* geom, uint32_t bvh_level, Ray& ray, Hit& hit, sycl::private_ptr<RayQueryContext> context, const RTCFeatureFlags feature_mask)
__forceinline bool invokeTriangleIntersectionFilter(intel_ray_query_t& query, Geometry* geom, uint32_t bvh_level, Ray& ray, Hit& hit, sycl::private_ptr<RayQueryContext> context, const RTCFeatureFlags feature_mask)
{
bool ishit = true;
#if defined(EMBREE_FILTER_FUNCTION)
@@ -492,18 +487,18 @@ bool invokeTriangleIntersectionFilter(intel_ray_query_t& query, Geometry* geom,
return ishit;
}
bool commit_potential_hit(intel_ray_query_t& query, RayHit& ray) {
__forceinline bool commit_potential_hit(intel_ray_query_t& query, RayHit& ray) {
intel_ray_query_commit_potential_hit_override (query, ray.tfar, float2(ray.u, ray.v));
return false;
}
bool commit_potential_hit(intel_ray_query_t& query, Ray& ray) {
__forceinline bool commit_potential_hit(intel_ray_query_t& query, Ray& ray) {
intel_ray_query_commit_potential_hit_override (query, ray.tfar, float2(0.0f, 0.0f));
return true;
}
template<typename Ray>
void trav_loop(intel_ray_query_t& query, Ray& ray, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr<RayQueryContext> context, const RTCFeatureFlags feature_mask)
__forceinline void trav_loop(intel_ray_query_t& query, Ray& ray, Scene* scenes[RTC_MAX_INSTANCE_LEVEL_COUNT+1], sycl::private_ptr<RayQueryContext> context, const RTCFeatureFlags feature_mask)
{
while (!intel_is_traversal_done(query))
{
@@ -570,7 +565,7 @@ void trav_loop(intel_ray_query_t& query, Ray& ray, Scene* scenes[RTC_MAX_INSTANC
}
}
SYCL_EXTERNAL void rtcIntersectRTHW(sycl::global_ptr<RTCSceneTy> hscene, sycl::private_ptr<RTCRayQueryContext> ucontext, sycl::private_ptr<RTCRayHit> rayhit_i, sycl::private_ptr<RTCIntersectArguments> args)
SYCL_EXTERNAL __attribute__((always_inline)) void rtcIntersectRTHW(sycl::global_ptr<RTCSceneTy> hscene, sycl::private_ptr<RTCRayQueryContext> ucontext, sycl::private_ptr<RTCRayHit> rayhit_i, sycl::private_ptr<RTCIntersectArguments> args)
{
Scene* scene = (Scene*) hscene.get();
intel_raytracing_acceleration_structure_t hwaccel_ptr = (intel_raytracing_acceleration_structure_t) scene->hwaccel.data();
@@ -683,7 +678,7 @@ SYCL_EXTERNAL void rtcIntersectRTHW(sycl::global_ptr<RTCSceneTy> hscene, sycl::p
intel_ray_query_abandon(query);
}
SYCL_EXTERNAL void rtcOccludedRTHW(sycl::global_ptr<RTCSceneTy> hscene, sycl::private_ptr<RTCRayQueryContext> ucontext, sycl::private_ptr<RTCRay> ray_i, sycl::private_ptr<RTCOccludedArguments> args)
SYCL_EXTERNAL __attribute__((always_inline)) void rtcOccludedRTHW(sycl::global_ptr<RTCSceneTy> hscene, sycl::private_ptr<RTCRayQueryContext> ucontext, sycl::private_ptr<RTCRay> ray_i, sycl::private_ptr<RTCOccludedArguments> args)
{
Scene* scene = (Scene*) hscene.get();
intel_raytracing_acceleration_structure_t hwaccel_ptr = (intel_raytracing_acceleration_structure_t) scene->hwaccel.data();
+233 -291
View File
@@ -9,17 +9,10 @@
#include "rthwif_embree_builder.h"
#include "../common/scene.h"
#include "../builders/primrefgen.h"
#include "../rthwif/rtbuild/rthwif_builder.h"
#if defined(EMBREE_LEVEL_ZERO)
#include <level_zero/ze_api.h>
#endif
#include "../rthwif/rtbuild/rtbuild.h"
namespace embree
{
BBox3fa rthwifBuildPloc(Scene* scene, RTCBuildQuality quality_flags, Device::avector<char,64>& buffer_o, const bool two_level=false);
using namespace embree::isa;
enum Flags : uint32_t {
@@ -34,7 +27,7 @@ namespace embree
struct DispatchGlobals
{
uint64_t rtMemBasePtr; // base address of the allocated stack memory
uint64_t callStackHandlerKSP; // this is the KSP of the continuation handler that is invoked by BTD when the read KSP is 0
uint64_t callStackHandlerKSP; // this is the KSP of the continuation handler that is invoked by BTD when the read KSP is 0
uint32_t asyncStackSize; // async-RT stack size in 64 byte blocks
uint32_t numDSSRTStacks : 16; // number of stacks per DSS
uint32_t syncRayQueryCount : 4; // number of ray queries in the sync-RT stack: 0-15 mapped to: 1-16
@@ -43,11 +36,15 @@ namespace embree
Flags flags; // per context control flags
};
void* rthwifInit(sycl::device device, sycl::context context)
void* zeRTASInitExp(sycl::device device, sycl::context context)
{
::rthwifInit();
::zeRTASInitExp();
#if defined(EMBREE_SYCL_ALLOC_DISPATCH_GLOBALS)
#if !defined(EMBREE_LEVEL_ZERO)
# error "Level Zero required to properly allocate RTDispatchGlobals"
#endif
size_t maxBVHLevels = RTC_MAX_INSTANCE_LEVEL_COUNT+1;
@@ -55,13 +52,9 @@ namespace embree
size_t num_rtstacks = 1<<17; // this is sufficiently large also for PVC
size_t dispatchGlobalSize = 128+num_rtstacks*rtstack_bytes;
//dispatchGlobalsPtr = this->malloc(dispatchGlobalSize, 64);
void* dispatchGlobalsPtr = sycl::aligned_alloc(64,dispatchGlobalSize,device,context,sycl::usm::alloc::shared);
void* dispatchGlobalsPtr = rthwifAllocAccelBuffer(dispatchGlobalSize,device,context);
memset(dispatchGlobalsPtr, 0, dispatchGlobalSize);
if (((size_t)dispatchGlobalsPtr & 0xFFFF000000000000ull) != 0)
throw_RTCError(RTC_ERROR_UNKNOWN,"internal error in RTStack allocation");
DispatchGlobals* dg = (DispatchGlobals*) dispatchGlobalsPtr;
dg->rtMemBasePtr = (uint64_t) dispatchGlobalsPtr + dispatchGlobalSize;
dg->callStackHandlerKSP = 0;
@@ -83,9 +76,11 @@ namespace embree
void rthwifCleanup(void* dispatchGlobalsPtr, sycl::context context)
{
sycl::free(dispatchGlobalsPtr, context);
#if defined(EMBREE_SYCL_ALLOC_DISPATCH_GLOBALS)
rthwifFreeAccelBuffer(dispatchGlobalsPtr, context);
#endif
rthwifExit();
zeRTASExitExp();
}
#if defined(EMBREE_LEVEL_ZERO)
@@ -123,15 +118,7 @@ namespace embree
if (!ze_extension_ray_tracing)
return -1;
#if 1
/* check if GPU device is supported */
ze_device_handle_t hDevice = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(sycl_device);
const RTHWIF_FEATURES features = rthwifGetSupportedFeatures(hDevice);
if (features == RTHWIF_FEATURES_NONE)
return -1;
#else
#if 0
/* check if GPU device is supported */
ze_device_handle_t hDevice = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(sycl_device);
@@ -186,8 +173,13 @@ namespace embree
ze_context_handle_t hContext = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(context);
ze_device_handle_t hDevice = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(device);
ze_rtas_device_exp_properties_t rtasProp = { ZE_STRUCTURE_TYPE_RTAS_DEVICE_EXP_PROPERTIES };
ze_result_t err = zeDeviceGetRTASPropertiesExp(hDevice, &rtasProp );
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("get rtas device properties failed");
ze_raytracing_mem_alloc_ext_desc_t rt_desc;
rt_desc.stype = ZE_STRUCTURE_TYPE_DEVICE_RAYTRACING_EXT_PROPERTIES;
rt_desc.stype = ZE_STRUCTURE_TYPE_RAYTRACING_MEM_ALLOC_EXT_DESC;
rt_desc.pNext = nullptr;
rt_desc.flags = 0;
@@ -208,10 +200,10 @@ namespace embree
host_desc.flags = ZE_HOST_MEM_ALLOC_FLAG_BIAS_CACHED;
void* ptr = nullptr;
ze_result_t result = zeMemAllocShared(hContext,&device_desc,&host_desc,bytes,RTHWIF_ACCELERATION_STRUCTURE_ALIGNMENT,hDevice,&ptr);
ze_result_t result = zeMemAllocShared(hContext,&device_desc,&host_desc,bytes,rtasProp.rtasBufferAlignment,hDevice,&ptr);
if (result != ZE_RESULT_SUCCESS)
throw_RTCError(RTC_ERROR_OUT_OF_MEMORY,"BVH memory allocation failed");
_unused(result);
throw_RTCError(RTC_ERROR_OUT_OF_MEMORY,"rtas memory allocation failed");
return ptr;
}
@@ -220,17 +212,25 @@ namespace embree
if (ptr == nullptr) return;
ze_context_handle_t hContext = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(context);
ze_result_t result = zeMemFree(hContext,ptr);
assert(result == ZE_RESULT_SUCCESS);
_unused(result);
if (result != ZE_RESULT_SUCCESS)
throw_RTCError(RTC_ERROR_OUT_OF_MEMORY,"rtas memory free failed");
}
#else
void* rthwifAllocAccelBuffer(size_t bytes, sycl::device device, sycl::context context)
{
void* ptr = sycl::aligned_alloc_shared(RTHWIF_ACCELERATION_STRUCTURE_ALIGNMENT, bytes, device, context);
void* ptr = sycl::aligned_alloc_shared(128, bytes, device, context);
if (ptr == nullptr)
throw_RTCError(RTC_ERROR_OUT_OF_MEMORY,"BVH memory allocation failed");
throw_RTCError(RTC_ERROR_OUT_OF_MEMORY,"rtas memory allocation failed");
auto isAddrCanonical = [](uint64_t addr) {
return ((addr & 0xFFFF000000000000LL) == 0x0) || ((addr & 0xFFFF800000000000LL) == 0xFFFF800000000000LL);
};
if (!isAddrCanonical((uint64_t)ptr))
throw_RTCError(RTC_ERROR_OUT_OF_MEMORY,"rtas memory allocation out of 48 bit address range");
return ptr;
}
@@ -242,27 +242,27 @@ namespace embree
#endif
struct GEOMETRY_INSTANCE_DESC : RTHWIF_GEOMETRY_INSTANCE_DESC
struct GEOMETRY_INSTANCE_DESC : ze_rtas_builder_instance_geometry_info_exp_t
{
RTHWIF_TRANSFORM_FLOAT4X4_COLUMN_MAJOR xfmdata;
ze_rtas_transform_float3x4_aligned_column_major_exp_t xfmdata;
};
struct GEOMETRY_TYPE
{
GEOMETRY_TYPE(RTHWIF_GEOMETRY_TYPE type, size_t extraBytes = 0)
GEOMETRY_TYPE(ze_rtas_builder_geometry_type_exp_t type, size_t extraBytes = 0)
: type(type), extraBytes(extraBytes) {}
RTHWIF_GEOMETRY_TYPE type;
ze_rtas_builder_geometry_type_exp_t type;
size_t extraBytes;
};
size_t sizeof_RTHWIF_GEOMETRY(GEOMETRY_TYPE type)
{
switch (type.type) {
case RTHWIF_GEOMETRY_TYPE_TRIANGLES : return sizeof(RTHWIF_GEOMETRY_TRIANGLES_DESC)+type.extraBytes;
case RTHWIF_GEOMETRY_TYPE_QUADS : return sizeof(RTHWIF_GEOMETRY_QUADS_DESC)+type.extraBytes;
case RTHWIF_GEOMETRY_TYPE_AABBS_FPTR: return sizeof(RTHWIF_GEOMETRY_AABBS_FPTR_DESC)+type.extraBytes;
case RTHWIF_GEOMETRY_TYPE_INSTANCE : return sizeof(RTHWIF_GEOMETRY_INSTANCE_DESC)+type.extraBytes;
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_TRIANGLES : return sizeof(ze_rtas_builder_triangles_geometry_info_exp_t)+type.extraBytes;
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_QUADS : return sizeof(ze_rtas_builder_quads_geometry_info_exp_t)+type.extraBytes;
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL: return sizeof(ze_rtas_builder_procedural_geometry_info_exp_t)+type.extraBytes;
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_INSTANCE : return sizeof(ze_rtas_builder_instance_geometry_info_exp_t)+type.extraBytes;
default: assert(false); return 0;
}
}
@@ -270,66 +270,73 @@ namespace embree
size_t alignof_RTHWIF_GEOMETRY(GEOMETRY_TYPE type)
{
switch (type.type) {
case RTHWIF_GEOMETRY_TYPE_TRIANGLES : return alignof(RTHWIF_GEOMETRY_TRIANGLES_DESC);
case RTHWIF_GEOMETRY_TYPE_QUADS : return alignof(RTHWIF_GEOMETRY_QUADS_DESC);
case RTHWIF_GEOMETRY_TYPE_AABBS_FPTR: return alignof(RTHWIF_GEOMETRY_AABBS_FPTR_DESC);
case RTHWIF_GEOMETRY_TYPE_INSTANCE : return alignof(RTHWIF_GEOMETRY_INSTANCE_DESC);
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_TRIANGLES : return alignof(ze_rtas_builder_triangles_geometry_info_exp_t);
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_QUADS : return alignof(ze_rtas_builder_quads_geometry_info_exp_t);
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL: return alignof(ze_rtas_builder_procedural_geometry_info_exp_t);
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_INSTANCE : return alignof(ze_rtas_builder_instance_geometry_info_exp_t);
default: assert(false); return 0;
}
}
RTHWIF_GEOMETRY_FLAGS getGeometryFlags(Scene* scene, Geometry* geom)
ze_rtas_builder_geometry_exp_flags_t getGeometryFlags(Scene* scene, Geometry* geom)
{
/* invoke any hit callback when Embree filter functions are present */
RTHWIF_GEOMETRY_FLAGS gflags = RTHWIF_GEOMETRY_FLAG_OPAQUE;
ze_rtas_builder_geometry_exp_flags_t gflags = 0;
if (geom->hasArgumentFilterFunctions() || geom->hasGeometryFilterFunctions())
gflags = RTHWIF_GEOMETRY_FLAG_NONE;
gflags = ZE_RTAS_BUILDER_GEOMETRY_EXP_FLAG_NON_OPAQUE;
#if defined(EMBREE_RAY_MASK)
/* invoke any hit callback when high mask bits are enabled */
if (geom->mask & 0xFFFFFF80)
gflags = RTHWIF_GEOMETRY_FLAG_NONE;
gflags = ZE_RTAS_BUILDER_GEOMETRY_EXP_FLAG_NON_OPAQUE;
#endif
return gflags;
}
void createGeometryDesc(RTHWIF_GEOMETRY_TRIANGLES_DESC* out, Scene* scene, TriangleMesh* geom)
void createGeometryDesc(ze_rtas_builder_triangles_geometry_info_exp_t* out, Scene* scene, TriangleMesh* geom)
{
memset(out,0,sizeof(RTHWIF_GEOMETRY_TRIANGLES_DESC));
out->geometryType = RTHWIF_GEOMETRY_TYPE_TRIANGLES;
memset(out,0,sizeof(ze_rtas_builder_triangles_geometry_info_exp_t));
out->geometryType = ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_TRIANGLES;
out->geometryFlags = getGeometryFlags(scene,geom);
out->geometryMask = mask32_to_mask8(geom->mask);
out->triangleBuffer = (RTHWIF_TRIANGLE_INDICES*) geom->triangles.getPtr();
out->triangleFormat = ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_TRIANGLE_INDICES_UINT32;
out->vertexFormat = ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3;
out->pTriangleBuffer = (ze_rtas_triangle_indices_uint32_exp_t*) geom->triangles.getPtr();
out->triangleCount = geom->triangles.size();
out->triangleStride = geom->triangles.getStride();
out->vertexBuffer = (RTHWIF_FLOAT3*) geom->vertices0.getPtr();
out->pVertexBuffer = (ze_rtas_float3_exp_t*) geom->vertices0.getPtr();
out->vertexCount = geom->vertices0.size();
out->vertexStride = geom->vertices0.getStride();
}
void createGeometryDesc(RTHWIF_GEOMETRY_QUADS_DESC* out, Scene* scene, QuadMesh* geom)
void createGeometryDesc(ze_rtas_builder_quads_geometry_info_exp_t* out, Scene* scene, QuadMesh* geom)
{
memset(out,0,sizeof(RTHWIF_GEOMETRY_QUADS_DESC));
out->geometryType = RTHWIF_GEOMETRY_TYPE_QUADS;
memset(out,0,sizeof(ze_rtas_builder_quads_geometry_info_exp_t));
out->geometryType = ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_QUADS;
out->geometryFlags = getGeometryFlags(scene,geom);
out->geometryMask = mask32_to_mask8(geom->mask);
out->quadBuffer = (RTHWIF_QUAD_INDICES*) geom->quads.getPtr();
out->quadFormat = ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_QUAD_INDICES_UINT32;
out->vertexFormat = ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3;
out->pQuadBuffer = (ze_rtas_quad_indices_uint32_exp_t*) geom->quads.getPtr();
out->quadCount = geom->quads.size();
out->quadStride = geom->quads.getStride();
out->vertexBuffer = (RTHWIF_FLOAT3*) geom->vertices0.getPtr();
out->pVertexBuffer = (ze_rtas_float3_exp_t*) geom->vertices0.getPtr();
out->vertexCount = geom->vertices0.size();
out->vertexStride = geom->vertices0.getStride();
}
void getProceduralAABB(const uint32_t primIDStart, const uint32_t primIDCount, void* geomUserPtr, void* buildUserPtr, RTHWIF_AABB* boundsOut)
void getProceduralAABB(ze_rtas_geometry_aabbs_exp_cb_params_t* params)
{
BBox1f time_range = * (BBox1f*) buildUserPtr;
Geometry* geom = (Geometry*) geomUserPtr;
assert(params->stype == ZE_STRUCTURE_TYPE_RTAS_GEOMETRY_AABBS_EXP_CB_PARAMS);
BBox1f time_range = * (BBox1f*) params->pBuildUserPtr;
Geometry* geom = (Geometry*) params->pGeomUserPtr;
ze_rtas_aabb_exp_t* boundsOut = params->pBoundsOut;
for (uint32_t i=0; i<primIDCount; i++)
for (uint32_t i=0; i<params->primIDCount; i++)
{
const uint32_t primID = primIDStart+i;
const uint32_t primID = params->primID+i;
PrimRef prim;
range<size_t> r(primID);
size_t k = 0;
@@ -363,169 +370,162 @@ namespace embree
}
};
void createGeometryDescProcedural(RTHWIF_GEOMETRY_AABBS_FPTR_DESC* out, Scene* scene, Geometry* geom)
void createGeometryDescProcedural(ze_rtas_builder_procedural_geometry_info_exp_t* out, Scene* scene, Geometry* geom)
{
uint32_t numPrimitives = geom->size();
if (GridMesh* mesh = dynamic_cast<GridMesh*>(geom))
numPrimitives = mesh->getNumTotalQuads(); // FIXME: slow
memset(out,0,sizeof(RTHWIF_GEOMETRY_AABBS_FPTR_DESC));
out->geometryType = RTHWIF_GEOMETRY_TYPE_AABBS_FPTR;
out->geometryFlags = RTHWIF_GEOMETRY_FLAG_NONE;
memset(out,0,sizeof(ze_rtas_builder_procedural_geometry_info_exp_t));
out->geometryType = ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL;
out->geometryFlags = 0;
out->geometryMask = mask32_to_mask8(geom->mask);
out->primCount = numPrimitives;
out->getBounds = getProceduralAABB;
out->geomUserPtr = geom;
out->pfnGetBoundsCb = getProceduralAABB;
out->pGeomUserPtr = geom;
}
void createGeometryDesc(GEOMETRY_INSTANCE_DESC* out, Scene* scene, Instance* geom)
{
assert(geom->gsubtype == AccelSet::GTY_SUBTYPE_INSTANCE_QUATERNION);
memset(out,0,sizeof(GEOMETRY_INSTANCE_DESC));
out->geometryType = RTHWIF_GEOMETRY_TYPE_INSTANCE;
out->instanceFlags = RTHWIF_INSTANCE_FLAG_NONE;
out->geometryType = ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_INSTANCE;
out->instanceFlags = 0;
out->geometryMask = mask32_to_mask8(geom->mask);
out->instanceUserID = 0;
const AffineSpace3fa local2world = geom->getLocal2World();
out->transformFormat = RTHWIF_TRANSFORM_FORMAT_FLOAT4X4_COLUMN_MAJOR;
out->transform = (float*) &out->xfmdata;
out->bounds = (RTHWIF_AABB*) &dynamic_cast<Scene*>(geom->object)->hwaccel_bounds;
out->xfmdata = *(RTHWIF_TRANSFORM_FLOAT4X4_COLUMN_MAJOR*) &local2world;
out->transformFormat = ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3X4_ALIGNED_COLUMN_MAJOR;
out->pTransform = (float*) &out->xfmdata;
out->pBounds = (ze_rtas_aabb_exp_t*) &dynamic_cast<Scene*>(geom->object)->hwaccel_bounds;
out->xfmdata = *(ze_rtas_transform_float3x4_aligned_column_major_exp_t*) &local2world;
EmbreeHWAccel* hwaccel = (EmbreeHWAccel*) dynamic_cast<Scene*>(geom->object)->hwaccel.data();
out->accel = hwaccel->AccelTable[0];
out->pAccelerationStructure = hwaccel->AccelTable[0];
}
void createGeometryDesc(RTHWIF_GEOMETRY_INSTANCE_DESC* out, Scene* scene, Instance* geom)
void createGeometryDesc(ze_rtas_builder_instance_geometry_info_exp_t* out, Scene* scene, Instance* geom)
{
assert(geom->gsubtype == AccelSet::GTY_SUBTYPE_DEFAULT);
memset(out,0,sizeof(RTHWIF_GEOMETRY_INSTANCE_DESC));
out->geometryType = RTHWIF_GEOMETRY_TYPE_INSTANCE;
out->instanceFlags = RTHWIF_INSTANCE_FLAG_NONE;
memset(out,0,sizeof(ze_rtas_builder_instance_geometry_info_exp_t));
out->geometryType = ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_INSTANCE;
out->instanceFlags = 0;
out->geometryMask = mask32_to_mask8(geom->mask);
out->instanceUserID = 0;
out->transformFormat = RTHWIF_TRANSFORM_FORMAT_FLOAT4X4_COLUMN_MAJOR;
out->transform = (float*) &geom->local2world[0];
out->bounds = (RTHWIF_AABB*) &dynamic_cast<Scene*>(geom->object)->hwaccel_bounds;
out->transformFormat = ZE_RTAS_BUILDER_INPUT_DATA_FORMAT_EXP_FLOAT3X4_ALIGNED_COLUMN_MAJOR;
out->pTransform = (float*) &geom->local2world[0];
out->pBounds = (ze_rtas_aabb_exp_t*) &dynamic_cast<Scene*>(geom->object)->hwaccel_bounds;
EmbreeHWAccel* hwaccel = (EmbreeHWAccel*) dynamic_cast<Scene*>(geom->object)->hwaccel.data();
out->accel = hwaccel->AccelTable[0];
out->pAccelerationStructure = hwaccel->AccelTable[0];
}
void createGeometryDesc(char* out, Scene* scene, Geometry* geom, GEOMETRY_TYPE type)
{
switch (type.type) {
case RTHWIF_GEOMETRY_TYPE_TRIANGLES : return createGeometryDesc((RTHWIF_GEOMETRY_TRIANGLES_DESC*)out,scene,dynamic_cast<TriangleMesh*>(geom));
case RTHWIF_GEOMETRY_TYPE_QUADS : return createGeometryDesc((RTHWIF_GEOMETRY_QUADS_DESC*)out,scene,dynamic_cast<QuadMesh*>(geom));
case RTHWIF_GEOMETRY_TYPE_AABBS_FPTR: return createGeometryDescProcedural((RTHWIF_GEOMETRY_AABBS_FPTR_DESC*)out,scene,geom);
case RTHWIF_GEOMETRY_TYPE_INSTANCE:
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_TRIANGLES : return createGeometryDesc((ze_rtas_builder_triangles_geometry_info_exp_t*)out,scene,dynamic_cast<TriangleMesh*>(geom));
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_QUADS : return createGeometryDesc((ze_rtas_builder_quads_geometry_info_exp_t*)out,scene,dynamic_cast<QuadMesh*>(geom));
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL: return createGeometryDescProcedural((ze_rtas_builder_procedural_geometry_info_exp_t*)out,scene,geom);
case ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_INSTANCE:
if (type.extraBytes) return createGeometryDesc((GEOMETRY_INSTANCE_DESC*)out,scene,dynamic_cast<Instance*>(geom));
else return createGeometryDesc((RTHWIF_GEOMETRY_INSTANCE_DESC*)out,scene,dynamic_cast<Instance*>(geom));
else return createGeometryDesc((ze_rtas_builder_instance_geometry_info_exp_t*)out,scene,dynamic_cast<Instance*>(geom));
default: assert(false);
}
}
RTHWIF_BUILD_QUALITY convertBuildQuality(RTCBuildQuality quality_flags)
ze_rtas_builder_build_quality_hint_exp_t convertBuildQuality(RTCBuildQuality quality_flags)
{
switch (quality_flags) {
case RTC_BUILD_QUALITY_LOW : return RTHWIF_BUILD_QUALITY_LOW;
case RTC_BUILD_QUALITY_MEDIUM : return RTHWIF_BUILD_QUALITY_MEDIUM;
case RTC_BUILD_QUALITY_HIGH : return RTHWIF_BUILD_QUALITY_HIGH;
case RTC_BUILD_QUALITY_REFIT : return RTHWIF_BUILD_QUALITY_LOW;
default : return RTHWIF_BUILD_QUALITY_MEDIUM;
case RTC_BUILD_QUALITY_LOW : return ZE_RTAS_BUILDER_BUILD_QUALITY_HINT_EXP_LOW;
case RTC_BUILD_QUALITY_MEDIUM : return ZE_RTAS_BUILDER_BUILD_QUALITY_HINT_EXP_MEDIUM;
case RTC_BUILD_QUALITY_HIGH : return ZE_RTAS_BUILDER_BUILD_QUALITY_HINT_EXP_HIGH;
case RTC_BUILD_QUALITY_REFIT : return ZE_RTAS_BUILDER_BUILD_QUALITY_HINT_EXP_LOW;
default : return ZE_RTAS_BUILDER_BUILD_QUALITY_HINT_EXP_MEDIUM;
}
}
RTHWIF_BUILD_FLAGS convertBuildFlags(RTCSceneFlags scene_flags)
ze_rtas_builder_build_op_exp_flags_t convertBuildFlags(RTCSceneFlags scene_flags, RTCBuildQuality quality_flags)
{
uint32_t result = RTHWIF_BUILD_FLAG_NONE;
if (scene_flags & RTC_SCENE_FLAG_DYNAMIC) result |= RTHWIF_BUILD_FLAG_DYNAMIC;
if (scene_flags & RTC_SCENE_FLAG_COMPACT) result |= RTHWIF_BUILD_FLAG_COMPACT;
return (RTHWIF_BUILD_FLAGS) result;
ze_rtas_builder_build_op_exp_flags_t result = 0;
if (scene_flags & RTC_SCENE_FLAG_COMPACT) result |= ZE_RTAS_BUILDER_BUILD_OP_EXP_FLAG_COMPACT;
/* only in high quality build mode spatial splits are allowed in Embree */
if (quality_flags != RTC_BUILD_QUALITY_HIGH)
result |= ZE_RTAS_BUILDER_BUILD_OP_EXP_FLAG_NO_DUPLICATE_ANYHIT_INVOCATION;
return result;
}
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
void exception_handler(sycl::exception_list exceptions)
{
for (std::exception_ptr const& e : exceptions) {
try {
std::rethrow_exception(e);
} catch(sycl::exception const& e) {
std::cout << "Caught asynchronous SYCL exception: " << e.what() << std::endl;
}
}
};
#endif
BBox3f rthwifBuild(Scene* scene, AccelBuffer& accel)
{
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
DeviceGPU *gpu_device = dynamic_cast<DeviceGPU*>(scene->device);
sycl::device &sycl_device = gpu_device->getGPUDevice();
sycl::property_list PropList;
if (gpu_device->verbose) PropList = { sycl::property::queue::enable_profiling() };
sycl::queue sycl_queue(sycl_device, exception_handler, PropList );
#endif
{
DeviceGPU* gpuDevice = dynamic_cast<DeviceGPU*>(scene->device);
if (gpuDevice == nullptr) throw std::runtime_error("internal error");
sycl::device device = gpuDevice->getGPUDevice();
ze_device_handle_t hDevice = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(device);
sycl::platform platform = device.get_platform();
ze_driver_handle_t hDriver = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(platform);
/* create L0 builder object */
ze_rtas_builder_exp_desc_t builderDesc = { ZE_STRUCTURE_TYPE_RTAS_BUILDER_EXP_DESC };
ze_rtas_builder_exp_handle_t hBuilder = nullptr;
ze_result_t err = zeRTASBuilderCreateExp(hDriver, &builderDesc, &hBuilder);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("ze_rtas_builder creation failed");
auto getType = [&](unsigned int geomID) -> GEOMETRY_TYPE
{
/* no HW support for MB yet */
if (scene->get(geomID)->numTimeSegments() > 0)
return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR;
return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL;
switch (scene->get(geomID)->getType()) {
case Geometry::GTY_FLAT_LINEAR_CURVE : return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_ROUND_LINEAR_CURVE : return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_ORIENTED_LINEAR_CURVE: return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_CONE_LINEAR_CURVE : return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_FLAT_LINEAR_CURVE : return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_ROUND_LINEAR_CURVE : return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_ORIENTED_LINEAR_CURVE: return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_CONE_LINEAR_CURVE : return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_FLAT_BEZIER_CURVE : return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_ROUND_BEZIER_CURVE : return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_ORIENTED_BEZIER_CURVE: return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_FLAT_BEZIER_CURVE : return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_ROUND_BEZIER_CURVE : return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_ORIENTED_BEZIER_CURVE: return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_FLAT_BSPLINE_CURVE : return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_ROUND_BSPLINE_CURVE : return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_ORIENTED_BSPLINE_CURVE: return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_FLAT_BSPLINE_CURVE : return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_ROUND_BSPLINE_CURVE : return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_ORIENTED_BSPLINE_CURVE: return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_FLAT_HERMITE_CURVE : return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_ROUND_HERMITE_CURVE : return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_ORIENTED_HERMITE_CURVE: return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_FLAT_HERMITE_CURVE : return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_ROUND_HERMITE_CURVE : return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_ORIENTED_HERMITE_CURVE: return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_FLAT_CATMULL_ROM_CURVE : return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_ROUND_CATMULL_ROM_CURVE : return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_ORIENTED_CATMULL_ROM_CURVE: return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_FLAT_CATMULL_ROM_CURVE : return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_ROUND_CATMULL_ROM_CURVE : return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_ORIENTED_CATMULL_ROM_CURVE: return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_TRIANGLE_MESH: return RTHWIF_GEOMETRY_TYPE_TRIANGLES; break;
case Geometry::GTY_QUAD_MESH : return RTHWIF_GEOMETRY_TYPE_QUADS; break;
case Geometry::GTY_GRID_MESH : return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_SUBDIV_MESH : assert(false); return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_TRIANGLE_MESH: return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_TRIANGLES; break;
case Geometry::GTY_QUAD_MESH : return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_QUADS; break;
case Geometry::GTY_GRID_MESH : return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_SUBDIV_MESH : assert(false); return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_SPHERE_POINT : return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_DISC_POINT : return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_ORIENTED_DISC_POINT: return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_SPHERE_POINT : return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_DISC_POINT : return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_ORIENTED_DISC_POINT: return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_USER_GEOMETRY : return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_USER_GEOMETRY : return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
#if RTC_MAX_INSTANCE_LEVEL_COUNT < 2
case Geometry::GTY_INSTANCE_CHEAP :
case Geometry::GTY_INSTANCE_EXPENSIVE: {
Instance* instance = scene->get<Instance>(geomID);
EmbreeHWAccel* object = (EmbreeHWAccel*)((Scene*)instance->object)->hwaccel.data();
if (object->numTimeSegments > 1) return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; // we need to handle instances in procedural mode if instanced scene has motion blur
if (instance->mask & 0xFFFFFF80) return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; // we need to handle instances in procedural mode if high mask bits are set
if (object->numTimeSegments > 1) return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; // we need to handle instances in procedural mode if instanced scene has motion blur
if (instance->mask & 0xFFFFFF80) return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; // we need to handle instances in procedural mode if high mask bits are set
else if (instance->gsubtype == AccelSet::GTY_SUBTYPE_INSTANCE_QUATERNION)
return GEOMETRY_TYPE(RTHWIF_GEOMETRY_TYPE_INSTANCE,sizeof(GEOMETRY_INSTANCE_DESC)-sizeof(RTHWIF_GEOMETRY_INSTANCE_DESC));
else return RTHWIF_GEOMETRY_TYPE_INSTANCE;
return GEOMETRY_TYPE(ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_INSTANCE,sizeof(GEOMETRY_INSTANCE_DESC)-sizeof(ze_rtas_builder_instance_geometry_info_exp_t));
else return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_INSTANCE;
}
#else
case Geometry::GTY_INSTANCE_CHEAP : return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_INSTANCE_EXPENSIVE: return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR; break;
case Geometry::GTY_INSTANCE_CHEAP : return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
case Geometry::GTY_INSTANCE_EXPENSIVE: return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL; break;
#endif
default: assert(false); return RTHWIF_GEOMETRY_TYPE_AABBS_FPTR;
default: assert(false); return ZE_RTAS_BUILDER_GEOMETRY_TYPE_EXP_PROCEDURAL;
}
};
@@ -550,22 +550,12 @@ namespace embree
totalBytes += sizeof_RTHWIF_GEOMETRY(type);
}
const size_t numGeometries = scene->size();
/* fill geomdesc buffers */
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
const size_t geomDescrBytes = sizeof(RTHWIF_GEOMETRY_DESC*)*numGeometries;
RTHWIF_GEOMETRY_DESC** geomDescr = (RTHWIF_GEOMETRY_DESC**)sycl::aligned_alloc_shared(64,geomDescrBytes,gpu_device->getGPUDevice(),gpu_device->getGPUContext(),sycl::ext::oneapi::property::usm::device_read_only());
assert(geomDescr);
char *geomDescrData = (char*)sycl::aligned_alloc_shared(64,totalBytes,gpu_device->getGPUDevice(),gpu_device->getGPUContext(),sycl::ext::oneapi::property::usm::device_read_only());
assert(geomDescrData);
#else
std::vector<RTHWIF_GEOMETRY_DESC*> geomDescr(numGeometries);
/* fill geomdesc buffers */
std::vector<ze_rtas_builder_geometry_info_exp_t*> geomDescr(scene->size());
std::vector<char> geomDescrData(totalBytes);
#endif
size_t offset = 0;
for (size_t geomID=0; geomID<numGeometries; geomID++) // FIXME: slow if numGeometries is large
for (size_t geomID=0; geomID<scene->size(); geomID++)
{
geomDescr[geomID] = nullptr;
Geometry* geom = scene->get(geomID);
@@ -574,72 +564,45 @@ namespace embree
const GEOMETRY_TYPE type = getType(geomID);
align(offset,alignof_RTHWIF_GEOMETRY(type));
createGeometryDesc(&geomDescrData[offset],scene,scene->get(geomID),type);
geomDescr[geomID] = (RTHWIF_GEOMETRY_DESC*) &geomDescrData[offset];
geomDescr[geomID] = (ze_rtas_builder_geometry_info_exp_t*) &geomDescrData[offset];
offset += sizeof_RTHWIF_GEOMETRY(type);
#if !defined(EMBREE_SYCL_GPU_BVH_BUILDER)
assert(offset <= geomDescrData.size());
#endif
}
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
RTHWIF_PARALLEL_OPERATION parallelOperation = nullptr;
#else
RTHWIF_PARALLEL_OPERATION parallelOperation = rthwifNewParallelOperation();
#endif
ze_rtas_parallel_operation_exp_handle_t parallelOperation = nullptr;
err = zeRTASParallelOperationCreateExp(hDriver, &parallelOperation);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("parallel operation creation failed");
ze_rtas_device_exp_properties_t rtasProp = { ZE_STRUCTURE_TYPE_RTAS_DEVICE_EXP_PROPERTIES };
err = zeDeviceGetRTASPropertiesExp(hDevice, &rtasProp );
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("get rtas device properties failed");
/* estimate static accel size */
BBox1f time_range(0,1);
RTHWIF_AABB bounds;
RTHWIF_BUILD_ACCEL_ARGS args;
ze_rtas_aabb_exp_t bounds;
ze_rtas_builder_build_op_exp_desc_t args;
memset(&args,0,sizeof(args));
args.structBytes = sizeof(args);
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
args.geometries = (const RTHWIF_GEOMETRY_DESC**) geomDescr;
#else
args.geometries = (const RTHWIF_GEOMETRY_DESC**) geomDescr.data();
#endif
args.numGeometries = numGeometries;
args.accelBuffer = nullptr;
args.accelBufferBytes = 0;
args.scratchBuffer = nullptr;
args.scratchBufferBytes = 0;
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
args.quality = gpu_device->quality_flags == RTC_BUILD_QUALITY_LOW ? RTHWIF_BUILD_QUALITY_LOW : RTHWIF_BUILD_QUALITY_MEDIUM;
#else
args.quality = convertBuildQuality(scene->quality_flags);
#endif
args.flags = convertBuildFlags(scene->scene_flags);
args.parallelOperation = parallelOperation;
args.boundsOut = &bounds;
args.buildUserPtr = &time_range;
args.stype = ZE_STRUCTURE_TYPE_RTAS_BUILDER_BUILD_OP_EXP_DESC;
args.pNext = nullptr;
args.rtasFormat = rtasProp.rtasFormat;
args.buildQuality = convertBuildQuality(scene->quality_flags);
args.buildFlags = convertBuildFlags(scene->scene_flags,scene->quality_flags);
args.ppGeometries = (const ze_rtas_builder_geometry_info_exp_t**) geomDescr.data();
args.numGeometries = geomDescr.size();
#if defined(EMBREE_SYCL_ALLOC_DISPATCH_GLOBALS)
args.dispatchGlobalsPtr = dynamic_cast<DeviceGPU*>(scene->device)->dispatchGlobalsPtr;
#endif
RTHWIF_ACCEL_SIZE sizeTotal;
memset(&sizeTotal,0,sizeof(RTHWIF_ACCEL_SIZE));
sizeTotal.structBytes = sizeof(RTHWIF_ACCEL_SIZE);
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
RTHWIF_ERROR err = rthwifGetAccelSizeGPU(args,sizeTotal,&sycl_queue,gpu_device->verbose);
#else
RTHWIF_ERROR err = rthwifGetAccelSize(args,sizeTotal);
#endif
if (err != RTHWIF_ERROR_NONE)
ze_rtas_builder_exp_properties_t sizeTotal = { ZE_STRUCTURE_TYPE_RTAS_BUILDER_EXP_PROPERTIES };
err = zeRTASBuilderGetBuildPropertiesExp(hBuilder,&args,&sizeTotal);
if (err != ZE_RESULT_SUCCESS)
throw_RTCError(RTC_ERROR_UNKNOWN,"BVH size estimate failed");
/* allocate scratch buffer */
std::vector<char> scratchBuffer(sizeTotal.scratchBufferSizeBytes);
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
// === scratch buffer ===
char *scratchBuffer = (char*)sycl::aligned_alloc(64,sizeTotal.scratchBufferBytes,gpu_device->getGPUDevice(),gpu_device->getGPUContext(),gpu_device->verbose > 1 ? sycl::usm::alloc::shared : sycl::usm::alloc::device);
assert(scratchBuffer);
args.scratchBuffer = scratchBuffer;
args.scratchBufferBytes = sizeTotal.scratchBufferBytes;
#else
std::vector<char> scratchBuffer(sizeTotal.scratchBufferBytes);
args.scratchBuffer = scratchBuffer.data();
args.scratchBufferBytes = scratchBuffer.size();
#endif
size_t headerBytes = sizeof(EmbreeHWAccel) + std::max(1u,maxTimeSegments)*8;
align(headerBytes,128);
@@ -648,99 +611,78 @@ namespace embree
while (true)
{
/* estimate size of all mblur BVHs */
RTHWIF_ACCEL_SIZE size;
size.accelBufferExpectedBytes = maxTimeSegments*sizeTotal.accelBufferExpectedBytes;
size.accelBufferWorstCaseBytes = maxTimeSegments*sizeTotal.accelBufferWorstCaseBytes;
size_t bytes = headerBytes+size.accelBufferExpectedBytes;
ze_rtas_builder_exp_properties_t size = { ZE_STRUCTURE_TYPE_RTAS_BUILDER_EXP_PROPERTIES };
size.rtasBufferSizeBytesExpected = maxTimeSegments*sizeTotal.rtasBufferSizeBytesExpected;
size.rtasBufferSizeBytesMaxRequired = maxTimeSegments*sizeTotal.rtasBufferSizeBytesMaxRequired;
size_t bytes = headerBytes+size.rtasBufferSizeBytesExpected;
/* allocate BVH data */
if (accel.size() < bytes) accel.resize(bytes);
#if !defined(EMBREE_SYCL_GPU_BVH_BUILDER)
memset(accel.data(),0,accel.size()); // FIXME: not required
#endif
/* build BVH for each time segment */
for (uint32_t i=0; i<maxTimeSegments; i++)
{
const float t0 = float(i+0)/float(maxTimeSegments);
const float t1 = float(i+1)/float(maxTimeSegments);
time_range = BBox1f(t0,t1);
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
args.geometries = (const RTHWIF_GEOMETRY_DESC**) geomDescr;
#else
args.geometries = (const RTHWIF_GEOMETRY_DESC**) geomDescr.data();
#endif
args.numGeometries = numGeometries;
args.accelBuffer = accel.data() + headerBytes + i*sizeTotal.accelBufferExpectedBytes; // why + headerBytes?
args.accelBufferBytes = sizeTotal.accelBufferExpectedBytes;
bounds = { { INFINITY, INFINITY, INFINITY }, { -INFINITY, -INFINITY, -INFINITY } }; // why does the host initializes the bounds
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
err = rthwifPrefetchAccelGPU(args,&sycl_queue,gpu_device->verbose); //triggers additional USM transfers
#endif
void* accelBuffer = accel.data() + headerBytes + i*sizeTotal.rtasBufferSizeBytesExpected;
size_t accelBufferBytes = sizeTotal.rtasBufferSizeBytesExpected;
bounds = { { INFINITY, INFINITY, INFINITY }, { -INFINITY, -INFINITY, -INFINITY } };
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
err = rthwifBuildAccelGPU(args,&sycl_queue,gpu_device->verbose);
#else
err = rthwifBuildAccel(args);
#endif
if (args.parallelOperation) {
assert(err == RTHWIF_ERROR_PARALLEL_OPERATION);
uint32_t maxThreads = rthwifGetParallelOperationMaxConcurrency(parallelOperation);
parallel_for(maxThreads, [&](uint32_t) { err = rthwifJoinParallelOperation(parallelOperation); });
}
if (err == RTHWIF_ERROR_NONE) // added if
fullBounds.extend(*(BBox3f*) args.boundsOut);
if (err == RTHWIF_ERROR_RETRY)
err = zeRTASBuilderBuildExp(hBuilder,&args,
scratchBuffer.data(),scratchBuffer.size(),
accelBuffer, accelBufferBytes,
parallelOperation,
&time_range, &bounds, nullptr);
if (parallelOperation)
{
if (sizeTotal.accelBufferExpectedBytes == sizeTotal.accelBufferWorstCaseBytes)
assert(err == ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE);
ze_rtas_parallel_operation_exp_properties_t prop = { ZE_STRUCTURE_TYPE_RTAS_PARALLEL_OPERATION_EXP_PROPERTIES };
err = zeRTASParallelOperationGetPropertiesExp(parallelOperation,&prop);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("get max concurrency failed");
parallel_for(prop.maxConcurrency, [&](uint32_t) { err = zeRTASParallelOperationJoinExp(parallelOperation); });
}
fullBounds.extend(*(BBox3f*) &bounds);
if (err == ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY)
{
if (sizeTotal.rtasBufferSizeBytesExpected == sizeTotal.rtasBufferSizeBytesMaxRequired)
throw_RTCError(RTC_ERROR_UNKNOWN,"build error");
sizeTotal.accelBufferExpectedBytes = std::min(sizeTotal.accelBufferWorstCaseBytes,(size_t(1.2*sizeTotal.accelBufferExpectedBytes)+127)&-128);
sizeTotal.rtasBufferSizeBytesExpected = std::min(sizeTotal.rtasBufferSizeBytesMaxRequired,(size_t(1.2*sizeTotal.rtasBufferSizeBytesExpected)+127)&-128);
break;
}
if (err != RTHWIF_ERROR_NONE) break;
if (err != ZE_RESULT_SUCCESS) break;
}
if (err != RTHWIF_ERROR_RETRY) break;
if (err != ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY) break;
}
if (err != RTHWIF_ERROR_NONE)
if (err != ZE_RESULT_SUCCESS)
throw_RTCError(RTC_ERROR_UNKNOWN,"build error");
// === moving this to device code prevents USM down and up transfer of accel ===
/* destroy parallel operation */
err = zeRTASParallelOperationDestroyExp(parallelOperation);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("parallel operation destruction failed");
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
EmbreeHWAccel hwaccel;
hwaccel.numTimeSegments = maxTimeSegments;
for (size_t i=0; i<maxTimeSegments; i++)
hwaccel.AccelTable[i] = (char*)accel.data() + headerBytes + i*sizeTotal.accelBufferExpectedBytes;
sycl::event queue_event = sycl_queue.memcpy(accel.data(),&hwaccel,sizeof(EmbreeHWAccel));
queue_event.wait();
#else
/* destroy rtas builder again */
err = zeRTASBuilderDestroyExp(hBuilder);
if (err != ZE_RESULT_SUCCESS)
throw std::runtime_error("ze_rtas_builder destruction failed");
EmbreeHWAccel* hwaccel = (EmbreeHWAccel*) accel.data();
hwaccel->numTimeSegments = maxTimeSegments;
for (size_t i=0; i<maxTimeSegments; i++)
hwaccel->AccelTable[i] = (char*)hwaccel + headerBytes + i*sizeTotal.accelBufferExpectedBytes;
#endif
// =============================================================================
#if defined(EMBREE_SYCL_GPU_BVH_BUILDER)
sycl::free(geomDescr ,gpu_device->getGPUContext());
sycl::free(geomDescrData ,gpu_device->getGPUContext());
sycl::free(scratchBuffer ,gpu_device->getGPUContext());
#endif
hwaccel->AccelTable[i] = (char*)hwaccel + headerBytes + i*sizeTotal.rtasBufferSizeBytesExpected;
return fullBounds;
}
}
+1 -1
View File
@@ -63,7 +63,7 @@ namespace embree
typedef vector_t<char,AccelAllocator<char>> AccelBuffer;
void* rthwifInit(sycl::device device, sycl::context context);
void* zeRTASInitExp(sycl::device device, sycl::context context);
void rthwifCleanup(void* dispatchGlobalsPtr, sycl::context context);
+3 -3
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTCBufferType" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTCBufferType" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTCFormat \- specifies format of data in buffers
RTCFormat - specifies format of data in buffers
\f[R]
.fi
.SS SYNOPSIS
+9 -6
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTCCurveFlags" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTCCurveFlags" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTCCurveFlags \- per segment flags for curve geometry
RTCCurveFlags - per segment flags for curve geometry
\f[R]
.fi
.SS SYNOPSIS
@@ -14,11 +14,14 @@ RTCCurveFlags \- per segment flags for curve geometry
.nf
\f[C]
#include <embree4/rtcore.h>
enum RTCCurveFlags
{
RTC_CURVE_FLAG_NEIGHBOR_LEFT = (1 << 0),
RTC_CURVE_FLAG_NEIGHBOR_RIGHT = (1 << 1)
};
\f[R]
.fi
.PP
enum RTCCurveFlags { RTC_CURVE_FLAG_NEIGHBOR_LEFT = (1 << 0),
RTC_CURVE_FLAG_NEIGHBOR_RIGHT = (1 << 1) };
.SS DESCRIPTION
.PP
The RTCCurveFlags type is used for linear curves to determine if the
+230
View File
@@ -0,0 +1,230 @@
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTCFeatureFlags" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTCFeatureFlags - specifies features to enable
for ray queries
\f[R]
.fi
.SS SYNOPSIS
.IP
.nf
\f[C]
#include <embree4/rtcore_ray.h>
enum RTCFeatureFlags
{
RTC_FEATURE_FLAG_NONE = 0,
RTC_FEATURE_FLAG_MOTION_BLUR = 1 << 0,
RTC_FEATURE_FLAG_TRIANGLE = 1 << 1,
RTC_FEATURE_FLAG_QUAD = 1 << 2,
RTC_FEATURE_FLAG_GRID = 1 << 3,
RTC_FEATURE_FLAG_SUBDIVISION = 1 << 4,
RTC_FEATURE_FLAG_POINT = ... ,
RTC_FEATURE_FLAG_CURVES = ... ,
RTC_FEATURE_FLAG_CONE_LINEAR_CURVE = 1 << 5,
RTC_FEATURE_FLAG_ROUND_LINEAR_CURVE = 1 << 6,
RTC_FEATURE_FLAG_FLAT_LINEAR_CURVE = 1 << 7,
RTC_FEATURE_FLAG_ROUND_BEZIER_CURVE = 1 << 8,
RTC_FEATURE_FLAG_FLAT_BEZIER_CURVE = 1 << 9,
RTC_FEATURE_FLAG_NORMAL_ORIENTED_BEZIER_CURVE = 1 << 10,
RTC_FEATURE_FLAG_ROUND_BSPLINE_CURVE = 1 << 11,
RTC_FEATURE_FLAG_FLAT_BSPLINE_CURVE = 1 << 12,
RTC_FEATURE_FLAG_NORMAL_ORIENTED_BSPLINE_CURVE = 1 << 13,
RTC_FEATURE_FLAG_ROUND_HERMITE_CURVE = 1 << 14,
RTC_FEATURE_FLAG_FLAT_HERMITE_CURVE = 1 << 15,
RTC_FEATURE_FLAG_NORMAL_ORIENTED_HERMITE_CURVE = 1 << 16,
RTC_FEATURE_FLAG_ROUND_CATMULL_ROM_CURVE = 1 << 17,
RTC_FEATURE_FLAG_FLAT_CATMULL_ROM_CURVE = 1 << 18,
RTC_FEATURE_FLAG_NORMAL_ORIENTED_CATMULL_ROM_CURVE = 1 << 19,
RTC_FEATURE_FLAG_SPHERE_POINT = 1 << 20,
RTC_FEATURE_FLAG_DISC_POINT = 1 << 21,
RTC_FEATURE_FLAG_ORIENTED_DISC_POINT = 1 << 22,
RTC_FEATURE_FLAG_ROUND_CURVES = ... ,
RTC_FEATURE_FLAG_FLAT_CURVES = ... ,
RTC_FEATURE_FLAG_NORMAL_ORIENTED_CURVES = ... ,
RTC_FEATURE_FLAG_LINEAR_CURVES = ... ,
RTC_FEATURE_FLAG_BEZIER_CURVES = ... ,
RTC_FEATURE_FLAG_BSPLINE_CURVES = ... ,
RTC_FEATURE_FLAG_HERMITE_CURVES = ... ,
RTC_FEATURE_FLAG_INSTANCE = 1 << 23,
RTC_FEATURE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS = 1 << 24,
RTC_FEATURE_FLAG_FILTER_FUNCTION_IN_GEOMETRY = 1 << 25,
RTC_FEATURE_FLAG_FILTER_FUNCTION = ... ,
RTC_FEATURE_FLAG_USER_GEOMETRY_CALLBACK_IN_ARGUMENTS = 1 << 26,
RTC_FEATURE_FLAG_USER_GEOMETRY_CALLBACK_IN_GEOMETRY = 1 << 27,
RTC_FEATURE_FLAG_USER_GEOMETRY = ... ,
RTC_FEATURE_FLAG_32_BIT_RAY_MASK = 1 << 28,
RTC_FEATURE_FLAG_ALL = 0xffffffff
};
\f[R]
.fi
.SS DESCRIPTION
.PP
The \f[C]RTCFeatureFlags\f[R] enum specify a bit mask to enable specific
ray tracing features for ray query operations.
The feature flags are passed to the \f[C]rtcIntersect1/4/8/16\f[R] and
\f[C]rtcOccluded1/4/8/16\f[R] functions through the
\f[C]RTCIntersectArguments\f[R] and \f[C]RTCOccludedArguments\f[R]
structures.
Only a ray tracing feature whose bit is enabled in the feature mask can
get used.
If a feature bit is not set, the behaviour is undefined, thus the
feature may work or not.
To enable multiple features the respective features have to get combined
using a bitwise \f[C]OR\f[R] operation.
.PP
The purpose of feature flags is to reduce code size on the GPU by
enabling just the features required to render the scene.
On the CPU there is no need to use feature flags, and the default of all
features enabled (\f[C]RTC_FEATURE_FLAG_ALL\f[R]) can just be kept.
.PP
The following features can get enabled using feature flags:
.IP \[bu] 2
RTC_FEATURE_FLAG_MOTION_BLUR: Enables motion blur for all geometry
types.
.IP \[bu] 2
RTC_FEATURE_FLAG_TRIANGLE: Enables triangle geometries
(RTC_GEOMETRY_TYPE_TRIANGLE).
.IP \[bu] 2
RTC_FEATURE_FLAG_QUAD: Enables quad geometries (RTC_GEOMETRY_TYPE_QUAD).
.IP \[bu] 2
RTC_FEATURE_FLAG_GRID: Enables grid geometries (RTC_GEOMETRY_TYPE_GRID).
.IP \[bu] 2
RTC_FEATURE_FLAG_SUBDIVISION: Enables subdivision geometries
(RTC_GEOMETRY_TYPE_SUBDIVISION).
.IP \[bu] 2
RTC_FEATURE_FLAG_POINT: Enables all point geometry types
(RTC_GEOMETRY_TYPE_XXX_POINT)
.IP \[bu] 2
RTC_FEATURE_FLAG_CURVES: Enables all curve geometry types
(RTC_GEOMETRY_TYPE_XXX_YYY_CURVE)
.IP \[bu] 2
RTC_FEATURE_FLAG_ROUND_CURVES: Enables all round curves
(RTC_GEOMETRY_TYPE_ROUND_XXX_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_FLAT_CURVES: Enables all flat curves
(RTC_GEOMETRY_TYPE_FLAT_XXX_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_NORMAL_ORIENTED_CURVES: Enables all normal oriented
curves (RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_XXX_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_LINEAR_CURVES: Enables all linear curves
(RTC_GEOMETRY_TYPE_XXX_LINEAR_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_BEZIER_CURVES: Enables all B\['e]zier curves
(RTC_GEOMETRY_TYPE_XXX_BEZIER_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_BSPLINE_CURVES: Enables all B-spline curves
(RTC_GEOMETRY_TYPE_XXX_BSPLINE_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_HERMITE_CURVES: Enables all Hermite curves
(RTC_GEOMETRY_TYPE_XXX_HERMITE_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_CONE_LINEAR_CURVE: Enables cone geometry type
(RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_ROUND_LINEAR_CURVE: Enables round linear curves
(RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_FLAT_LINEAR_CURVE: Enables flat linear curves
(RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_ROUND_BEZIER_CURVE: Enables round B\['e]zier curves
(RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_FLAT_BEZIER_CURVE: Enables flat B\['e]zier curves
(RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_NORMAL_ORIENTED_BEZIER_CURVE: Enables normal oriented
B\['e]zier curves (RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_ROUND_BSPLINE_CURVE: Enables round B-spline curves
(RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_FLAT_BSPLINE_CURVE: Enables flat B-spline curves
(RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_NORMAL_ORIENTED_BSPLINE_CURVE: Enables normal oriented
B-spline curves (RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_ROUND_HERMITE_CURVE: Enables round Hermite curves
(RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_FLAT_HERMITE_CURVE: Enables flat Hermite curves
(RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_NORMAL_ORIENTED_HERMITE_CURVE: Enables normal oriented
Hermite curves (RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_ROUND_CATMULL_ROM_CURVE: Enables round Catmull Rom
curves (RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_FLAT_CATMULL_ROM_CURVE: Enables flat Catmull Rom curves
(RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_NORMAL_ORIENTED_CATMULL_ROM_CURVE: Enables normal
oriented Catmull Rom curves
(RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE).
.IP \[bu] 2
RTC_FEATURE_FLAG_SPHERE_POINT: Enables sphere geometry type
(RTC_GEOMETRY_TYPE_SPHERE_POINT).
.IP \[bu] 2
RTC_FEATURE_FLAG_DISC_POINT: Enables disc geometry type
(RTC_GEOMETRY_TYPE_DISC_POINT).
.IP \[bu] 2
RTC_FEATURE_FLAG_ORIENTED_DISC_POINT: Enables oriented disc geometry
types (RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT).
.IP \[bu] 2
RTC_FEATURE_FLAG_INSTANCE: Enables instance geometries
(RTC_GEOMETRY_TYPE_INSTANCE).
.IP \[bu] 2
RTC_FEATURE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS: Enables filter functions
passed through intersect arguments.
.IP \[bu] 2
RTC_FEATURE_FLAG_FILTER_FUNCTION_IN_GEOMETRY: Enable filter functions
passed through geometry.
.IP \[bu] 2
RTC_FEATURE_FLAG_FILTER_FUNCTION: Enables filter functions (argument and
geometry version).
.IP \[bu] 2
RTC_FEATURE_FLAG_USER_GEOMETRY_CALLBACK_IN_ARGUMENTS: Enables
RTC_GEOMETRY_TYPE_USER with function pointer passed through intersect
arguments.
.IP \[bu] 2
RTC_FEATURE_FLAG_USER_GEOMETRY_CALLBACK_IN_GEOMETRY: Enables
RTC_GEOMETRY_TYPE_USER with function pointer passed through geometry
object.
.IP \[bu] 2
RTC_FEATURE_FLAG_USER_GEOMETRY: Enables RTC_GEOMETRY_TYPE_USER
geometries (both argument and geometry callback versions).
.IP \[bu] 2
RTC_FEATURE_FLAG_32_BIT_RAY_MASK: Enables full 32 bit ray masks.
If not used, only the lower 7 bits in the ray mask are handled
correctly.
.IP \[bu] 2
RTC_FEATURE_FLAG_ALL: Enables all features (default).
.SS EXIT STATUS
.SS SEE ALSO
.PP
[rtcIntersect1], [rtcIntersect4/8/16], [rtcOccluded1],
[rtcOccluded4/8/16],
+4 -5
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTCFormat" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTCFormat" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTCFormat \- specifies format of data in buffers
RTCFormat - specifies format of data in buffers
\f[R]
.fi
.SS SYNOPSIS
@@ -46,10 +46,9 @@ enum RTCFormat
RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR,
RTC_FORMAT_GRID,
};
\f[R]
.fi
.PP
};
.SS DESCRIPTION
.PP
The \f[C]RTFormat\f[R] structure defines the data format stored in data
+5 -5
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTCHit" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTCHit" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTCHit \- single hit structure
RTCHit - single hit structure
\f[R]
.fi
.SS SYNOPSIS
@@ -48,8 +48,8 @@ hit structure in structure of array (SOA) layout for hit packets of size
4 (\f[C]RTCHit4\f[R] type), size 8 (\f[C]RTCHit8\f[R] type), and size 16
(\f[C]RTCHit16\f[R] type).
The header additionally defines an \f[C]RTCHitNt\f[R] template for hit
packets of an arbitrary compile\-time size.
packets of an arbitrary compile-time size.
.SS EXIT STATUS
.SS SEE ALSO
.PP
[RTCRay], [Multi\-Level Instancing]
[RTCRay], [Multi-Level Instancing]
+4 -4
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTCHitN" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTCHitN" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTCHitN \- hit packet of runtime size
RTCHitN - hit packet of runtime size
\f[R]
.fi
.SS SYNOPSIS
@@ -45,7 +45,7 @@ type, or implement one general code path that uses the
These helper functions get a pointer to the hit packet (\f[C]hit\f[R]
argument), the packet size (\f[C]N\f[R] argument), and returns a
reference to a component (e.g.\ x component of \f[C]Ng\f[R]) of the the
i\-th hit of the packet (\f[C]i\f[R] argument).
i-th hit of the packet (\f[C]i\f[R] argument).
.SS EXIT STATUS
.SS SEE ALSO
.PP
+3 -3
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTCQuaternionDecomposition" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTCQuaternionDecomposition" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTCQuaternionDecomposition \- structure that represents a quaternion
RTCQuaternionDecomposition - structure that represents a quaternion
decomposition of an affine transformation
\f[R]
.fi
+5 -8
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTCRay" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTCRay" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTCRay \- single ray structure
RTCRay - single ray structure
\f[R]
.fi
.SS SYNOPSIS
@@ -48,8 +48,6 @@ considered valid.
The ray segment must be in the range [0,\[u2006]\[if]], thus ranges that
start behind the ray origin are not allowed, but ranges can reach to
infinity.
For rays inside a ray stream, \f[C]tfar\f[R] < \f[C]tnear\f[R]
identifies an inactive ray.
.PP
The ray further contains a motion blur time in the range [0,\[u2006]1]
(\f[C]time\f[R] member), a ray mask (\f[C]mask\f[R] member), a ray ID
@@ -57,15 +55,14 @@ The ray further contains a motion blur time in the range [0,\[u2006]1]
The ray mask can be used to mask out some geometries for some rays (see
\f[C]rtcSetGeometryMask\f[R] for more details).
The ray ID can be used to identify a ray inside a callback function,
even if the order of rays inside a ray packet or stream has changed.
The ray flags are reserved.
even if the order of rays inside a ray packet has changed.
.PP
The \f[C]embree4/rtcore_ray.h\f[R] header additionally defines the same
ray structure in structure of array (SOA) layout for API functions
accepting ray packets of size 4 (\f[C]RTCRay4\f[R] type), size 8
(\f[C]RTCRay8\f[R] type), and size 16 (\f[C]RTCRay16\f[R] type).
The header additionally defines an \f[C]RTCRayNt\f[R] template for ray
packets of an arbitrary compile\-time size.
packets of an arbitrary compile-time size.
.SS EXIT STATUS
.SS SEE ALSO
.PP
+5 -5
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTCRay" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTCRay" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTCRayHit \- combined single ray/hit structure
RTCRayHit - combined single ray/hit structure
\f[R]
.fi
.SS SYNOPSIS
@@ -25,7 +25,7 @@ struct RTCORE_ALIGN(16) RTCRayHit
.SS DESCRIPTION
.PP
The \f[C]RTCRayHit\f[R] structure is used as input for the
\f[C]rtcIntersect\f[R]\-type functions and stores the ray to intersect
\f[C]rtcIntersect\f[R]-type functions and stores the ray to intersect
and some hit fields that hold the intersection result afterwards.
.PP
The \f[C]embree4/rtcore_ray.h\f[R] header additionally defines the same
@@ -33,7 +33,7 @@ ray/hit structure in structure of array (SOA) layout for API functions
accepting ray packets of size 4 (\f[C]RTCRayHit4\f[R] type), size 8
(\f[C]RTCRayHit8\f[R] type), and size 16 (\f[C]RTCRayHit16\f[R] type).
The header additionally defines an \f[C]RTCRayHitNt\f[R] template to
generate ray/hit packets of an arbitrary compile\-time size.
generate ray/hit packets of an arbitrary compile-time size.
.SS EXIT STATUS
.SS SEE ALSO
.PP
+3 -3
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTCRayHitN" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTCRayHitN" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTCRayHitN \- combined ray/hit packet of runtime size
RTCRayHitN - combined ray/hit packet of runtime size
\f[R]
.fi
.SS SYNOPSIS
+4 -4
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTCRayN" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTCRayN" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTCRayN \- ray packet of runtime size
RTCRayN - ray packet of runtime size
\f[R]
.fi
.SS SYNOPSIS
@@ -49,7 +49,7 @@ components.
.PP
These helper functions get a pointer to the ray packet (\f[C]ray\f[R]
argument), the packet size (\f[C]N\f[R] argument), and returns a
reference to a component (e.g.\ x\-component of origin) of the the i\-th
reference to a component (e.g.\ x-component of origin) of the the i-th
ray of the packet (\f[C]i\f[R] argument).
.SS EXIT STATUS
.SS SEE ALSO
+47 -47
View File
@@ -1,55 +1,55 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTC_GEOMETRY_TYPE_*_CURVE" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTC_GEOMETRY_TYPE_*_CURVE" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE \-
RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE -
flat curve geometry with linear basis
RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE \-
RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE -
flat curve geometry with cubic B\['e]zier basis
RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE \-
flat curve geometry with cubic B\-spline basis
RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE -
flat curve geometry with cubic B-spline basis
RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE \-
RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE -
flat curve geometry with cubic Hermite basis
RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE \-
flat curve geometry with Catmull\-Rom basis
RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE -
flat curve geometry with Catmull-Rom basis
RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE \-
RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE -
flat normal oriented curve geometry with cubic B\['e]zier basis
RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE \-
flat normal oriented curve geometry with cubic B\-spline basis
RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE -
flat normal oriented curve geometry with cubic B-spline basis
RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE \-
RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE -
flat normal oriented curve geometry with cubic Hermite basis
RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE \-
flat normal oriented curve geometry with Catmull\-Rom basis
RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE -
flat normal oriented curve geometry with Catmull-Rom basis
RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE \-
capped cone curve geometry with linear basis \- discontinuous at edge boundaries
RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE -
capped cone curve geometry with linear basis - discontinuous at edge boundaries
RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE \-
RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE -
capped cone curve geometry with linear basis and spherical ending
RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE \-
RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE -
swept surface curve geometry with cubic B\['e]zier basis
RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE \-
swept surface curve geometry with cubic B\-spline basis
RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE -
swept surface curve geometry with cubic B-spline basis
RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE \-
RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE -
swept surface curve geometry with cubic Hermite basis
RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE \-
swept surface curve geometry with Catmull\-Rom basis
RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE -
swept surface curve geometry with Catmull-Rom basis
\f[R]
.fi
.SS SYNOPSIS
@@ -78,7 +78,7 @@ rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE);
.SS DESCRIPTION
.PP
Curves with per vertex radii are supported with linear, cubic
B\['e]zier, cubic B\-spline, and cubic Hermite bases.
B\['e]zier, cubic B-spline, and cubic Hermite bases.
Such curve geometries are created by passing
\f[C]RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE\f[R],
\f[C]RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE\f[R],
@@ -109,7 +109,7 @@ See \f[C]rtcSetGeometryBuffer\f[R] and
\f[C]rtcSetSharedGeometryBuffer\f[R] for more details on how to set
buffers.
.PP
The index buffer contains an array of 32\-bit indices
The index buffer contains an array of 32-bit indices
(\f[C]RTC_FORMAT_UINT\f[R] format), each pointing to the first control
vertex in the vertex buffer, but also to the first tangent in the
tangent buffer, and first normal in the normal buffer if these buffers
@@ -133,7 +133,7 @@ For the linear basis the indices point to the first of 2 consecutive
control points in the vertex buffer.
The first control point is the start and the second control point the
end of the line segment.
When constructing hair strands in this basis, the end\-point can be
When constructing hair strands in this basis, the end-point can be
shared with the start of the next line segment.
.PP
For the linear basis the user optionally can provide a flags buffer of
@@ -143,8 +143,8 @@ and/or right neighbor segment (\f[C]RTC_CURVE_FLAG_NEIGHBOR_RIGHT\f[R]
flags) exist (see [RTCCurveFlags]).
If this buffer is not set, than the left/right neighbor bits are
automatically calculated base on the index buffer (left segment exists
if segment(id\-1)+1 == segment(id) and right segment exists if
segment(id+1)\-1 == segment(id)).
if segment(id-1)+1 == segment(id) and right segment exists if
segment(id+1)-1 == segment(id)).
.PP
A left neighbor segment is assumed to end at the start vertex of the
current segment, and to start at the previous vertex in the vertex
@@ -165,11 +165,11 @@ control point represents the start point of the curve, and the 4th
control point the end point of the curve.
The B\['e]zier basis is interpolating, thus the curve does go exactly
through the first and fourth control vertex.
.SS B\-spline Basis
.SS B-spline Basis
.PP
For the cubic B\-spline basis the indices point to the first of 4
For the cubic B-spline basis the indices point to the first of 4
consecutive control points in the vertex buffer.
These control points make up a cardinal cubic B\-spline (implicit
These control points make up a cardinal cubic B-spline (implicit
equidistant knot vector).
This basis is not interpolating, thus the curve does in general not go
through any of the control points directly.
@@ -177,7 +177,7 @@ A big advantage of this basis is that 3 control points can be shared for
two continuous neighboring curve segments, e.g.\ the curves
(p0,p1,p2,p3) and (p1,p2,p3,p4) are C1 continuous.
This feature makes this basis a good choice to construct continuous
multi\-segment curves, as memory consumption can be kept minimal.
multi-segment curves, as memory consumption can be kept minimal.
.SS Hermite Basis
.PP
For the cubic Hermite basis the indices point to the first of 2
@@ -189,15 +189,15 @@ second control point, and the first order derivative at the begin and
end matches exactly the value specified in the tangent buffer.
When connecting two segments continuously, the end point and tangent of
the previous segment can be shared.
Different versions of Catmull\-Rom splines can be easily constructed
Different versions of Catmull-Rom splines can be easily constructed
using the Hermite basis, by calculating a proper tangent buffer from the
control points.
.SS Catmull\-Rom Basis
.SS Catmull-Rom Basis
.PP
For the Catmull\-Rom basis the indices point to the first of 4
For the Catmull-Rom basis the indices point to the first of 4
consecutive control points in the vertex buffer.
This basis goes through p1 and p2, with tangents (p2\-p0)/2 and
(p3\-p1)/2.
This basis goes through p1 and p2, with tangents (p2-p0)/2 and
(p3-p1)/2.
.SS Flat Curves
.PP
The \f[C]RTC_GEOMETRY_TYPE_FLAT_*\f[R] flat mode is a fast mode designed
@@ -223,7 +223,7 @@ the provided vertex spline, whose half width approximately follows the
provided radius spline, and whose normal orientation approximately
follows the provided normal spline.
.PP
To intersect the normal oriented curve, we perform a newton\-raphson
To intersect the normal oriented curve, we perform a newton-raphson
style intersection of a ray with a tensor product surface of a linear
basis (perpendicular to the curve) and cubic B\['e]zier basis (along the
curve).
@@ -248,7 +248,7 @@ surface is rendered for the curve, which is more expensive but allows
closeup views.
.PP
For the linear basis the round mode renders a cone that tangentially
touches a start\-sphere and end\-sphere.
touches a start-sphere and end-sphere.
The start sphere is rendered when no previous segments is indicated by
the neighbor bits.
The end sphere is always rendered but parts that lie inside the next
@@ -264,20 +264,20 @@ As a limitation, the radius of the curve has to be smaller than the
curvature radius of the curve at each location on the curve.
.PP
The intersection with the curve segment stores the parametric hit
location along the curve segment as u\-coordinate (range 0 to +1).
location along the curve segment as u-coordinate (range 0 to +1).
.PP
For flat curves, the v\-coordinate is set to the normalized distance in
the range \-1 to +1.
For normal oriented curves the v\-coordinate is in the range 0 to 1.
For the linear basis and in round mode the v\-coordinate is set to zero.
For flat curves, the v-coordinate is set to the normalized distance in
the range -1 to +1.
For normal oriented curves the v-coordinate is in the range 0 to 1.
For the linear basis and in round mode the v-coordinate is set to zero.
.PP
In flat mode, the geometry normal \f[C]Ng\f[R] is set to the tangent of
the curve at the hit location.
In round mode and for normal oriented curves, the geometry normal
\f[C]Ng\f[R] is set to the non\-normalized geometric normal of the
\f[C]Ng\f[R] is set to the non-normalized geometric normal of the
surface.
.PP
For multi\-segment motion blur, the number of time steps must be first
For multi-segment motion blur, the number of time steps must be first
specified using the \f[C]rtcSetGeometryTimeStepCount\f[R] call.
Then a vertex buffer for each time step can be set using different
buffer slots, and all these buffers must have the same stride and size.
+7 -7
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTC_GEOMETRY_TYPE_GRID" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTC_GEOMETRY_TYPE_GRID" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTC_GEOMETRY_TYPE_GRID \- grid geometry type
RTC_GEOMETRY_TYPE_GRID - grid geometry type
\f[R]
.fi
.SS SYNOPSIS
@@ -58,20 +58,20 @@ The \f[C]width\f[R] and \f[C]height\f[R] members specify the number of
vertices in u and v direction, e.g.\ setting both \f[C]width\f[R] and
\f[C]height\f[R] to 3 sets up a 3\[tmu]3 vertex grid.
The maximum allowed \f[C]width\f[R] and \f[C]height\f[R] is 32767.
The \f[C]startVertexID\f[R] specifies the ID of the top\-left vertex in
The \f[C]startVertexID\f[R] specifies the ID of the top-left vertex in
the vertex grid, while the \f[C]stride\f[R] parameter specifies a stride
(in number of vertices) used to step to the next row.
.PP
A vertex grid of dimensions \f[C]width\f[R] and \f[C]height\f[R] is
treated as a \f[C](width\-1)\f[R] x \f[C](height\-1)\f[R] grid of
\f[C]quads\f[R] (triangle\-pairs), with the same shared edge handling as
treated as a \f[C](width-1)\f[R] x \f[C](height-1)\f[R] grid of
\f[C]quads\f[R] (triangle-pairs), with the same shared edge handling as
for regular quad meshes.
However, the \f[C]u\f[R]/\f[C]v\f[R] coordinates have the uniform range
\f[C][0..1]\f[R] for an entire vertex grid.
The \f[C]u\f[R] direction follows the \f[C]width\f[R] of the grid while
the \f[C]v\f[R] direction the \f[C]height\f[R].
.PP
For multi\-segment motion blur, the number of time steps must be first
For multi-segment motion blur, the number of time steps must be first
specified using the \f[C]rtcSetGeometryTimeStepCount\f[R] call.
Then a vertex buffer for each time step can be set using different
buffer slots, and all these buffers must have the same stride and size.
+11 -12
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTC_GEOMETRY_TYPE_INSTANCE" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTC_GEOMETRY_TYPE_INSTANCE" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTC_GEOMETRY_TYPE_INSTANCE \- instance geometry type
RTC_GEOMETRY_TYPE_INSTANCE - instance geometry type
\f[R]
.fi
.SS SYNOPSIS
@@ -27,11 +27,10 @@ As the instanced scene is stored only a single time, even if instanced
to multiple locations, this feature can be used to create very complex
scenes with small memory footprint.
.PP
Embree supports both single\-level instancing and multi\-level
instancing.
Embree supports both single-level instancing and multi-level instancing.
The maximum instance nesting depth is
\f[C]RTC_MAX_INSTANCE_LEVEL_COUNT\f[R]; it can be configured at
compile\-time using the constant
compile-time using the constant
\f[C]EMBREE_MAX_INSTANCE_LEVEL_COUNT\f[R].
Users should adapt this constant to their needs: instances nested any
deeper are silently ignored in release mode, and cause assertions in
@@ -46,26 +45,26 @@ function.
.PP
Please note that \f[C]rtcCommitScene\f[R] on the instanced scene should
be called first, followed by \f[C]rtcCommitGeometry\f[R] on the
instance, followed by \f[C]rtcCommitScene\f[R] for the top\-level scene
instance, followed by \f[C]rtcCommitScene\f[R] for the top-level scene
containing the instance.
.PP
If a ray hits the instance, the \f[C]geomID\f[R] and \f[C]primID\f[R]
members of the hit are set to the geometry ID and primitive ID of the
hit primitive in the instanced scene, and the \f[C]instID\f[R] member of
the hit is set to the geometry ID of the instance in the top\-level
the hit is set to the geometry ID of the instance in the top-level
scene.
.PP
The instancing scheme can also be implemented using user geometries.
To achieve this, the user geometry code should set the \f[C]instID\f[R]
member of the ray query context to the geometry ID of the instance,
then trace the transformed ray, and finally set the \f[C]instID\f[R]
field of the ray query context again to \-1.
member of the ray query context to the geometry ID of the instance, then
trace the transformed ray, and finally set the \f[C]instID\f[R] field of
the ray query context again to -1.
The \f[C]instID\f[R] field is copied automatically by each primitive
intersector into the \f[C]instID\f[R] field of the hit structure when
the primitive is hit.
See the [User Geometry] tutorial for an example.
.PP
For multi\-segment motion blur, the number of time steps must be first
For multi-segment motion blur, the number of time steps must be first
specified using the \f[C]rtcSetGeometryTimeStepCount\f[R] function.
Then a transformation for each time step can be specified using the
\f[C]rtcSetGeometryTransform\f[R] function.
+10 -10
View File
@@ -1,19 +1,19 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTC_GEOMETRY_TYPE_*_POINT" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTC_GEOMETRY_TYPE_*_POINT" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTC_GEOMETRY_TYPE_SPHERE_POINT \-
RTC_GEOMETRY_TYPE_SPHERE_POINT -
point geometry spheres
RTC_GEOMETRY_TYPE_DISC_POINT \-
point geometry with ray\-oriented discs
RTC_GEOMETRY_TYPE_DISC_POINT -
point geometry with ray-oriented discs
RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT \-
point geometry with normal\-oriented discs
RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT -
point geometry with normal-oriented discs
\f[R]
.fi
.SS SYNOPSIS
@@ -29,8 +29,8 @@ rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT);
.fi
.SS DESCRIPTION
.PP
Points with per vertex radii are supported with sphere, ray\-oriented
discs, and normal\-oriented discs geometric representations.
Points with per vertex radii are supported with sphere, ray-oriented
discs, and normal-oriented discs geometric representations.
Such point geometries are created by passing
\f[C]RTC_GEOMETRY_TYPE_SPHERE_POINT\f[R],
\f[C]RTC_GEOMETRY_TYPE_DISC_POINT\f[R], or
@@ -69,7 +69,7 @@ In this mode the point is rendered as a normal oriented disc.
For all point types, only the hit distance and geometry normal is
returned as hit information, u and v are set to zero.
.PP
For multi\-segment motion blur, the number of time steps must be first
For multi-segment motion blur, the number of time steps must be first
specified using the \f[C]rtcSetGeometryTimeStepCount\f[R] call.
Then a vertex buffer for each time step can be set using different
buffer slots, and all these buffers must have the same stride and size.
+11 -11
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTC_GEOMETRY_TYPE_QUAD" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTC_GEOMETRY_TYPE_QUAD" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTC_GEOMETRY_TYPE_QUAD \- quad geometry type
RTC_GEOMETRY_TYPE_QUAD - quad geometry type
\f[R]
.fi
.SS SYNOPSIS
@@ -29,7 +29,7 @@ a vertex buffer (\f[C]RTC_BUFFER_TYPE_VERTEX\f[R] type).
See \f[C]rtcSetGeometryBuffer\f[R] and
\f[C]rtcSetSharedGeometryBuffer\f[R] for more details on how to set
buffers.
The index buffer contains an array of four 32\-bit indices per quad
The index buffer contains an array of four 32-bit indices per quad
(\f[C]RTC_FORMAT_UINT4\f[R] format), and the number of primitives is
inferred from the size of that buffer.
The vertex buffer contains an array of single precision \f[C]x\f[R],
@@ -41,29 +41,29 @@ The vertex buffer can be at most 16 GB large.
A quad is internally handled as a pair of two triangles
\f[C]v0,v1,v3\f[R] and \f[C]v2,v3,v1\f[R], with the
\f[C]u\[aq]\f[R]/\f[C]v\[aq]\f[R] coordinates of the second triangle
corrected by \f[C]u = 1\-u\[aq]\f[R] and \f[C]v = 1\-v\[aq]\f[R] to
corrected by \f[C]u = 1-u\[aq]\f[R] and \f[C]v = 1-v\[aq]\f[R] to
produce a quad parametrization where \f[C]u\f[R] and \f[C]v\f[R] are in
the range 0 to 1.
Thus the parametrization of a quad uses the first vertex \f[C]p0\f[R] as
base point, and the vector \f[C]p1 \- p0\f[R] as \f[C]u\f[R]\-direction,
and \f[C]p3 \- p0\f[R] as v\-direction.
base point, and the vector \f[C]p1 - p0\f[R] as \f[C]u\f[R]-direction,
and \f[C]p3 - p0\f[R] as v-direction.
Thus vertex attributes \f[C]t0,t1,t2,t3\f[R] can be bilinearly
interpolated over the quadrilateral the following way:
.IP
.nf
\f[C]
t_uv = (1\-v)((1\-u)*t0 + u*t1) + v*((1\-u)*t3 + u*t2)
t_uv = (1-v)((1-u)*t0 + u*t1) + v*((1-u)*t3 + u*t2)
\f[R]
.fi
.PP
Mixed triangle/quad meshes are supported by encoding a triangle as a
quad, which can be achieved by replicating the last triangle vertex
(\f[C]v0,v1,v2\f[R] \-> \f[C]v0,v1,v2,v2\f[R]).
(\f[C]v0,v1,v2\f[R] -> \f[C]v0,v1,v2,v2\f[R]).
This way the second triangle is a line (which can never get hit), and
the parametrization of the first triangle is compatible with the
standard triangle parametrization.
.PP
A quad whose vertices are laid out counter\-clockwise has its geometry
A quad whose vertices are laid out counter-clockwise has its geometry
normal pointing upwards outside the front face, like illustrated in the
following picture.
.IP
@@ -72,7 +72,7 @@ following picture.
\f[R]
.fi
.PP
For multi\-segment motion blur, the number of time steps must be first
For multi-segment motion blur, the number of time steps must be first
specified using the \f[C]rtcSetGeometryTimeStepCount\f[R] call.
Then a vertex buffer for each time step can be set using different
buffer slots, and all these buffers must have the same stride and size.
+28 -28
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTC_GEOMETRY_TYPE_SUBDIVISION" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTC_GEOMETRY_TYPE_SUBDIVISION" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTC_GEOMETRY_TYPE_SUBDIVISION \- subdivision geometry type
RTC_GEOMETRY_TYPE_SUBDIVISION - subdivision geometry type
\f[R]
.fi
.SS SYNOPSIS
@@ -21,9 +21,9 @@ RTCGeometry geometry =
.fi
.SS DESCRIPTION
.PP
Catmull\-Clark subdivision meshes are supported, including support for
edge creases, vertex creases, holes, non\-manifold geometry, and
face\-varying interpolation.
Catmull-Clark subdivision meshes are supported, including support for
edge creases, vertex creases, holes, non-manifold geometry, and
face-varying interpolation.
The number of vertices per face can be in the range of 3 to 15 vertices
(triangles, quadrilateral, pentagons, etc).
.PP
@@ -40,7 +40,7 @@ The face buffer (\f[C]RTC_BUFFER_TYPE_FACE\f[R] type and
of each face (3 to 15), and the number of faces is inferred from the
size of this buffer.
The index buffer (\f[C]RTC_BUFFER_TYPE_INDEX\f[R] type) contains
multiple (3 to 15) 32\-bit vertex indices (\f[C]RTC_FORMAT_UINT\f[R]
multiple (3 to 15) 32-bit vertex indices (\f[C]RTC_FORMAT_UINT\f[R]
format) for each face, and the number of edges is inferred from the size
of this buffer.
The vertex buffer (\f[C]RTC_BUFFER_TYPE_VERTEX\f[R] type) stores an
@@ -50,7 +50,7 @@ of vertices is inferred from the size of this buffer.
.PP
Optionally, the application may set additional index buffers using
different buffer slots if multiple topologies are required for
face\-varying interpolation.
face-varying interpolation.
The standard vertex buffers (\f[C]RTC_BUFFER_TYPE_VERTEX\f[R]) are
always bound to the geometry topology (topology 0) thus use
\f[C]RTC_BUFFER_TYPE_INDEX\f[R] with buffer slot 0.
@@ -58,9 +58,9 @@ User vertex data interpolation may use different topologies as described
later.
.PP
Optionally, the application can set up the hole buffer
(\f[C]RTC_BUFFER_TYPE_HOLE\f[R]) which contains an array of 32\-bit
(\f[C]RTC_BUFFER_TYPE_HOLE\f[R]) which contains an array of 32-bit
indices (\f[C]RTC_FORMAT_UINT\f[R] format) of faces that should be
considered non\-existing in all topologies.
considered non-existing in all topologies.
The number of holes is inferred from the size of this buffer.
.PP
Optionally, the application can fill the level buffer
@@ -85,7 +85,7 @@ Optionally, the application can fill the sparse edge crease buffers to
make edges appear sharper.
The edge crease index buffer
(\f[C]RTC_BUFFER_TYPE_EDGE_CREASE_INDEX\f[R]) contains an array of pairs
of 32\-bit vertex indices (\f[C]RTC_FORMAT_UINT2\f[R] format) that
of 32-bit vertex indices (\f[C]RTC_FORMAT_UINT2\f[R] format) that
specify unoriented edges in the geometry topology.
The edge crease weight buffer
(\f[C]RTC_BUFFER_TYPE_EDGE_CREASE_WEIGHT\f[R]) stores for each of these
@@ -108,7 +108,7 @@ Optionally, the application can fill the sparse vertex crease buffers to
make vertices appear sharper.
The vertex crease index buffer
(\f[C]RTC_BUFFER_TYPE_VERTEX_CREASE_INDEX\f[R]), contains an array of
32\-bit vertex indices (\f[C]RTC_FORMAT_UINT\f[R] format) to specify a
32-bit vertex indices (\f[C]RTC_FORMAT_UINT\f[R] format) to specify a
set of vertices from the geometry topology.
The vertex crease weight buffer
(\f[C]RTC_BUFFER_TYPE_VERTEX_CREASE_WEIGHT\f[R]) specifies for each of
@@ -129,7 +129,7 @@ Subdivision modes can be used to force linear interpolation for parts of
the subdivision mesh; see \f[C]rtcSetGeometrySubdivisionMode\f[R] for
more details.
.PP
For multi\-segment motion blur, the number of time steps must be first
For multi-segment motion blur, the number of time steps must be first
specified using the \f[C]rtcSetGeometryTimeStepCount\f[R] call.
Then a vertex buffer for each time step can be set using different
buffer slots, and all these buffers have to have the same stride and
@@ -140,18 +140,18 @@ subdivision surfaces.
.SS Parametrization
.PP
The parametrization for subdivision faces is different for
quadrilaterals and non\-quadrilateral faces.
quadrilaterals and non-quadrilateral faces.
.PP
The parametrization of a quadrilateral face uses the first vertex
\f[C]p0\f[R] as base point, and the vector \f[C]p1 \- p0\f[R] as
u\-direction and \f[C]p3 \- p0\f[R] as v\-direction.
\f[C]p0\f[R] as base point, and the vector \f[C]p1 - p0\f[R] as
u-direction and \f[C]p3 - p0\f[R] as v-direction.
.PP
The parametrization for all other face types (with number of vertices
not equal 4), have a special parametrization where the subpatch ID
\f[C]n\f[R] (of the \f[C]n\f[R]\-th quadrilateral that would be obtained
\f[C]n\f[R] (of the \f[C]n\f[R]-th quadrilateral that would be obtained
by a single subdivision step) and the local hit location inside this
quadrilateral are encoded in the UV coordinates.
The following code extracts the sub\-patch ID \f[C]i\f[R] and local UVs
The following code extracts the sub-patch ID \f[C]i\f[R] and local UVs
of this subpatch:
.IP
.nf
@@ -159,28 +159,28 @@ of this subpatch:
unsigned int l = floorf(0.5f*U);
unsigned int h = floorf(0.5f*V);
unsigned int i = 4*h+l;
float u = 2.0f*fracf(0.5f*U)\-0.5f;
float v = 2.0f*fracf(0.5f*V)\-0.5f;
float u = 2.0f*fracf(0.5f*U)-0.5f;
float v = 2.0f*fracf(0.5f*V)-0.5f;
\f[R]
.fi
.PP
This encoding allows local subpatch UVs to be in the range
\f[C][\-0.5,1.5[\f[R] thus negative subpatch UVs can be passed to
\f[C][-0.5,1.5[\f[R] thus negative subpatch UVs can be passed to
\f[C]rtcInterpolate\f[R] to sample subpatches slightly out of bounds.
This can be useful to calculate derivatives using finite differences if
required.
The encoding further has the property that one can just move the value
\f[C]u\f[R] (or \f[C]v\f[R]) on a subpatch by adding \f[C]du\f[R] (or
\f[C]dv\f[R]) to the special UV encoding as long as it does not fall out
of the \f[C][\-0.5,1.5[\f[R] range.
of the \f[C][-0.5,1.5[\f[R] range.
.PP
To smoothly interpolate vertex attributes over the subdivision surface
we recommend using the \f[C]rtcInterpolate\f[R] function, which will
apply the standard subdivision rules for interpolation and automatically
takes care of the special UV encoding for non\-quadrilaterals.
.SS Face\-Varying Data
takes care of the special UV encoding for non-quadrilaterals.
.SS Face-Varying Data
.PP
Face\-varying interpolation is supported through multiple topologies per
Face-varying interpolation is supported through multiple topologies per
subdivision mesh and binding such topologies to vertex attribute buffers
to interpolate.
This way, texture coordinates may use a different topology with
@@ -197,9 +197,9 @@ interpolation using the \f[C]rtcSetGeometryVertexAttributeTopology\f[R]
call.
.PP
The face buffer (\f[C]RTC_BUFFER_TYPE_FACE\f[R] type) is shared between
all topologies, which means that the \f[C]n\f[R]\-th primitive always
has the same number of vertices (e.g.\ being a triangle or a quad) for
each topology.
all topologies, which means that the \f[C]n\f[R]-th primitive always has
the same number of vertices (e.g.\ being a triangle or a quad) for each
topology.
However, the indices of the topologies themselves may be different.
.SS EXIT STATUS
.PP
+10 -10
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTC_GEOMETRY_TYPE_TRIANGLE" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTC_GEOMETRY_TYPE_TRIANGLE" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTC_GEOMETRY_TYPE_TRIANGLE \- triangle geometry type
RTC_GEOMETRY_TYPE_TRIANGLE - triangle geometry type
\f[R]
.fi
.SS SYNOPSIS
@@ -30,7 +30,7 @@ setting a vertex buffer (\f[C]RTC_BUFFER_TYPE_VERTEX\f[R] type).
See \f[C]rtcSetGeometryBuffer\f[R] and
\f[C]rtcSetSharedGeometryBuffer\f[R] for more details on how to set
buffers.
The index buffer must contain an array of three 32\-bit indices per
The index buffer must contain an array of three 32-bit indices per
triangle (\f[C]RTC_FORMAT_UINT3\f[R] format) and the number of
primitives is inferred from the size of that buffer.
The vertex buffer must contain an array of single precision \f[C]x\f[R],
@@ -40,19 +40,19 @@ inferred from the size of that buffer.
The vertex buffer can be at most 16 GB large.
.PP
The parametrization of a triangle uses the first vertex \f[C]p0\f[R] as
base point, the vector \f[C]p1 \- p0\f[R] as u\-direction and the vector
\f[C]p2 \- p0\f[R] as v\-direction.
base point, the vector \f[C]p1 - p0\f[R] as u-direction and the vector
\f[C]p2 - p0\f[R] as v-direction.
Thus vertex attributes \f[C]t0,t1,t2\f[R] can be linearly interpolated
over the triangle the following way:
.IP
.nf
\f[C]
t_uv = (1\-u\-v)*t0 + u*t1 + v*t2
= t0 + u*(t1\-t0) + v*(t2\-t0)
t_uv = (1-u-v)*t0 + u*t1 + v*t2
= t0 + u*(t1-t0) + v*(t2-t0)
\f[R]
.fi
.PP
A triangle whose vertices are laid out counter\-clockwise has its
A triangle whose vertices are laid out counter-clockwise has its
geometry normal pointing upwards outside the front face, like
illustrated in the following picture:
.IP
@@ -61,7 +61,7 @@ illustrated in the following picture:
\f[R]
.fi
.PP
For multi\-segment motion blur, the number of time steps must be first
For multi-segment motion blur, the number of time steps must be first
specified using the \f[C]rtcSetGeometryTimeStepCount\f[R] call.
Then a vertex buffer for each time step can be set using different
buffer slots, and all these buffers have to have the same stride and
+10 -10
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "RTC_GEOMETRY_TYPE_USER" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "RTC_GEOMETRY_TYPE_USER" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
RTC_GEOMETRY_TYPE_USER \- user geometry type
RTC_GEOMETRY_TYPE_USER - user geometry type
\f[R]
.fi
.SS SYNOPSIS
@@ -21,19 +21,19 @@ RTCGeometry geometry =
.fi
.SS DESCRIPTION
.PP
User\-defined geometries contain a number of user\-defined primitives,
User-defined geometries contain a number of user-defined primitives,
just like triangle meshes contain multiple triangles.
The shape of the user\-defined primitives is specified through
registered callback functions, which enable extending Embree with
arbitrary types of primitives.
The shape of the user-defined primitives is specified through registered
callback functions, which enable extending Embree with arbitrary types
of primitives.
.PP
User\-defined geometries are created by passing
User-defined geometries are created by passing
\f[C]RTC_GEOMETRY_TYPE_USER\f[R] to the \f[C]rtcNewGeometry\f[R]
function call.
One has to set the number of primitives (see
\f[C]rtcSetGeometryUserPrimitiveCount\f[R]), a user data pointer (see
\f[C]rtcSetGeometryUserData\f[R]), a bounding function closure (see
\f[C]rtcSetGeometryBoundsFunction\f[R]), as well as user\-defined
\f[C]rtcSetGeometryBoundsFunction\f[R]), as well as user-defined
intersect (see \f[C]rtcSetGeometryIntersectFunction\f[R]) and occluded
(see \f[C]rtcSetGeometryOccludedFunction\f[R]) callback functions.
The bounding function is used to query the bounds of all time steps of a
@@ -66,7 +66,7 @@ bounds are empty, thus bounds have lower>upper in at least one
dimension.
.PP
See tutorial [User Geometry] for an example of how to use the
user\-defined geometries.
user-defined geometries.
.SS EXIT STATUS
.PP
On failure \f[C]NULL\f[R] is returned and an error code is set that can
+5 -5
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "rtcAttachGeometry" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "rtcAttachGeometry" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
rtcAttachGeometry \- attaches a geometry to the scene
rtcAttachGeometry - attaches a geometry to the scene
\f[R]
.fi
.SS SYNOPSIS
@@ -32,7 +32,7 @@ A geometry can get attached to multiple scenes.
The geometry ID is unique for the scene, and is used to identify the
geometry when hit by a ray during ray queries.
.PP
This function is thread\-safe, thus multiple threads can attach
This function is thread-safe, thus multiple threads can attach
geometries to a scene in parallel.
.PP
The geometry IDs are assigned sequentially, starting from 0, as long as
@@ -44,7 +44,7 @@ compact range of IDs.
.PP
These rules allow the application to manage a dynamic array to
efficiently map from geometry IDs to its own geometry representation.
Alternatively, the application can also use per\-geometry user data to
Alternatively, the application can also use per-geometry user data to
map to its geometry representation.
See \f[C]rtcSetGeometryUserData\f[R] and
\f[C]rtcGetGeometryUserData\f[R] for more information.
+8 -8
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "rtcAttachGeometryByID" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "rtcAttachGeometryByID" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
rtcAttachGeometryByID \- attaches a geometry to the scene
rtcAttachGeometryByID - attaches a geometry to the scene
using a specified geometry ID
\f[R]
.fi
@@ -32,17 +32,17 @@ geometry.
All geometries attached to a scene are defined to be included inside the
scene.
A geometry can get attached to multiple scenes.
The passed user\-defined geometry ID is used to identify the geometry
The passed user-defined geometry ID is used to identify the geometry
when hit by a ray during ray queries.
Using this function, it is possible to share the same IDs to refer to
geometries inside the application and Embree.
.PP
This function is thread\-safe, thus multiple threads can attach
This function is thread-safe, thus multiple threads can attach
geometries to a scene in parallel.
.PP
The user\-provided geometry ID must be unused in the scene, otherwise
the creation of the geometry will fail.
Further, the user\-provided geometry IDs should be compact, as Embree
The user-provided geometry ID must be unused in the scene, otherwise the
creation of the geometry will fail.
Further, the user-provided geometry IDs should be compact, as Embree
internally creates a vector which size is equal to the largest geometry
ID used.
Creating very large geometry IDs for small scenes would thus cause a
+7 -7
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "rtcBuildBVH" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "rtcBuildBVH" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
rtcBuildBVH \- builds a BVH
rtcBuildBVH - builds a BVH
\f[R]
.fi
.SS SYNOPSIS
@@ -107,7 +107,7 @@ void* rtcBuildBVH(
.SS DESCRIPTION
.PP
The \f[C]rtcBuildBVH\f[R] function can be used to build a BVH in a
user\-defined format over arbitrary primitives.
user-defined format over arbitrary primitives.
All arguments to the function are provided through the
\f[C]RTCBuildArguments\f[R] structure.
The first member of that structure must be set to the size of the
@@ -121,12 +121,12 @@ The \f[C]rtcBuildBVH\f[R] function gets passed the BVH to build
member), the capacity of that array (\f[C]primitiveArrayCapacity\f[R]
member), the number of primitives stored inside the array
(\f[C]primitiveCount\f[R] member), callback function pointers, and a
user\-defined pointer (\f[C]userPtr\f[R] member) that is passed to all
user-defined pointer (\f[C]userPtr\f[R] member) that is passed to all
callback functions when invoked.
The \f[C]primitives\f[R] array can be freed by the application after the
BVH is built.
All callback functions are typically called from multiple threads, thus
their implementation must be thread\-safe.
their implementation must be thread-safe.
.PP
Four callback functions must be registered, which are invoked during
build to create BVH nodes (\f[C]createNode\f[R] member), to set the
@@ -153,7 +153,7 @@ have (\f[C]maxDepth\f[R] member), the block size for the SAH heuristic
estimated costs of one traversal step and one primitive intersection
(\f[C]traversalCost\f[R] and \f[C]intersectionCost\f[R] members).
When enabling the \f[C]RTC_BUILD_FLAG_DYNAMIC\f[R] build flags
(\f[C]buildFlags\f[R] member), re\-build performance for dynamic scenes
(\f[C]buildFlags\f[R] member), re-build performance for dynamic scenes
is improved at the cost of higher memory requirements.
.PP
To spatially split primitives in high quality mode, the builder needs
+3 -3
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "rtcCollide" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "rtcCollide" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
rtcCollide \- intersects one BVH with another
rtcCollide - intersects one BVH with another
\f[R]
.fi
.SS SYNOPSIS
+3 -3
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "rtcCommitGeometry" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "rtcCommitGeometry" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
rtcCommitGeometry \- commits geometry changes
rtcCommitGeometry - commits geometry changes
\f[R]
.fi
.SS SYNOPSIS
+3 -3
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "rtcCommitScene" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "rtcCommitScene" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
rtcCommitScene \- commits scene changes
rtcCommitScene - commits scene changes
\f[R]
.fi
.SS SYNOPSIS
+4 -4
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "rtcDetachGeometry" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "rtcDetachGeometry" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
rtcDetachGeometry \- detaches a geometry from the scene
rtcDetachGeometry - detaches a geometry from the scene
\f[R]
.fi
.SS SYNOPSIS
@@ -24,7 +24,7 @@ This function detaches a geometry identified by its geometry ID
(\f[C]geomID\f[R] argument) from a scene (\f[C]scene\f[R] argument).
When detached, the geometry is no longer contained in the scene.
.PP
This function is thread\-safe, thus multiple threads can detach
This function is thread-safe, thus multiple threads can detach
geometries from a scene at the same time.
.SS EXIT STATUS
.PP
+3 -3
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "rtcDisableGeometry" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "rtcDisableGeometry" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
rtcDisableGeometry \- disables the geometry
rtcDisableGeometry - disables the geometry
\f[R]
.fi
.SS SYNOPSIS
+3 -3
View File
@@ -1,12 +1,12 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "rtcEnableGeometry" "3" "" "" "Embree Ray Tracing Kernels 3"
.TH "rtcEnableGeometry" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
rtcEnableGeometry \- enables the geometry
rtcEnableGeometry - enables the geometry
\f[R]
.fi
.SS SYNOPSIS
+66
View File
@@ -0,0 +1,66 @@
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "rtcForwardIntersect1" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
rtcForwardIntersect1 - forwards a single ray to new scene
from user geometry callback
\f[R]
.fi
.SS SYNOPSIS
.IP
.nf
\f[C]
#include <embree4/rtcore.h>
void rtcForwardIntersect1(
const struct RTCIntersectFunctionNArguments* args,
RTCScene scene,
struct RTCRay* ray,
unsigned int instID
);
\f[R]
.fi
.SS DESCRIPTION
.PP
The \f[C]rtcForwardIntersect1\f[R] function forwards the traversal of a
transformed ray (\f[C]ray\f[R] argument) into a scene (\f[C]scene\f[R]
argument) from a user geometry callback.
The function can only get invoked from a user geometry callback for a
ray traversal initiated with the \f[C]rtcIntersect1\f[R] function.
The callback arguments structure of the callback invokation has to get
passed to the ray forwarding (\f[C]args\f[R] argument).
The user geometry callback should instantly terminate after invoking the
\f[C]rtcForwardIntersect1\f[R] function.
.PP
Only the ray origin and ray direction members of the ray argument are
used for forwarding, all additional ray properties are inherited from
the initial ray traversal invokation of \f[C]rtcIntersect1\f[R].
.PP
The implementation of the \f[C]rtcForwardIntersect1\f[R] function
recursively continues the ray traversal into the specified scene and
pushes the provided instance ID (\f[C]instID\f[R] argument) to the
instance ID stack.
Hit information is updated into the ray hit structure passed to the
original \f[C]rtcIntersect1\f[R] invokation.
.PP
This function can get used to implement user defined instancing using
user geometries, e.g.\ by transforming the ray in a special way, and/or
selecting between different scenes to instantiate.
.PP
When using Embree on the CPU it is possible to recursively invoke
\f[C]rtcIntersect1\f[R] directly from a user geometry callback.
However, when SYCL is used, recursively tracing rays is not directly
supported, and the \f[C]rtcForwardIntersect1\f[R] function must be used.
.PP
The ray structure must be aligned to 16 bytes.
.SS EXIT STATUS
.PP
For performance reasons this function does not do any error checks, thus
will not set any error flags on failure.
.SS SEE ALSO
.PP
[rtcIntersect1], [RTCRay]
+87
View File
@@ -0,0 +1,87 @@
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "rtcForwardIntersect4/8/16" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
rtcForwardIntersect4/8/16 - forwards a ray packet to new scene
from user geometry callback
\f[R]
.fi
.SS SYNOPSIS
.IP
.nf
\f[C]
#include <embree4/rtcore.h>
void rtcForwardIntersect4(
void int* valid,
const struct RTCIntersectFunctionNArguments* args,
RTCScene scene,
struct RTCRay4* ray,
unsigned int instID
);
void rtcForwardIntersect4(
void int* valid,
const struct RTCIntersectFunctionNArguments* args,
RTCScene scene,
struct RTCRay4* ray,
unsigned int instID
);
void rtcForwardIntersect16(
void int* valid,
const struct RTCIntersectFunctionNArguments* args,
RTCScene scene,
struct RTCRay16* ray,
unsigned int instID
);
\f[R]
.fi
.SS DESCRIPTION
.PP
The \f[C]rtcForwardIntersect4/8/16\f[R] functions forward the traversal
of a transformed ray packet (\f[C]ray\f[R] argument) into a scene
(\f[C]scene\f[R] argument) from a user geometry callback.
The function can only get invoked from a user geometry callback for a
ray traversal initiated with the \f[C]rtcIntersect4/8/16\f[R] function.
The callback arguments structure of the callback invokation has to get
passed to the ray forwarding (\f[C]args\f[R] argument).
The user geometry callback should instantly terminate after invoking the
\f[C]rtcForwardIntersect4/8/16\f[R] function.
.PP
Only the ray origin and ray direction members of the ray argument are
used for forwarding, all additional ray properties are inherited from
the initial ray traversal invokation of \f[C]rtcIntersect4/8/16\f[R].
.PP
The implementation of the \f[C]rtcForwardIntersect4/8/16\f[R] function
recursively continues the ray traversal into the specified scene and
pushes the provided instance ID (\f[C]instID\f[R] argument) to the
instance ID stack.
Hit information is updated into the ray hit structure passed to the
original \f[C]rtcIntersect4/8/16\f[R] invokation.
.PP
This function can get used to implement user defined instancing using
user geometries, e.g.\ by transforming the ray in a special way, and/or
selecting between different scenes to instantiate.
.PP
When using Embree on the CPU it is possible to recursively invoke
\f[C]rtcIntersect4/8/16\f[R] directly from a user geometry callback.
However, when SYCL is used, recursively tracing rays is not directly
supported, and the \f[C]rtcForwardIntersect4/8/16\f[R] function must be
used.
.PP
For \f[C]rtcForwardIntersect4\f[R] the ray packet must be aligned to 16
bytes, for \f[C]rtcForwardIntersect8\f[R] the alignment must be 32
bytes, and for \f[C]rtcForwardIntersect16\f[R] the alignment must be 64
bytes.
.SS EXIT STATUS
.PP
For performance reasons this function does not do any error checks, thus
will not set any error flags on failure.
.SS SEE ALSO
.PP
[rtcIntersect4/8/16]
+66
View File
@@ -0,0 +1,66 @@
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "rtcForwardOccluded1" "3" "" "" "Embree Ray Tracing Kernels 4"
.hy
.SS NAME
.IP
.nf
\f[C]
rtcForwardOccluded1 - forwards a single ray to new scene
from user geometry callback
\f[R]
.fi
.SS SYNOPSIS
.IP
.nf
\f[C]
#include <embree4/rtcore.h>
void rtcForwardOccluded1(
const struct RTCOccludedFunctionNArguments* args,
RTCScene scene,
struct RTCRay* ray,
unsigned int instID
);
\f[R]
.fi
.SS DESCRIPTION
.PP
The \f[C]rtcForwardOccluded1\f[R] function forwards the traversal of a
transformed ray (\f[C]ray\f[R] argument) into a scene (\f[C]scene\f[R]
argument) from a user geometry callback.
The function can only get invoked from a user geometry callback for a
ray traversal initiated with the \f[C]rtcOccluded1\f[R] function.
The callback arguments structure of the callback invokation has to get
passed to the ray forwarding (\f[C]args\f[R] argument).
The user geometry callback should instantly terminate after invoking the
\f[C]rtcForwardOccluded1\f[R] function.
.PP
Only the ray origin and ray direction members of the ray argument are
used for forwarding, all additional ray properties are inherited from
the initial ray traversal invokation of \f[C]rtcOccluded1\f[R].
.PP
The implementation of the \f[C]rtcForwardOccluded1\f[R] function
recursively continues the ray traversal into the specified scene and
pushes the provided instance ID (\f[C]instID\f[R] argument) to the
instance ID stack.
Hit information is updated into the ray structure passed to the original
\f[C]rtcOccluded1\f[R] invokation.
.PP
This function can get used to implement user defined instancing using
user geometries, e.g.\ by transforming the ray in a special way, and/or
selecting between different scenes to instantiate.
.PP
When using Embree on the CPU it is possible to recursively invoke
\f[C]rtcOccluded1\f[R] directly from a user geometry callback.
However, when SYCL is used, recursively tracing rays is not directly
supported, and the \f[C]rtcForwardOccluded1\f[R] function must be used.
.PP
The ray structure must be aligned to 16 bytes.
.SS EXIT STATUS
.PP
For performance reasons this function does not do any error checks, thus
will not set any error flags on failure.
.SS SEE ALSO
.PP
[rtcOccluded1], [RTCRay]

Some files were not shown because too many files have changed in this diff Show More